JavaScript 中 var、let、const区别

本文详细对比了JavaScript中var、let和const声明变量的区别,包括重复声明、变量提升、暂时性死区、window对象的属性、块级作用域以及是否可修改。建议优先使用const和let以提高代码规范性和避免意外行为。
摘要由CSDN通过智能技术生成

JavaScript 中 var、let、const 三种声明变量的方式之间的具体差别


前言

在ES6出现之前在 JavaScript 中声明变量都是用 var 来声明;在ES6出现之后,一般会使用 let 代替 var来进行变量的声明,使用 const 来进行常量的声明。

varletconst
重复声明Y
变量提升Y
暂时性死区YY
window 对象的属性和方法Y
块级作用域YY
定义后可修改YY

1. 重复声明

/* var */
var a = 123
var a = 321
console.log(a); // 打印结果: 321 新的会覆盖旧的

/* let */ 
let b = 123
let b = 321
console.log(b); // 报错:Uncaught SyntaxError: Identifier 'b' has already been declared

/* const */
const c = 123
const c = 321
console.log(c); // 报错:Uncaught SyntaxError: Identifier 'c' has already been declared
  • 总结 1:在同一个块级作用域下,var 可以重复声明同一个变量,但 let 和 const 不能。

2. 变量 提升(hoisting)

/* var */
console.log(a); // 打印结果: undefined
var a = 123

// 逻辑上等于
var a
console.log(a);//undefined
a = 123

/* let */  
console.log(b); // 报错:Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 123

/* const */
console.log(c); // 报错:Uncaught ReferenceError: Cannot access 'c' before initialization
const c = 123
  • 总结 2:变量提升是指无论 var 出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在当前的整个作用域中任何地方都可以访问得到这个变量 。注意只有变量声明才会提升,但变量赋值并不会提升。let 和 const 不存在变量提升。

3. 暂时性死区(临时死区 Temporal Dead Zone,简写为 TDZ)

/* var */
var a = 1;
console.log(a); // 1
console.log(b); // undefined
var b = 2;

/* let */
let a = 1;
console.log(a); // 1
console.log(b); // 报错:Uncaught ReferenceError: Cannot access 'b' before initialization
let b = 2;

/* const */
const a = 1;
console.log(a); // 1
console.log(b); // 报错:Uncaught ReferenceError: Cannot access 'b' before initialization
const b = 2;

var a = 123
{
    console.log(a); // U123
    var a = 312
}

let a = 123
{
    console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
    let a = 312
}
  • 总结 3:暂时性死区和变量提升有点相类似,如果区块中存在let 和 const 命令,这个区块对这些命令声明的变量或常量,一开始就形成一个作用域。let 和 const 的变量不能在声明之前被使用,var 可以。暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码被执行过后,才可以获取和使用该变量,也就是先声明,再使用。

4. window 对象的属性和方法(全局作用域中)

var a = 123
console.log(window.a); // 123
function fn() {
    console.log('function');
}
window.fn(); // function
console.log(window.fn === fn); // true

let b = 123
console.log(window.b); // undefined
let c = fn
console.log(window.c === fn); // false
  • 总结 4:在全局作用域中,var 声明的变量和通过 function 声明的函数,会自动变成 window 对象的属性或方法,但是 let 和 const 不会。

5. 块级作用域

/* var */
for (var i = 0; i < 3; i++) {
    console.log(i); // 1 2 3
}
console.log(i); // 3

/* let */
for (let i = 0; i < 3; i++) {
    console.log(i); // 1 2 3
}
console.log(i); // 报错:Uncaught ReferenceError: i is not defined

/* const */
if (true) {
    var a = 'asd'
    const c = 'zxc'
}
console.log(a) // asd
console.log(c) // Uncaught ReferenceError: c is not defined

/* 这里涉及相关的只是点 */
// 作用域链:内层作用域 --> 外层作用域 --> ... --> 全局作用域

// 作用域有三种:全局作用域、块级作用域、函数作用域

// 块级作用域有哪些:
// {}
// for(){}
// while(){}
// do{}while()
// if(){}
// switch(){}

// 函数作用域:
// function(){}

// let animal={} 这里对象的{},不构成作用域的
  • 总结 5:let 和 const 的声明会形成块级作用域,var 不会。

6. 定义变量后可修改

/* 简单数据类型 */
var a = 111
a = 999
console.log(a); // 999

let b = 222
b = 888
console.log(b); // 888

const c = 333
c = 777
console.log(c); // 报错:Uncaught TypeError: Assignment to constant variable.

/* 复合数据类型 */
const animal = {}
animal.dog = '二哈'
animal.cat = '大橘'
console.log(animal) // {dog: "二哈", cat: "大橘"}
animal = { bird: '鹦鹉' } // 报错:Uncaught TypeError: Assignment to constant variable.

const arr = ['foo', 'asd']
arr.push('zxc')
arr[3] = '123'
arr.shift('asd')
console.log(arr) // ["asd", "zxc", "123"]
  • 总结 6:var、let 定义变量之后可以修改,而 const 表面上像是声明一个“常量”,但 const 并不是保证变量的值不得改动,而是指变量指向的内存地址不得改变。对于简单数据类型(Number、String、Boolean),变量就指向的保存了对应值的内存地址,因此等同于常量;而对于复合数据类型(主要是对象和数组),变量只是保存了指向堆内存的地址,至于堆内的数据是不是可变的,就不能控制了。

结论:

为了规范代码书写,减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为,声明变量最好优先使用 const 、let 命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值