关于词法作用域与动态作用域
以前很早就知道词法作用域的概念,还恍惚知道动态作用域,但是至于为啥做这个区分,一直不是很清楚。直到开始频繁用js时,遇到了this的问题,才开始注意到。
原来自己一直以来用的和理解的都是词法作用域,也叫静态作用域,变量的绑定,是直观的,写在哪里就在哪里绑定,找不到就一层一层往外找,看代码就能直接看出来。
var a = 2;
function test(){
console.log(a); // 输出是多少?
}
(function (){
var a = 4;
test();
})();
这一段代码,如果是词法作用域,那么输出结果会是2, 如果是动态作用域,结果就是4。
词法作用域取决于代码怎么写,就怎么绑定,还没运行,就能知道绑定的值在哪里。
动态作用域则不然,在没有运行的时候,是不知道绑定到什么值的,非得到运行时才知道,其查找规则是查看函数调用栈,顶层函数种找不到的变量,就往下一层的函数中寻找。很显然,如果使用第三方库的话,不知道人家的调用次序和方法的情况,不运行是根本没办法知道变量在哪个作用域进行的绑定。
javascript的this,和动态作用域比较像,可是又不同,ES6的箭头函数this指针是词法作用域,传统的function定义,会根据运行时的调用栈,找到是谁调用了自己,以此来决定绑定,如果找不到绑定,则会默认绑定到最外围的window或nodejs的global对象,而不是传统的动态作用域的一层一层的往外找。
绝大部份市面上的语言,都是词法作用域,比如C, C++, java, javascript等等。
动态作用域的语言就少多了,比如lisp, perl等等。
如果看到这里还不清楚的话,一句话可以概括:看代码就能知道结果的,是静态作用域。看代码时难以预测结果,时对时错的(完全自己写的代码能预测对,用别人的代码难以预测对,因为别人的调用顺序不知道),是动态作用域。