话不多说,直接上代码:
function fn() {
var x = y = 1;
}
fn();
console.log(y); // 1;
console.log(x); // Error: undefined;
运行结果:
原因是这个函数在执行的时候, 是先执行的: y = 1; 因为这里的y在声明赋值时没有使用var, 因此会默认成为全局变量, 然后将一个全局变量的值赋值给一个局部变量x;
其实际的执行过程如下:
var y = 1;
function fn() {
var x = y;
}
既然讲到了变量提升,我们就接着分析一下var,let和const之间的区别
从以下三个方面说:
变量提升方面:var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升问题(注意这个‘问题’后缀,其实是有提升的,只不过是let和const具有一个暂时性死区的概念,即没有到其赋值时,之前就不能用),即它们所声明的变量一定要在声明后使用,否则报错。
块级作用域方面:var不存在块级作用域,let和const存在块级作用域
声明方面:var允许重复声明变量,let和const在同一作用域不允许重复声明变量。其中const声明一个只读的常量(因为如此,其声明时就一定要赋值,不然报错)。一旦声明,常量的值就不能改变。
如何使const声明的对象内属性不可变,只可读呢?
如果const声明了一个对象,对象里的属性是可以改变的。
const obj={name:'蟹黄'};
obj.name='同学';
console.log(obj.name);//同学
因为const声明的obj只是保存着其对象的引用地址,只要地址不变,就不会出错。
使用Object.freeze(obj) 冻结obj,就能使其内的属性不可变,但它有局限,就是obj对象中要是有属性是对象,该对象内属性还能改变,要全不可变,就需要使用递归等方式一层一层全部冻结。