一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第4天,点击查看活动详情。
函数作用域和全局作用域
每个函数在执行都需要查找自己的作用域,我们称之为函数作用域,执行一个函数的时候,当该函数需要使用某个变量或者调用某个函数的时候,便会优先在该函数作用域中查找相关内容。
如果在当前函数作用域中没有查找到该变量,v8会去从全局作用域中查找,这个查找到过程称之为作用域。
全局作用域和函数作用域类似,也是存放函数和变量的地方,但是,全局作用域是在v8启动的过程中就创建了,并且一直保存在内存中不会被销毁,直到v8推出,而函数作用域是在执行该函数时创建,当函数执行结束之后,函数作用域就随之销毁。
全局作用域包括了很多全局变量,比如全局的this,如果是浏览器作为宿主,还会有window,document很多方法和对象,如果是node环境,还会有global,file
作用域链是怎么工作
var type='global type'
function foo(){
console.log(type)
}
function bar(){
var type='bar'
foo()
}
bar()
来猜一下这个案例的输出。
这个案例的执行阶段只会调用bar,v8执行bar函数,执行bar函数,同样也会进行编译和执行2个阶段。v8会在编译阶段给bar函数创建函数作用域。
然后进入了bar函数的执行阶段,发现bar也只是调用了foo,那同样编译且执行foo,同样会创建foo函数的作用域,此时有3个作用域,分别是全局作用域,bar函数作用域,foo函数作用域
此时就是作用域链的问题,foo打印的type到底是谁的type,到底是bar的type还是全局作用域的type。
词法作用域
js是基于词法作用域,也就是查找作用域的顺序,是由函数定义时的位置来决定的,bar和foo函数的外部都是全局的代码,所以无论是bar还是foo中查找变量,都是按照当前函数作用域->全局作用域这个路径来的。
所以最终会打印全局的type。
词法作用域是根据函数在代码的位置来确定的,作用域是在声明函数时就确定了,所以词法作用域也称为静态作用域。
和静态作用域相对的是动态作用域,动态作用域不关心函数在哪里声明的,只关心何处调用,是基于函数调用栈的,不是基于函数定义的位置。