加 var 和 不加 var 的区别:
全局作用域下:
在全局作用域下使用 var
声明一个变量,相当于给 window 全局对象设置了一个属性,变量的值就是属性值;
// 前面2个为 undefined 是因为变量提升,没有值
console.log(a) // => undefined
console.log(window.a) // => undefined
// 但是在 对象 中访问不存在的 属性,也会输出 undefined,就不清楚某个属性 是否存在于对象中,例如
console.log(window.c) // => undefined
// 他们输出的都是 undefined,于是你就不知道 a 和 c 那个值是在 window 中的;可以使用 in 来进行判断
console.log('a' in window) // => true
console.log('c' in window) // => false
var a = 12
console.log(a) // => 12
console.log(window.a) // => 12
// 改变 window 中的a,全局变量 a 也变化, 全局变量 和 window的属性存在映射关系
window.a = 13;
console.log(a) // => 13
结论:
-
in
用于判断 属性名 是否存在于 某个对象; -
全局变量 和
window
中的属性存在 映射机制,一个改变,另一个也跟着改变;
我们不使用 var
来看看,有什么区别:
// console.log(a) // => a is not defined
console.log(window.a) // => undefined, 这个结果是 window 没有 a 这个值,还是 a 的值为 undefined 呢?
console.log('a' in window) // => false; window 不存在 a 这个属性;
a = 12; // 这个其实不是定义一个变量 a,而是为 window 添加一个 a属性,可以看做这样 window.a = 12;
console.log(a) // => 12,这个和下面的一致,可以看做 window.a
console.log(window.a) // => 12
console.log('a' in window) // => true
提问:为什么第一个 a 输出报错了呢?
答: 一开始,浏览器是以他会变量去寻找 a 的,发现没有,就报错;
总结: 不加 var
创建的变量,创建的是 window
的属性;
私有作用域下:
1,带 var
的变量,在私有作用域变量提升时,都为 私有变量 和 外部没有任何关系;
2,在私有作用域中,不带 var
创建的不是私有变量,会向上级作用域查找他 ,看是否为上级的变量,不是的话,继续向上查找,直到找到 window
为止(我们把这种查找机制称为: “作用域链”),之后 我们在 私有作用域中操作的这个 非私有的变量, 是别人的变量,在 私有作用域中操作他,会改变他的值 。
console.log(a, b)
var a = 12, b = 12;
function fn () {
console.log(a, b);
var a = b = 13;
console.log(a, b)
}
fn();
console.log(a,b)
以下的画的图结构:
学习视频:
JS中的堆栈内存及闭包详解