JavaScript 内功心法——作用域链

前端必备内功之作用域链

Posted by Shiyanping on November 11, 2018

1. 作用域

JS 中包含全局作用域,函数作用域,块级作用域,在 ES6 之前没有块级作用域,只有一个全局作用域和函数作用域。

函数内部可以访问外部的变量,但是函数外部不可以访问函数内部的变量,当没有使用 var 定义一个变量时,默认会定义成全局变量,全局都可以访问。

例:

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

function test() {
  if (false) {
    var i = 100;
  }
  j = 10000;
  console.log(m); // 1000
}

test();

console.log(i); // Uncaught ReferenceError: i is not defined
console.log(j); // 10000

tips:

非匿名自执行函数,函数变量为只读状态,无法修改。

1
2
3
4
(function foo() {
  foo = 10; // 由于foo在函数中只为可读,因此赋值无效
  console.log(foo);
})();

2. 作用域链

当我们在函数中访问一个变量时,如果函数中没有这个变量,会逐层的往上层作用域去找,直到找到全局作用域。

在向上找的这个过程中,作用域和作用域的关联都是通过 [[scope]] 属性去连接。

通过 [[scope]] 去逐层向上找作用域,内层的作用域中,可以访问它自己直到全局作用域中的变量。

1
2
3
4
5
function foo() {
    function bar() {
        ...
    }
}

函数创建时,每个函数就会形成各自的 [[scope]]

1
2
3
4
5
6
7
8
foo.[[scope]] = [
  globalContext
];

bar.[[scope]] = [
    fooContext,
    globalContext
];