小记·作用域|闭包|变量提升

完全是些零碎的总结↓

变量提升?

栗子:

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

对于可执行代码,在其执行之初会有一个分析的过程,分析时会预处理函数的活动对象(AO),此时AO内部的foo初值为undefined,只有当真正执行到var foo时,才会赋值1,由于console.log在var之前,所以打印的foo是undefined(此时AO.foo=undefined)

简而言之:变量能提升是因为分析过程中,var声明的键被初始化了。

思维导图?

闭包?

JS是词法(静态)作用域,其作用域在创建(而不是执行时)确定,所以

let value = 1;
function foo() {
    console.log(value);
}
function bar() {
    let value = 2;
    foo();
}
bar();

结果是value=1
原因是
1.foo和bar被在全局代码中被创建,此时会初始化AO,作用域链,this,
2.foo和bar的作用域链都是[自己的AO,global.AO]
3.所以打印结果是1

这里涉及的作用域链,其完全与函数内部一个叫做[[Scopes]]的属性有关,不信看下例闭包

function foo() {
    let a=1
    function bar() {
      console.log(a)
    }
   return bar
}
console.dir(foo());
//打印结果↓↓
f bar()
arguments: null
caller: null
length: 0
name: "bar"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: VM50:3
[[Scopes]]: Scopes[2]
0: Closure (foo) {a: 1}
1: Global {window: Window, self: Window, document: document, name: "", location: Location, …}

[[Scopes]]内包含的就是变量对象VO,函数执行时找变量就是从Scopes的VO按序遍历来寻找的。
根据上面的解析过程,我们也可以如法炮制
原因:
1.全局代码下foo被创建,初始化AO,作用域链,this,此时foo的作用域链是[foo.AO,global.AO]
2.执行foo
3.bar被创建,此时bar的作用域链是[bar.AO,foo.[[Scopes]]]==[bar.AO,foo.AO,global.AO]
4.返回bar
5.bar的scopes没有变化,当然被保存了呀,所以闭包

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容