深入理解词法作用域
18888628835 opened this issue · 0 comments
什么是作用域
作用域就是程序源代码中定义变量的区域,JS中按照作用域的范围可分为全局作用域跟局部作用域(块级作用域、函数作用域)
作用域主要用来规定JS
引擎查找变量的访问权限。
作用域的类型有两种,动态作用域和词法作用域,词法作用域也称静态作用域。JS
的作用域属于词法作用域
什么是词法作用域
词法作用域说通俗一点就是在写代码的时候就已经确定了作用域范围。
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
上面的代码会打印出1
,也就是说,在foo这个函数定义的时候,value这个变量就已经确定了是全局作用域下的value
。
我们分析一下它的执行过程:
1、bar
执行,作用域记录里面有个value
变量,值为2。
2、foo
执行,进入foo
函数内
3、foo
内部打印value
变量,此时查找value
变量
4、value
不存在于foo函数内部,此时查找foo
定义时词法作用域下的环境,查找上一层作用域,最后发现全局下有个value
变量
5、打印value
,结果为1。
以上属于JS
词法作用域的执行过程,我们拿它和动态作用域做一个对比.
动态作用域
依然是上面的代码,如果打印出value的值为2,那就是动态作用域。很多语言诸如Java
就是动态作用域。说白了动态作用域会按照当前的运行环境动态选择作用域范围,这样查找的变量就会发生动态变化。
动态作用域取决于函数的调用环境,如果是动态作用域的语言,那么上面代码的执行过程是这样的:
1、bar
执行,作用域记录里面有个value
变量,值为2。
2、foo
执行,进入foo
函数内
3、foo
内部打印value
变量,此时查找value
变量
4、value
不存在于foo函数内部,此时查找foo
运行时的环境,发现调用foo
时的作用域是bar函数,内部有个value
变量
5、打印value
,结果为2。
我个人觉得动态作用域更符合人类的思维。不过JS
的设计也减轻阅读代码的难度。
思考
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope(); //打印出什么
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()(); //打印出什么
var a=checkscope()
a() //打印出什么
上面的代码分别执行打印的结果是什么?
上面的答案全部都是local scope
原因很简单,只需要记住JS
是词法作用域,所有变量在函数定义的时候就已经跟着作用域确定好了,所以不管是处于怎样的运行环境,始终会牢牢绑定函数checkscope
内部的scope
变量。
小贴士:JS的作用域是静态的,那么有什么是动态的呢?答案是
this
,所谓动态,就是根据运行环境变化而变化。this
就是能代表变量跟随运行环境变化的关键字。