js作用链的疑惑

(function(){
    console.log(bar);
    console.log(baz);
    
    bar = 20;
    console.log(window.bar);
    console.log(bar);
    
    function baz(){
        console.log("baz");
    }
    
})()

当代码执行到"console.log(bar);"的时候,会去AO中查找"bar"。函数中的"bar"并没有通过var关键字声明,所有不会被存放在AO中。但是为什么不会去global上面去找呢?网上说这种变量是,只是给Global添加了一个属性,并不在VO中,求解释

阅读 1.6k
2 个回答

题主问题:但是为什么不会去global上面去找呢?
回答:因为第一次执行到

console.log(bar);

这个的时候,

bar = 20;

这个还没执行,所以上面访问会报错
这句代码执行后,才会在全局创建一个 bar,作为全局对象的属性存在,然后你才可以访问.
题主可以看下下面测试,这个,第一次执行,把上面代码注释掉,就不会报错,接着执行第二次,不注释代码,也不会报错,这是因为第一次执行的时候前面那句 bar = 20 执行过了;

clipboard.png

题主可能还有疑问,function baz 不是也在后面么,他可以提前访问,是因为 函数声明语句和 var 变量声明会在 代码执行之前 提前到所在函数环境或全局作用域的顶部,其中 var 声明提前仅仅是 var 提前,实际赋值保留在原地,函数声明提前是全部提前,这个可以另行百度,不过推荐看经典书籍,JavaScript权威指南-第6版-中

如果变量与执行上下文相关,那变量自己应该知道它的数据存储在哪里,并且知道如何访问。这种机制称为变量对象(variable object)。 变量对象(VO)是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容: 1.变量 (var, 变量声明); 2.函数声明(FunctionDeclaration, 缩写为FD); 3.函数的形参。在函数上下文中,变量对象被表示为活动对象AO。当函数被调用后,这个特殊的活动对象就被创建了。它包含普通参数与特殊参数对象(具有索引属性的参数映射表)。在函数执行上下文中,VO是不能直接访问的,此时由活动对象(activation object,AO)扮演VO的角色。
这里的bar并没有用var声明,并不是变量,并不在变量对象(VO)中,因而在函数执行时,也不会被活动对象AO所包含。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题