探索 JavaScript 作用域:解密变量范围与访问规则
前言
作用域(Scope)在编程中是指变量和函数的可访问性和可见性的范围。在JavaScript中,作用域定义了变量和函数在代码中的可访问范围。作用域规定了在代码中的哪些位置可以访问某个变量或函数,以及在这些位置如何解析变量名。作用域控制着变量的生命周期以及其在代码中的可见性。其中作用域分为全局作用域,函数作用域和块级作用域,内层作用域是可以访问外层作用域的,反之,则不行。
全局作用域
代码演示
var a = 1;
对于上述的代码进行的步骤:
- 词法分析:词法单元:var,a,=,2
- 解析:将词法单元=转换成一个 逐级嵌套 的程序语法结构树 --- 抽象语法树
- 生成代码:var a = 2
有效标识符:a
函数作用域
代码演示
function foo(b) {
var b = 2;
console.log(b);
}
有效标识符:b
综合代码
var b;
function foo(a) {
function bar(a){
return a - 1;
};
b = a + bar(a * 2);
console.log(b * 3);
};
foo(2);
- 全局作用域的有效标识符:b,foo(2)
- foo函数作用域的有效标识符:a,bar()
- bar函数作用域的有效标识符:a
分析:当执行b = a + bar(a * 2);时,该bar函数作用域没有a,那么这个时候内层作用域是可以访问外层作用域的,就去foo函数作用域,查找到a=2,此时就可以执行,则b=5。
块级作用域
代码演示
if (true) {
let a = 1;
}
console.log(a);
分析:报错是因为{let/const}
这种形式会形成块级作用域,并且外层不能访问内层,所以报错。
小知识
自执行函数 (立即执行函数)
(function() {
var a = 3;
console.log(a);
})();
声明提升
console.log(a);
var a = 1;//声明提升
分析:此时没有报错,因为var具有声明提升,上面的代码相当于:
var a;
console.log(a);
var a = 1;
注意:如果将上述的代码中的var改为let,将报错,因为var可以重复声明变量,let不可以。
let a;
console.log(a);
let a = 1;
let VS var
- var存在声明提升,let不存在
- let会和{}形成块级作用域
- var可以重复声明变量,let不可以
const:定义的为常量,不可改值
const a = 1; // 常量
a = 2;
console.log(a);
欺骗词法作用域
- eval():将原本不属于这里的代码变成就像天生就定义在这里一样
function foo(str ,a) {
eval(str);//var b = 3
console.log(a ,b);
};
var b = 2;
foo('var b = 3', 1);
- with():用于修改一个对象中的属性值,但如果修改的属性在原对象中不存在,那么该属性就会被泄露到全局
var obj = {
a:1,
b:2,
c:3
};
with (obj) {
a = 3,
b = 4,
c = 5
}
console.log(obj);
function foo(obj) {
with(obj){
a = 2;
}
};
var o2 = {
b: 3
};
foo(o2);
console.log(o2);
console.log(a);
结语
希望能给需要的人带来一点小小的帮助,喜欢的话,记得一键三连哦~
转载自:https://juejin.cn/post/7361724931124740108