JavaScript 关于声明变量和函数的优先级

dxcqcv · 2014年05月16日 · 最后由 yanguango 回复于 2014年05月16日 · 3819 次阅读
var a = 1;
function b() {
    a = 10;
    return;
    function a (){};
}
b();
alert(a);

运行结果是 1,为什么?同名函数 a 替代了 a 的赋值吗?

function 内部的 local 变量的作用域仅仅限于 function 内部,也就是说在外部的便利 a 只能在外部修改。

#1 楼 @lgn21st 但我这个在函数内的 a 没有 var,是全局的,如果我把下面的 function a(){};去掉,结果将会是 10,这就是我困惑的地方

#2 楼 @dxcqcv 看走眼了...... 我也困惑了。

存在function a() {}时,函数 b 里的 a 实际上只是函数 b 范围内的局部变量,它的值是不会影响到函数 b 外部的 a 的值的。把function a() {}删除后,函数 b 内部的 a 就是函数 b 外部的那个。 下面的代码应该就是上面代码的等价形式。

var a = 1;
function b() {
  var a;
  a = 10;
  return;
  a = function() {};
}
b();
alert(a);

Update: 上面我的说法有误,上面我提供的代码并不完全与题主的代码等价。真正的原因是 JavaScript 在 解析时就会处理 function a() {}这种形式的函数定义,可以参考这里。在执行a=10时,函数 b 的内部作用域里已经存在了一个名字为a的函数,即a是函数 b 内的局部变量,所以a=10不会影响到函数 b 外部的变量a

#4 楼 @edgar_wang_cn 为什么函数 a 会让全局 a 变成局部呢?

#5 楼 @dxcqcv 你看下我补充的代码。

因为a=10这句修改的其实是function a不是全局 a

执行到 b 时,会先定义 a 这个 local 的方法,所以外边的 a 根本没被访问到

#4 楼 @edgar_wang_cn 正解。 javascript 的 hoisting 特性:函数内部定义的变量就像全部都在顶部定义(不包括赋值)。如

function f() {
   console.log(a);
   var a = "local";
}

f() 会输出“undefined", 而不是产生”a is not defined"的错误。

function a() {}这种类型的函数定义相当于var a = function() {}, 所以会有 @edgar_wang_cn代码所示的等价代码。

javascript 函数也是对象,和数字,字符串等一样,不存在声明函数和声明变量的优先级问题,这和 ruby 不同。

预解析的时候,采用声明式 (declaration) 的函数定义会被预先读取,所以在函数 b 之内,首先声明了函数 a,然后再a=10,这时候 a 是一个在函数 b 这个 scope 内的局部变量,所以不会修改外面 global 的 a

如果改成表达式 (expression) 的函数定义就不一样了

var a = 1;
function b() {
    a = 10;
    return;
    a = function (){};
}
b();
console.log(a);

js 里面 function a() 这种写法有个天坑,就是会影响前面的代码!你可以看 coffeescript 生成的代码里,都不会这样写的

嗯,谢谢大家,补充一个小疑问,在 b 里,a 成为局部函数了,那么 a=10;怎么不报错?

#12 楼 @dxcqcv 这就是动态类型,一个变量的类型不是固定的,你给他什么他就是什么,就像 Ruby 里面

a = lambda{1}
a = 1
需要 登录 后方可回复, 如果你还没有账号请 注册新账号