三大门派var,const,let之间的纠纷
let,const是属于块级作用域的,而var是属于全局作用域的
对于这三大门派,我们可以从以下四点进行分析学习
- 作用域规则
- 重复声明/重复赋值
- 变量提升(hoisted)
- 暂时死区(TDZ)
var的缺陷是什么?
- var 存在变量提升,那么接下来的这段会发生什么?
function fun2(){
let f3 = 3
const f4 = 4
//Uncaught ReferenceError: Cannot access 'f1' before initialization
//console.log('f1--',f1)
console.log('f2--',f2)
//undefined
console.log('f3--',f3)
//3
console.log('f4--',f4)
//4
//Uncaught ReferenceError: Cannot access 'f5' before initialization
//console.log('f5--',f5)
let f1 = 1
var f2 = 2
const f5 = 5
}
fun2()
-
该销毁的没有销毁,没有屏蔽功能
因为var声明的变量存在全局变量中,存在变量提升问题,而且var声明的变量没有销毁,所以不能实现块级作用域变量销毁的概念,但是let,const的出现解决了这个问题。
function fun1(){
for(var i =0 ;i<5;i++){
}
//i-- 5
console.log('i--',i)
for(let j =0 ;i<5;i++){
}
//Uncaught ReferenceError: j is not defined
console.log('j--',j)
}
fun1()
-
变量容易在不被察觉的情况下被覆盖掉
var myname = "w" function showName(){ console.log('before--',myname); if(0){ var myname = "j" } console.log('after--',myname); } showName()
-
所有未声明直接赋值的变量都会自动挂在顶层对象下,造成全局环境变量不可控、混乱
var a = 0 function fun(){ //重新赋值,对于let,const a = 10 b = 11 console.log('fun--a',a)//10 console.log('fun--b',window.b)//11 }
-
允许多次声明同一变量而不报错,造成代码不容易维护,直接修改变量值
var t = 100 function fun3(){ for (let i = 0;i<10;i++){ t = i console.log('fun3--i--',t) } }
var arr = []; for (var i = 0; i < 10; i++) { arr[i] = function () { console.log(i); }; } //10 arr[6]();
let 解决了var的什么缺陷
1不存在变量提升,有暂时死区,始终在
在 JavaScript 中,当控制流进入它们出现的范围时,所有绑定声明都会被实例化。传统的
var
和function
声明允许在实际声明之前访问那些绑定,并且其值(value)为undefined
。这种遗留行为被称为变量提升(hoisting)。当控制流进入它们出现的范围时,let
和const
声明也会被实例化,但在运行到实际声明之前禁止访问。这称为暂时性死区( Temporal Dead Zone)。TDZ 的存在是为了防止传统提升可能造成的那种错误。
//Cannot access 'test1' before initialization
//console.log(test1)
let test1 = 'test1'
{
//test2 is not defined
//console.log(test2)
let test1 = 'test2'
}
let myname = "w"
function showName(){
//before-- w
console.log('before--',myname);
if(0){
let myname = "j"
}
//after-- w
console.log('after--',myname);
}
showName()
-
不允许同一块重复声明
在一个嵌套作用域中声明同一个变量名称的行为称做 屏蔽 ,
function sumArr(arrList) {
let sum = 0;
for (let i = 0; i < arrList.length; i++) {
var arr = arrList[i];
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
}
}
return sum;
}
-
使用 let 在全局作用域下声明的变量也不是顶层对象的属性
属于块级作用域,作用域块内声明的变量不影响块外面的变量
块作用域变量在包含它们的块或
for
循环之外是不能访问的var arr = []; for (let i = 0; i < 10; i++) { arr[i] = function () { console.log(i); }; } //6 arr[6]();
function fun4(){ let g = 44 var gg = 55 } //Uncaught ReferenceError: g is not defined console.log('g',g) console.log('gg',gg)
const 解决了var的什么缺陷
-
const
声明一个只读的常量。一旦声明,常量的值就不能改变。 -
其它
const
与let
相同,例如:- 常量也是不提升,同样存在暂时性死区
- 作用域相同,只在声明所在的块级作用域内有效
var VS let VS const
var
、 let
、 const
的不同主要有以下几个方面:
- 作用域规则
- 重复声明/重复赋值
- 变量提升(hoisted)
- 暂时死区(TDZ)
作用域规则
let/const
声明的变量属于块作用域,只能在其块或子块中可用。而 var
声明的变量的作用域是是全局或者整个封闭函数
重复声明/重复赋值
var
可以重复声明和重复赋值let
仅允许重复赋值,但不能重复声明const
既不可以重复赋值,但不能重复声明
变量提升(hoisted)
var` 声明的变量存在变量提升,即可以在变量声明前访问变量,值为`undefined
let` 和 `const` 不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错 `ReferenceError
暂时死区(TDZ)
var
不存在暂时性死区, let
和const
存在暂时性死区,只有变量声明后,才能被访问或使用
本文参考:三分钟学前端