Fork me on GitHub

JS-作用域和作用域链

作用域和作用域链

词法环境(Lexical Environments)/作用域/词法作用域

是一种规范类型,用于根据 ECMAScript 代码的词法嵌套结构来定义标识符与特定变量和函数的关联。
通俗的将,词法环境就是一套约定好的规则。写代码应该按照这个规则来。JS 引擎对 JS 源码进行词法分析,也是按照这个规则。
所以,词法环境在我们写代码的时候已经确定,另外this指向在执行阶段才能确定。

  1. JS 中,我们可以将作用域定义为一套规则,这套规则用来管理 JS 引擎如何在当前作用域以及嵌套的子作用域中根据标识符(变量名或函数名)名称进行变量查找。
  2. JS有全局作用域与函数作用域。

作用域链

作用域链,是由当前环境与上层环境的一系列变量对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var a = 20;

function test() {
var b = a + 10;

function innerTest() {
var c = 10;
return b + c;
}

return innerTest();
}

test();

innerTest 的执行上下文
innerTest执行上下文
当前作用域与上层作用域不是包含关系。以最前端为起点,最末端为终点的单方向通道我认为是更加贴切的形容。
innerTest 作用域链
innerTest作用域链
注意,因为变量对象在执行上下文进入执行阶段时,就变成了活动对象(AO)

作用域与作用域链

作用域:就是一个独立的地盘,让变量不会外泄、暴露出去。
分类:全局作用域,函数作用域,块级作用域(ES6)

1
2
3
4
5
6
7
var a = 100
function fn() {
var b = 200;
console.log(a);
console.log(b)
}
fn()

在当前作用域没有该变量,就会向父级作用域寻找。如果还有找到,就向再向上级寻找,直到全局作用域,如果都没找到就报错。这种一层一层的关系,就是作用域链。

1
2
3
4
5
6
7
8
9
10
11
12
13
function F1() {
var a = 100;
return function () {
console.log(a)
}
}

function F2(f1) {
var a = 200;
f1()
}
var f1 = F1();
F2(f1) //100

上述代码中,变量 a,从函数 F1 中查找而不是 F2,变量从作用域链中去寻找,*依据的是函数定义时的作用域链,而不是函数执行时

1
2
3
4
5
6
7
8
9
10
11
12
13
var a = 20;
function foo() {
console.log(0, a) //0 undefined
if (!a) {
console.log(1,a) //1 undefined
a = 100;
}
console.log(2,a) //2 100
var a = 10;
console.log(3,a) //3 10
return a;
}
console.log(foo());
-------------本文结束感谢阅读-------------