var、let和const的区别

本文详细探讨了JavaScript中的var、let和const关键字的差异。var声明的变量存在变量提升和作用域限制,可以重复声明;let提供块级作用域,不提升且不能在同一作用域内重复声明,还有暂时性死区;const声明常量,一旦初始化不可更改,但其指向的对象属性可以修改。在for循环中,let解决了var声明迭代变量的问题,而const不能用于声明迭代变量。

目录

一、var关键字

1.var声明作用域

2.var声明提升 

3. var操作符可以重复声明同一个变量

二、let关键词 

1.let声明作用域

2.不能在同一个块内重复声明 

 3.暂时性死区

 4.for循环中的let声明

 三、const关键字

1.声明并初始化 

2.不能使用const来声明迭代变量

 


一、var关键字

1.var声明作用域

使用var操作符声明的变量会成为包含它的函数的局部变量:

function fun() {
	var variable = "hello";
	console.log(variable);
};

fun(); // 结果是hello
console.log(variable); 
// 结果是Uncaught ReferenceError: variable is not defined

这里,variable变量是在fun函数内部定义的,调用该函数会创建这个变量并初始化值,调用过后变量随即被销毁,因此在函数外部访问会报错。

2.var声明提升 

使用var操作符声明的变量会自动提升到它所在的函数作用域的顶部:

function fun() {
	console.log(variable); // 在这里先访问
	var variable = "hello";
}
fun(); // 结果是 undefined

 之所以不会报错,是因为 ECMAScript 运行时把它看成等价于如下代码:

function fun() {
	var variable;
	console.log(variable); 
	variable = "hello";
}
fun(); // 结果是 undefined

 这就是所谓的“提升”(hoist),也就是把所有变量声明(var操作符声明的)都拉到函数作用域的顶部。

3. var操作符可以重复声明同一个变量

var variable = 1;
var variable = "hello";
var variable = true;
console.log(variable); // true
 

二、let关键词 

1.let声明作用域

let声明的范围是块级作用域 (一对{ }内)。
注意:这里就和 var 声明的作用域有区别了。

// var 声明变量
if (true) {
	var variable = "hello";
	console.log(variable); // hello
}
console.log(variable); // hello

// let 声明变量
if (true) {
	let variable = "hello";
	console.log(variable); // hello
}
console.log(variable); 
//  Uncaught ReferenceError: variable is not defined

let声明的变量之所以不能在if块外被引用,是因为它的作用域仅限于if块内部。

块级作用域是函数作用域的子集,因此适用于 var 的作用域限制同样也适用于 let。

2.不能在同一个块内重复声明 

和var又一个区别是,let操作符不允许在同一个块作用域中重复声明变量。

let variable;
let variable; //Uncaught SyntaxError: Identifier 'variable' has already been declared
// 会报错:'variable' 已经声明过

 3.暂时性死区

与var又一个很重要的区别是,let声明的变量不会在它所在的作用域中被提升,对暂时性死区可以理解为,在代码块内,使用let声明变量之前,该变量都是不可用的。

console.log(variable); // undefined  var 存在变量声明提升
var variable = 1;

console.log(variable1);// 直接报错
let variable1 = 1; 

 4.for循环中的let声明

在 let 出现之前,for 循环定义的迭代变量会渗透到循环体外部:

for (var i = 0; i < 5; ++i) { 
 // 循环逻辑 
} 
console.log(i); // 5

 改成使用 let 之后,这个问题就消失了,因为迭代变量的作用域仅限于 for 循环块内部:

for (let i = 0; i < 5; ++i) { 
 // 循环逻辑
} 
console.log(i); // ReferenceError: i 没有定义

 在使用 var 的时候,最常见的问题就是对迭代变量的奇特声明和修改:

for (var i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 你可能以为会输出 0、1、2、3、4 
// 实际上会输出 5、5、5、5、5

 之所以会这样,是因为在退出循环时,迭代变量保存的是导致循环退出的值:5。在之后执行超时逻辑时,所有的 i 都是同一个变量,因而输出的都是同一个最终值。

 而在使用 let 声明迭代变量时,JavaScript 引擎在后台会为每个迭代循环声明一个新的迭代变量。每个 setTimeout 引用的都是不同的变量实例,所以 console.log 输出的是我们期望的值,也就是循环执行过程中每个迭代变量的值。 

for (let i = 0; i < 5; ++i) { 
 setTimeout(() => console.log(i), 0) 
} 
// 会输出 0、1、2、3、4 

 三、const关键字

const 的行为与 let 基本相同(块级作用域、暂时性死区、不允许重复声明等)

1.声明并初始化 

const与let 和 var 的唯一 一个重要的区别是:使用const关键字声明变量时必须要初始化值,并且不可以修改。

const variable; // 报错:Missing initializer in const declaration
// ----------------
const variable1;
variable1 = 1; // 报错:Missing initializer in const declaration
// ----------------
const variable2 = 1;
variable2 = true; // 报错: Assignment to constant variable.
// ----------------
const variable3 = 1;
console.log(variable3); // 1 正确

 注意:const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制

const person = {}; 
person.name = 'Matt'; // ok

这样是完全可以的,这里const指向的是person的地址值,改变其内部属性并不会改变其地址值。 

2.不能使用const来声明迭代变量

for (const i = 0; i < 10; ++i) {} // TypeError:给常量赋值

因为迭代变量会自增,所以会报错。

不过,如果你只想用 const 声明一个不会被修改的 for 循环变量,那也是可以的。也就是说,每次迭代只是创建一个新变量。这对 for-of 和 for-in 循环特别有意义:

for (const key in {a: 1, b: 2}) { 
 console.log(key); 
} 
// a, b 
for (const value of [1,2,3,4,5]) { 
 console.log(value); 
} 
// 1, 2, 3, 4, 5 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值