最近读到《你不知道的 JavaScript》,里面讲到了静态作用域和动态作用域,我一脸懵,我只知道有作用域,但不知道作用域还有分类。哎呀,再次感到学无止境!
好了,话不多说,我们先看书中列出来的一个例子
function foo(){
console.log(a);
}
function bar(){
var a = 3;
foo();
}
var a = 2;
bar();
大家认为会输出什么呢,我一看,认为是会输出3,因为在函数bar里有定义a并初始化为3。但实际上控制台输出为2。
为什么输出是2呢,在这里就要认真掰掰静态作用域和动态作用域了。
静态作用域
就是说函数的作用域在函数定义时就已经确定下来了,而javascipt是采用静态作用域的。
那么我们来分析一下刚才的代码:
- 执行bar(),内部定义局部变量a并初始化为3
- 执行foo(),里面是打印变量a,但发现foo函数内部没有定义变量a,然后在函数foo定义位置的上面一层查找,发现有变量a,打印2
可以发现,函数作用域在定义时就决定了。
如果js是动态作用域,那么会怎么样呢?
动态作用域
假如js是动态作用域,刚才的代码分析流程是:
- 执行bar(),内部定义局部变量a并初始化为3
- 执行foo(),里面是打印变量a,但发现foo函数内部没有定义变量a,那么调用函数作用域,也就是bar函数的作用域,发现bar函数有定义变量a,打印3
可以发现,针对动态作用域,函数作用域是在函数被调用时才决定的。
总结
以上就是我对静态作用域和动态作用域的理解,可能你仍然会觉得懵圈,后续会从作用域链,变量对象和this等角度再次分析js的词法作用域。如果觉得对你有帮助,请帮忙点个赞+评论+收藏。