你不知道的JavaScript(上)
2023-09-04 本文已影响0人
普通市民王二狗
1 作用域是什么
程序的一段代码在执行之前,会经历三个步骤,统称为编译。
- 词法分析
- 语法分析
- 代码生成
js引擎会在执行前进行编译,比如var a = 2
- var a 在作用域生成新的变量
- a = 2 会进行LHS查询,查询a并进行赋值
2 词法作用域
2.1 词法阶段
大部分语言编译器进行的第一个工作阶段叫做词法化,词法化的过程会对源代码中的字符进行检查。
词法作用域就是定义在词法阶段的作用域。简单说,是由代码写在哪里来决定的。
2.2 欺骗词法作用域
- eval
function foo () {
console.log(b)
}
var b = 1;
foo() // 1
在这里,foo作用域中找不到变量b,便会向上级作用域查找,于是找到了全局变量中的b。
function foo (str) {
eval(str) // 假装在这里
console.log(b)
}
var b = 1;
foo("var b = 2") // 2
eva可以在运行期间修改书写期的词法作用域,假装“var b = 2”在foo中。
2.with
function foo (obj) {
with(obj) {
a = 2;
}
}
var o1 = {
a: 3
}
var o2 = {
b: 3
}
foo(o1);
console.log(o1.a) // 2
foo(o2);
console.log(o2.a) // undefined
console.log(a) // 2
o1,o2 的区别是,o1原本具有a属性。
with声明实际上为传入的对象凭空生成了一个词法作用域。所以,在这个作用域中,o1中的a被赋值为2。o2中,未查找到变量a,于是向上查找,直到全局作用域都没有找到,于是在全局作用域中创建了变量a,并赋值为2。