作用域
求以下代码的打印结果
var a = 10;
function test() {
console.log(a);
a = 100;
console.log(this.a);
var a;
console.log(a);
}
test();
追问: 如果注释掉 test中的第四行 var a; 打印结果有什么变化?
// 题解
var a = 10; // 全局变量 a
// 函数声明 test
function test() {
console.log(a);
a = 100;
console.log(this.a);
var a;
console.log(a);
}
// 注意到上面👆函数中有var a 声明,这是在考察 var 的变量提升,注意 var 提升的只有声明,赋值不提升,所以V8执行实际的代码如下👇
function test() {
var a; // 把 var a 变量声明提升到函数最上面
console.log(a); // 妥妥的 undefined 嘛!
a = 100; // 给 a 赋值 100
// 打印this.a, 那么 this 指向谁? 那要看谁调用的 test 我们来看看:👀test() 谁调用的? 全局调用的,所以this.a 是外层的 10
console.log(this.a);
// 打印变量 a 先在当前函数作用域中查找变量 a 我们找一下 🔍能找到嘛,可以! 有一个 100 所以 第三个是 100
console.log(a);
}
// 正确答案: undefined 10 100 (浏览器环境)
// 追问题解: 如果题目是这样的
var a = 10; // 全局变量 a: 10
// test中没有 var 所以没有变量提升,代码按顺序执行
function test() {
// 打印变量 a ,按作用域链找,函数作用域中没有变量 a 向上查找,找到全局变量 a: 10 打印 10
console.log(a);
// 好家伙,直接 a = 100; 还记得这种没有 var 直接光秃秃的给一个变量赋值,的情况浏览器会怎么处理嘛?
// 他会直接把 a 作为一个全局变量,此时外面已经有一个 a 是 10了,会怎样?会直接覆盖!!
a = 100; // 这一步直接把外面全局的 a 改为 100 了
console.log(this.a); // 同上面一样,test() 函数调用 this指向全局,此时全局的a 已经是 100,打印100
console.log(a); // 按作用域查找,函数内部没有声明变量 a 向上查找 找到全局的 a 打印也是 100
}
test(); // 打印 10 100 100 (浏览器环境)