重温 JavaScript 之变量声明

本文详细介绍了JavaScript中let和var的区别,包括它们在作用域、变量提升、重复声明和暂时性死区等方面的不同。let关键字引入了块级作用域,避免了变量提升和变量污染,而var则允许变量在作用域内重复声明。文章通过实例展示了let如何解决for循环中变量i的问题,并提出了两种解决方案。最后,强调了let在块级作用域中的重要性。
摘要由CSDN通过智能技术生成

var 和 let 关键字

1. 属于顶层对象window

下面代码说明:var 声明的全局变量时 window 的属性,是可以通过 window.变量名 的方式访问的。
let 声明的全局变量不是 window 的属性,不可以通过 window.变量名的方式访问。

var a = 5;
console.log(window.a);  // 5

let a = 5;
console.log(window.a);  // undefined

2. 变量重复声明

下面代码说明: var 可以重复定义,而 let 不可以重复定义。

var a = 5;
var a = 6;
console.log(a) // 6

let a = 5;
let a = 6;
// 报错:VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared at <anonymous>:1:1

3. 变量提升

下述代码中, a 的调用在声明之前,所以它的值是 undefined,而不是 Uncaught ReferenceError。实际上因为 var 会导致变量提升
说明: var 关键字定义变量时,存在变量提升
let 关键字不存在变量提升

console.log(a)  // undefined
var a = 2;
// 等价写法
var a;
console.log(a)  // undefined
a = 2;

function foo() {
    console.log(a)
    var a = 5
}
foo() //undefined

function foo() {
    var a
    console.log(a)
    a = 5
}
foo() //undefined

function foo() {
    console.log(a)
    let a = 5
}
foo()  // 报错:Uncaught ReferenceError: Cannot access 'a' before initialization

console.log(b)  // 报错
let b = 2;

4. 暂时性死区

只要块级作用域内存在 let 命令,它所声明的变量就绑定在了这个区域,不再受外部的影响。
下面代码中,存在全局变量 a ,但是块级作用域内 let 又声明了一个局部变量 a ,导致后者绑定这个块级作用域,所以在 let 声明变量前,对 a 赋值会报错。
ES6 明确规定,如果区块中存在 letconst 命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”

var = 5;
if(true){
	a = 6;
	let a;
}

有时“暂时性死区”比较隐蔽,比如:

function foo(b = a, a = 2) {
    console.log(a, b)
}
foo()
// Uncaught ReferenceError: Cannot access 'a' before initialization

5. 块级作用域

let 实际上为 JavaScript 新增了块级作用域

{
	let a = 5;
}
console.log(a)  // undefined

a 变量是在代码块 {} 中使用 let 定义的,它的作用域是这个代码块内部,外部无法访问。
我们再看一个项目中很常见的 for 循环:

for (var i = 0; i < 3; i++) {
    console.log('循环内:' + i) // 0、1、2
}
console.log('循环外:' + i) // 3

如果改成 let 会怎么样呢?

for (let i = 0; i < 3; i++) {
    console.log('循环内:' + i) // 0、1、2
}
console.log('循环外:' + i) // ReferenceError: i is not defined

继续看下面两个例子的对比,这时 a 的值又是多少呢?

if (false) {
    var a = 5
}
console.log(a) // undefined
if (false) {
    let a = 5
}
console.log(a)  // Uncaught ReferenceError: a is not defined

思考

请问 i 的值是多少?

for(var i = 0; i < 3; i++){
	setTimeout(function() {
		console.log(i)
	})
}
// 输出结果:3、3、3

答案是3次3。
但我希望的值是0、1、2,也就是每次保存住循环时候 i 的值,应该如何做呢?

方案1:闭包

for(var i = 0; i < 3; i++){
	(function(j){
		setTimeout(function() {
			console.log(j)  // 0、1、2
		})
	})(i);
}

方案2:使用 let

for(let i = 0; i < 3; i++){
	setTimeout(function() {
		console.log(j)  // 0、1、2
	})
}

总结

  • 使用let声明的变量:
  • 不属于顶层对象window
  • 不允许重复声明
  • 不存在变量提升
  • 暂时性死区
  • 块级作用域
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

愈彬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值