另一道题:
var a = 3;
function test() {
var b = a || 5;
var a = 7;
console.log(b);
}
test();
问输出是什么,我依旧毫不意外的做错,想着var a = 3;是全局变量,那么函数里边也能拿到 a,所以b = a = 3; 但我根本忽略了函数里的一句:var a = 7; 以及var的变量提升!!!所以其实上边的函数实际相当于:
function test(){
var a, b;
b = a || 5;
a = 7;
console.log(b);
}
在给 b 赋值的时候,需要访问 a ,而访问的顺序应该是先看自己的作用域中有无该变量,有则直接使用,没有则找自己的父级是否有该变量;那么这里尽管声明 a 变量是在给 b 赋值操作之后,但由于 var 的变量提升,在给 b 赋值时,其实 a 已经被声明了,但未赋值,给 a 赋值的操作放到了给 b 赋值的操作之后;那么给 b 赋值时,访问到的 a 的值其实是undefined,所以 a || 5 结果是 5 ;b 也就等于 5;
整个代码最后输出也就是: 5
再看另一段代码做个对比:
var color = 'blue';
function changeColor() {
if (color == 'blue') {
color = 'red';
console.log(color);
} else {
color = 'blue';
console.log(color);
}
}
changeColor(); // red
console.log(color); // red
changeColor(); // blue
上边段代码的输出就是:red
全局作用域下声明了color变量并赋值blue
在test函数中会去访问color变量,并对其做一定的操作;那么当需要访问color变量时,首先会看test函数自己的作用域中是否声明color,也就是是否有 var color; 没有则去看他的父级,此处的父级也就是全局作用域下是否有color变量,是有的,那么访问到的就是全局作用域下的color,后续操作也是对全局作用域下的color进行操作; 全局作用域下的color的值也会受影响
function changeColor() {
if (color == 'blue') { // 错误将在这一行抛出
color = 'red';
console.log(color);
} else {
color = 'blue';
console.log(color);
}
}
changeColor();
这段代码运行会报错:
因为在函数的作用域和全局作用域内都没有找到对变量color的声明,而没有声明就直接访问color了,所以会抛出:color is not defined