javascript函数跟变量的声明、作用域这些概念网上都已经讲烂了。

这里写个博客,也相当于做个笔记。

变量声明

首先看个例子:

var globalVar = "gv";
function fc() {
console.log(globalVar);
var globalVar = "lv";
console.log(globalVar);
}
fc();

这个例子输出:

undefined

"lv"

为什么会输出这样的信息呢?

  javascript中变量声明会被预编译(自动调整)到所在代码作用域的顶部。 原来那段代码将会变成仅仅给变量赋值的操作。

上面的代码也就变成了下面的代码。

var globalVar = "gv";
function fc() {
var globalVar;
console.log(globalVar);
globalVar = "lv";
console.log(globalVar);
}
fc();
函数体内的   var globalVar = "lv";  这段代码被拆分成了2个部分。
--- 第1个部分就是我们要说的var globalVar,也就是变量声明,它被预编译到所在作用域的顶部;第2部分就是给变量赋值操作。
因此,第一个console输出的是undefined(因为globalVar仅仅声明了,为赋值,声明的变量javascript会给个undefined值) ;
第二个输出的是“lv”,因为此时globalVar已经被赋值了。 现在你可能会问。 我在函数fc之外已经定义了1个全局变量globalVar, 并且fc函数内部我也仅仅再次声明了这个变量, 并没有赋值, 照理说应该会使用函数外的全局变量的。 为什么执行的时候却找不到呢。 照理说应该会输出 "gv" "lv" 的。 这是因为globalVar在函数体内通过关键字var声明了,这表示这个globalVar在函数体是是一个局部变量。
如果我们将函数体内的globalVar前面的var关键字去掉:
var globalVar = "gv";
function fc() {
console.log(globalVar);
globalVar = "lv";
console.log(globalVar);
}
fc();

那么就会输出"gv"  "lv"。  因为函数体内的globalVar是一个全局变量。

作用域

javascript的作用域有2种。1个全局作用域,1个是函数作用域。 它没有块级作用域
全局作用域很好理解, 在代码中任何地方都能访问到的对象拥有全局作用域。
函数作用域就是在函数体内声明的一些函数,变量。 那么什么是块级作用域呢?
首先,来看个例子:
for(var i = 0; i < 5; i ++) {
var j = i;
}
console.log(i +', ' + j); switch(j) {
case 4: var k = 2; break;
default: var k = 3;
} console.log(k); if(i >= 5) {
var l = 6;
} console.log(l);
这里例子最后都会输出i,j,k,l的值, 值分别为5、4、2、6。 
说明了javascript是没有块级作用域。for、if、switch等关键字包括起来的{}这段代码就是所谓的块级作用域。
结果还是可以找出这4个变量, 并没有报错。
没有块级作用域,那么以上代码就是在全局作用域内定义并执行的。
本文一开始讲了变量声明的预编译。 预编译的作用范围其实是在作用域里才会起作用的。
于是。 块级作用域的例子进行预编译之后会是如下样子:
var i,j,k,l;

for(i = 0; i < 5; i ++) {
j = i;
}
console.log(i +', ' + j); switch(j) {
case 4: k = 2; break;
default: k = 3;
} console.log(k); if(i >= 5) {
l = 6;
} console.log(l);

函数声明

函数声明同样会被提取到当前作用域内的最前面。

console.log(func);
function func() {
console.log(1);
}

以上这段代码就会输出func这个函数的定义代码。 而不是undefined。

函数声明与变量声明的优先级

如果我一段代码中既有函数声明,又有变量声明,那么谁的优先级更高呢?

          答案是:变量声明。

即变量声明的优先级比函数声明的优先级要更高

但是这个定义是有条件的。

function func() {
console.log(1);
}
var func = 1;
console.log(func);
var func = 1;
function func() {
console.log(1);
}
console.log(func);

这两段代码都会输出 1 。 说明的变量声明的优先级比函数声明高,也就是说变量声明会覆盖函数声明。

下面再来看个例子:

var func;
function func() {
console.log(1);
}
console.log(func);

这里会输出func函数的定义,不会输出undefined。

因为这段代码中变量声明并未进行赋值操作, 仅仅声明了1个变量。

因此最准确的说法是:  进行赋值操作的变量声明的优先级比函数声明要高。

总结

javascript是一门非常奇葩的语言,里面的坑其实蛮多的。

但是只要掌握好基础,其实也还好吧。

参考资料:

http://www.cnblogs.com/snandy/archive/2012/03/01/2373237.html

http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html

浅谈javascript函数,变量声明及作用域的更多相关文章

  1. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  2. [转载]浅谈JavaScript函数重载

     原文地址:浅谈JavaScript函数重载 作者:ChessZhang 上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试).面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都 ...

  3. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  4. 浅谈javascript函数执行过程

    javascript函数执行过程: 1. 为函数创建一个执行环境 2. 复制函数的 [[scopes]] 属性中的对象构建起执行环境的作用链域 3. 创建函数活动对象并推入执行环境作用链域的前端 4. ...

  5. [转]浅谈javascript函数劫持

    转自:Ph4nt0m Security Team 这么多年了,现在学习依然还是有很多收货,向前辈致敬.转载一方面是自己存档一份,另一方面是让更多喜欢安全的人一同学习. ================ ...

  6. 浅谈C语言变量声明的解析

    C语言本身提供了一种不甚明确的变量声明方式——基于使用的声明,如int *a,本质上是声明了*a的类型为int,所以得到了a的类型为指向int的指针.对于简单类型,这样声明并不会对代码产生多大的阅读障 ...

  7. 浅谈javascript中变量作用域和内存(2)

    1.无块级作用域 javascript没有块级作用域,这会让其他程序员在理解js代码上很痛苦.在其他很多语言,比如C,大括号括起来的代码块都有自己的作用域 举个例子 if(true) { var na ...

  8. 浅谈javascript的变量作用域

    1.变量遵循先声明再使用. console.log(b); b=123; 代码运行结果: Uncaught ReferenceError: b is not defined 2.方法内定义的局部变量外 ...

  9. 浅谈javascript中变量作用域和内存(1)

    先理解两个概念:基本类型和引用类型的值 1.基本类型和引用类型的值 (1)定义: 基本类型:指简单的数据段,比如按值访问的js五种基本数据类型undefined.null.boolean.number ...

随机推荐

  1. [Erlang34]erlang.mk的源码阅读1-入门makefile

    通过erlang.mk项目,掌握基本的makefile语法,可以自己定制makefile. 1. makefile 基本规则: 1. 所有的源文件没有被编译过,则对各个源文件进行编译并进行链接,生成最 ...

  2. NET npoi 合并单元值处理

    获取sheet中存在合并单元格总数,循环绑定值 // 得到一个sheet中有多少个合并单元格 int sheetMergeCount = sheet.NumMergedRegions; ; i < ...

  3. phonegap3.0+HTMLl5 开发 ipad app 总结

    忙碌了一段时间,终于完成了手上的这个ipad上的app ,app是用phonegap+ jquery mobile 开发的,不是用原生的objective c开发的.因为app有许多chart的渲染, ...

  4. Lock的await/singal 和 Object的wait/notify 的区别

    在使用Lock之前,我们都使用Object 的wait和notify实现同步的.举例来说,一个producer和consumer,consumer发现没有东西了,等待,produer生成东西了,唤醒. ...

  5. 【OCP-12c】CUUG 071题库考试原题及答案解析(13)

    13.(6-7) choose twoWhich two statements are true regarding operators used with subqueries? (Choose t ...

  6. leecode刷题(17)-- 实现StrStr

    leecode刷题(17)-- 实现StrStr 实现StrStr 描述: 实现 strStr() 函数. 给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串 ...

  7. 洛谷P3676 小清新数据结构题(动态点分治+树链剖分)

    传送门 感觉这题做下来心态有点崩……$RMQ$求$LCA$没有树剖快我可以理解为是常数太大……然而我明明用了自以为不会退化的点分然而为什么比会退化的点分跑得反而更慢啊啊啊啊~~~ 先膜一波zsy大佬 ...

  8. LOJ#3085. 「GXOI / GZOI2019」特技飞行(KDtree+坐标系变换)

    题面 传送门 前置芝士 请确定您会曼哈顿距离和切比雪夫距离之间的转换,以及\(KDtree\)对切比雪夫距离的操作 题解 我们发现\(AB\)和\(C\)没有任何关系,所以关于\(C\)可以直接暴力数 ...

  9. BZOJ4766: 文艺计算姬(Prufer序列)

    题面 传送门 题解 结,结论题? 答案就是\(n^{m-1}m^{n-1}\) 我们考虑它的\(Prufer\)序列,最后剩下的两个点肯定是一个在左边一个在右边,设左边\(n\)个点,右边\(m\)个 ...

  10. jzoj1792

    #include<bits/stdc++.h> using namespace std; long long a[100010],m,n; int main(){ scanf(" ...