前置知识 – 作用域
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)的规则
function foo() {
var a = 'iceman';
console.log(a); // 输出"iceman"
}
foo();
在foo函数执行的时候,输出一个a变量,那么这个a变量是哪里来的嘞,有看到函数第一行有定义a变量的代码var a = ‘iceman’。
var b = 'programmer';
function foo() {
console.log(b); // 输出"programmer"
}
foo();
同样的道理,在输出b的时候,自己函数内部没有找到变量b,那么就在外层的全局中查找,找到了就停止查找并输出了。
以上两段代码都有查找变量,第一段代码是在函数中找到a变量,第二段代码是在全局中找到b变量。所以,通俗的讲,作用域就是查找变量的地方。在某函数中找到该变量,就可以说在该函数作用域中找到了该变量;在全局中找到该变量,就可以说在全局作用域中找到了该变量!
我们在查找b变量的时候,先在函数作用域中查找,没有找到,再去全局作用域中查找,有一个往外层查找的过程。我们好像是顺着一条链条从下往上查找变量,这条链条,我们就称之为作用域链。
用代码表示:
词法作用域
在上面的作用域介绍中,我们将作用域定义为一套规则,这套规则来管理浏览器引擎如何在当前作用域以及嵌套的作用域中根据变量(标识符)进行变量查找。
所谓的词法作用域就是在你写代码时将变量和块作用域写在哪里来决定,也就是词法作用域是静态的作用域,在你书写代码时就确定了。
function fn1(x) {
var y = x + 4;
function fn2(z) {
console.log(x, y, z);
}
fn2(y * 5);
}
fn1(6); // 6 10 50
这个例子中有个三个嵌套的作用域,如图:
-
A 为全局作用域,有一个标识符:fn1
-
B 为fn1所创建的作用域,有三个标识符:x、y、fn2
-
C为fn2所创建的作用域,有一个标识符:z
词法作用域就是作用域是由书写代码时函数声明的位置来决定的。编译阶段就能够知道全部标识符在哪里以及是如何声明的,所以词法作用域是静态的作用域,也就是词法作用域能够预测在执行代码的过程中如何查找标识符。