JavaScript作用域深入理解
- JS作用域浅析
- JS变量提升
- JS作用域嵌套
- JS作用域链
来源:面试被问到JS为何会产生作用域链
JS作用域浅析
说到JS的作用域,就得从JS的变量说起,JS不像其他语言(Java、c#),它是一种弱类型语言,变量既可以存储数值,又可以存储字符串。
变量的声明分为两种方式:显式声明和隐式声明。
变量的重要概念就是:作用范围。
变量根据定义的范围分为全局变量和局部变量。
直接定义的变量成为全局变量,全局变量在整个脚本被访问到;定义在函数中的成为局部变量,局部变量只在函数内有效。
注意:
1.若全局变量和局部变量重名,那么局部变量将覆盖全局变量。
2.如果变量没用var来声明,就会定义一个新的全局变量。
**关键字:变量、全局变量、局部变量、隐式声明、显式声明、作用域
举例如下:
var scope = "全局变量";
function knowScope(){
var fnScope = "函数变量";
var scope = "局部变量";
newScope = "全局变量2"
console.log("scope的值为:" + scope);
console.log("fnScope的值为:" + fnScope);
console.log("newScope的值为:" + newScope);
}
console.log("scope的值为:" + scope);
knowScope();
输出结果为:
scope的值为:全局变量
scope的值为:局部变量
fnScope的值为:函数变量
newScope的值为:全局变量2
这个例子很好的说明了我们在上面说到各个细节问题。这就是我们平常说到的JS的作用域,但如果细分的话,可以分为三类:即全局作用域、局部(函数)作用域和块级作用域。
JS变量提升
所谓变量提升就是JS在执行的过程中会创建一个执行上下文,而变量提升就是执行上下文中的内容,也就是当我的变量执行先于变量的声明,例如执行打印变量函数先于声明赋值,这时会打印出undefined,而不会报错。
注意:
1.JS执行时会创建执行上下文。
2.变量会提升,变量的值不会发生提升。
3.函数变量提升优先级高于普通变量。
举例如下:
function knowScope(){
console.log("scope的值为:" + scope);
console.log("fnScope的值为:" + fnScope);
var scope = "局部变量";
var fnScope = "函数变量";
}
knowScope();
输出结果为:
scope的值为:undefined
fnScope的值为:undefined
至于JS为何会发生变量提升呢?
我的想法是JS在解析和执行的时候要创建自己的执行上下文,当执行的时候不至于发生错误,出现了变量提升,这样提高了代码容错性,让性能更好。(我觉得理解得不透彻,有想法的伙伴可以说说自己的见解)
JS作用域嵌套
JS的作用域会根据变量的名称来进行一系列的查找,在实际中不可避免的一个问题就是函数的的嵌套,即一个函数中包含了其他的一个或者多个函数。在当前函数中无法访问到某个变量时,就会向上一级函数进行查找,寻找该变量,找到就停止;如果找不到就会继续向上一级函数进行查找,直到找到该变量为止。
举例如下:
function parentFn(){
var scope = "局部变量";
function sonFn(){
console.log("scope的值为:" + scope);
function childFn(){
console.log("scope的值为:" + scope);
}
childFn();
}
sonFn();
}
parentFn();
输出结果为:
scope的值为:局部变量
scope的值为:局部变量
JS作用域链
在说到JS作用域嵌套的时候说到查找变量的问题时,已经用到了JS的作用域,在调用嵌套函数的时候,引擎会自动根据嵌套的层次来创建一个参数的作用域链,然后将各个嵌套的函数所定义的变量有外到内一次放入到作用域当中。希望各位能给推荐一些英文源码,感谢各位。