作用域分为两种,一种是词法作用域,一种是动态作用域,我们先看第一种,词法作用域
词法作用域就是定义在词法阶段的作用域(编译器的第一个工作阶段叫做词法化,词法化的过程会对源代码中的字符进行检查)。换句话说,词法作用域是由你在写代码时将变量和块作用域写在哪里来决定的。因此词法分析器处理代码时会保持作用域不变
function foo(a) {
var b = a * 2;
function bar(c){
console.log( a, b, c );
}
bar( b * 3 );
}
foo( 2 ); // 2, 4, 12
1、包含着整个全局作用域,其中只有一个标识符:foo
2、包含着 foo 所创建的作用域,其中有三个标识符:a、bar 和 b
3、包含着 bar 所创建的作用域,其中只有一个标识符:c
作用域气泡由其对应的作用域块代码写在哪里决定,它们是逐级包含的。每一个函数都会创建一个新的作用域气泡
在上一段代码中,引擎执行 console.log(a,b,c) 时,首先从最内部的作用域,也就是 bar 开始查找,引擎无法在这里找到 a,因此去上一级到嵌套的 foo 继续查找,在这里找到了。b 同理。 而对 c 来说,引擎在 bar 中就找到了。
如果 a 存在于 bar 中,console.log 就可以直接是用 bar 中的变量,而无需到 foo 中查找。
作用域查找会在找到到第一个匹配到标识符停止
无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处到位置决定。
词法作用域查找都只会查找一级标识符