js作用域和作用域链

作用域:在js预编译时、代码执行之前对全局或局部的变量进行收集,存放在一指定内存中scope,执行时对scope进行访问,scope 就是全局或局部的作用域。

如:

1 function test() {
2   var a = 123;  
3 }
4 
5 test();

在test() 执行之前对test 进行预编译 生成test 的 scope(AO Activetion Object)。收集test 函数中的变量存放在scope中。

此时test 的scope 为:

{

  a:undefined

}

在test 函数执行时 对 scope 中的 a 变量进行赋值,a = 123;

 

实际上在全局环境进行预编译时也会产生一个作用域,在test 被定义时会在test 函数上定义一个作用域数组([[Scopes]])。并将全局作用域放入test的作用域数组中。

如:

1 var a = 456;
2 
3 function test() {
4   var b = 123;
5   console.log(b);
6   console.log(a);      
7 }
8 
9 test();

在全局环境进行预编译时,会生成全局作用域Global

Global {

  a: undefined,

  test: undefined

}

此时test 函数的作用域数组中就已经包含了Global 

test.[[Scopes]] = [Global] // 实际上[[Scopes]] 是不可访问的

全局环境执行完后Global变成

Global{

  a: 456,

  test: function test() {...}

}

在test 函数执行前会对test函数进行预编译,生成test 函数的scope并放入到test 函数的作用域数组的第一位。

scope {

  b: undefined

}

test.[[Scopes]] = [scope,Global] // 实际上[[Scopes]] 是不可访问的

在test 代码执行b= 123时对作用域scope 中的b进行赋值

scope {

  b: 123

}

在test 函数中打印a 时会沿着test 作用域数组中的顺序进行查找,首先会查找test 的scope 中是否有a,如果有者直接使用,如果没有沿着[[Scopes]] 继续查找,在Global 中进行查找,所以打印的是Global 中的a的值--456。

如果沿着[[Scopes]] 的顺序找到Global 一直找不到a,就会报错 a is not defined

由于在访问变量时会沿着[[Scopes]] 查找,这种查找机制类似链条结构,所以称[[Scopes]] 为作用域链。

posted @ 2020-03-04 18:51  小小_先森  阅读(677)  评论(0编辑  收藏  举报