我的var、let、const区别
var
1.使用var声明变量时,变量会被自动添加到最接近的上下文。
2.如果变量未经声明就被初始化了,那么它就会自动被添加到全局上下文。
例如:
function add(num1, num2) {
var sum = num1 + num2;
return sum;
}
let result = add(10, 20);
console.log(sum);//报错:sum在这里不是有效变量
function add(num1, num2) {
sum = num1 + num2;
return sum;
}
let result = add(10, 20);
console.log(sum);//30
3.var声明会被拿到函数或全局作用域的顶部,位于作用域中所有的代码之前。(变量提升)反复多次使用var声明同一个变量也没问题,以最后一次声明初始化的值为准。
4.var声明的范围是函数作用域。
let
1.let声明的范围是块作用域。(块作用域是函数作用域的子集)
2.let不允许同一块作用域中出现冗余声明。
3.let声明的变量不会在作用域中被提升。
4.let在全局作用域声明的变量不会成为window对象的属性。(var声明的变量会)。不过,let声明仍然是在全局作用域中发生的,相应变量会在页面的生命周期内存续。
5.let声明迭代变量时,JavaScript引擎在后台会为每个迭代循环声明一个新的迭代变量。
例如:
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
},1000);
}
输出是:0 1 2 3 4
然而:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
},1000);
}
输出是:5 5 5 5 5
原因:
1.1var声明的迭代变量,在退出循环时,迭代变量保存的是导致循环退出的值,再执行超时逻辑时,所有的i都是同一个变量,因而输出的都是同一个值。
2.简单来说,setTimeout是异步任务,每次循环需要将其回调函数存放到异步任务队列当中。用var声明的迭代变量,当计时器回调入队列未执行时,i还是最初的值,但i的生命周期不受块级作用域的限制,那么之后i变量的叠加,就会影响到之前放入异步队列中的所有回调,当同步的i迭代到退出条件时,再对异步任务队列进行清空,此时队列中所有的回调的i都是同一个值。
3.而用let声明的迭代变量,会受到块级作用域的影响,那么每次放入异步队列的回调函数中的i的值,就不会受到之后的i值的覆盖,那么每个异步回调都是不同的,所以输出的结果也都是不同的值。
const
1.const的行为与let基本相同,唯一的重要区别是:用它声明变量时必须同时初始化变量。一经声明,在其声明周期的任何时候都不能再重新赋予新值。
2.赋值为对象的const变量不能再被重新赋值为其他引用值,但对象的键不受限制,即可以修改对象内部的属性。
const和let有利于垃圾回收
因为const和let都以块为作用域,所以相比于var,使用这两个关键字可能会更早的让垃圾回收程序介入。在块级作用域比函数作用域更早终止的情况下,这就有可能会发生。