这是我参与8月更文挑战的第二十二天,活动详情查看:8月更文挑战
词法作用域与动态作用域的区别
众所周知,JavaScript中的作用域是词法作用域。(实际上大部分语言都是词法作用域的)词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则。词法作用域最重要的特征就是它的定义过程发生在代码的书写阶段。(不适用eval和with的情况下)而动态作用域则是让作用域作为一个在运行时就被动态确定的形式,而不是在写代码时进行静态确定的形式。下面我们看一个例子:
var a = 2;
function foo(){
console.log(a);
}
fonctiong bar(){
var a = 3;
foo();
}
bar();
JavaScript的词法作用域让foo()中的a通过RHS引用(关于RHS引用和LHS引用后面会讲)了全局作用域中的a,因此会打印2。而动态作用域则并不会去关心函数的作用域是怎么声明以及在哪个地方声明的,它只关心从何处进行调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套。
因此,如果JavaScript具有的动态作用域,那么上面的代码在执行的时候,会输出3。因为在当foo()无法找到a的变量引用时,会顺着调用栈在调用foo()的地方查找a,而不是在嵌套的词法作用域链向上查找。在这个例子中,由于foo()是在bar()中调用的,引擎会检查bar()的作用域,并在其中找到值为3的变量a。
这里只是举例作为说明而已,事实上在JavaScript中是并没有动态作用域的,JavaScript只有词法作用域,简单明了。但是我们之前讲的this机制在某种程度上来说很像动态作用域。
总结
词法作用域是在写代码或者说定义时确定的,而动态作用域则是在运行时确定的。(this也是!)词法作用域关注函数在何处进行声明,而动态作用域关注函数从哪里进行调用。