let 和 const 命令

在这里插入图片描述

1. let 和 const 命令共同点

letconst 命令异同点如下:

在这里插入图片描述


1.1 声明的全局变量,不属于顶层对象的属性

顶层对象,在浏览器环境中指的是 window 对象,在 Node 环境中指的是 global 对象。


1️⃣ 在 ES5 中,顶层对象的属性与全局变量是等价的。

var name = '小鱼'
window.age = 18

console.log(window.name);  // '小鱼'
console.log(age);  // 18

上面代码中,顶层对象的属性赋值与全局变量的赋值是同一件事。说明通过 var 声明的全局变量会自动挂载到 window 对象下(成为 window 对象的属性)。


2️⃣ 在 ES6 中,为了保持兼容性,varfunction 命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,letconstclass 命令声明的全局变量,不属于顶层对象的属性。

var name = '小鱼';
let age = 18;
const PI = 3.14

console.log(window.name);  // '小鱼'
console.log(window.age);   // undefined
console.log(window.PI);    // undefined

上面代码中,全局变量 agelet 命令声明,所以它不是顶层对象的属性,返回 undefined


1.2 声明的变量只在它所在的代码块有效

{
	var v_name = '小鱼';
	let l_name = '小熊';
	const PI = 3.14;

	console.log(l_name);  // '小熊'
	console.log(PI);      // 3.14
}

console.log(v_name);  // '小鱼'
console.log(l_name);  // Uncaught ReferenceError: l_name is not defined
console.log(PI);      // Uncaught ReferenceError: PI is not defined

上面代码中,在代码块之外访问 varletconst 命令声明的变量,结果 var 声明的变量返回了正确值,letconst 声明的变量报错。这表明,letconst 命令声明的变量只在它所在的代码块内有效。

🚨 注意:在 for 循环中,设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {
  let i = "小鱼";
  console.log(i);
}

// '小鱼' x3

上面代码中,输出了3次 小鱼。这表明函数内部的变量 i 与循环变量 i 不在同一个作用域,有着各自单独的作用域(同一个作用域不可使用 let 重复声明同一个变量)。


1.3 不存在变量提升

1️⃣ var 命令会发生 变量提升 现象,即变量可以在声明之前使用,值为 undefined

console.log(name);  // undefined
var name = '小鱼';

// 相当于下面代码
var name;
console.log(name);
name = '小鱼';

上面代码中,变量用 var 命令声明,会发生变量提升,即脚本开始运行时,变量 name 已经存在,但是没有值,所以会输出 undefined


2️⃣ letconst 命令声明的变量一定要在声明后使用,否则报错。

console.log(l_name);  
// ReferenceError: Cannot access 'l_name' before initialization
// 在初始化之前无法访问“l_name”
console.log(PI);
// ReferenceError: Cannot access 'PI' before initialization
// 在初始化之前无法访问“PI”

let l_name = '小熊';
const PI = 3.14;

console.log(l_name);  // '小熊'
console.log(PI);      // 3.14

上面代码中,letconst 命令声明的变量不会发生变量提升。这表明在声明变量之前前,变量是不存在的,这时如果用到它,就会抛出一个错误。


1.4 暂时性死区

ES6 规定,如果块级作用域中存在 letconst 命令,这些命令声明的变量就绑定了这个区域。凡是在声明变量之前操作(获取或赋值)这些变量,就会报错。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)

{
  // TDZ 开始
  console.log(l_name);  // ReferenceError: Cannot access 'l_name' before initialization
  l_name = '小熊';  // ReferenceError: Cannot access 'l_name' before initialization

  let l_name;  // TDZ 结束
  console.log(l_name);  // undefined

  l_name = '小鱼';
  console.log(l_name);  // '小鱼'
}

上面代码中,在 let 命令声明变量之前,都属于变量 l_name 的死区。


1.5 不允许重复声明

letconst 命令不允许在相同作用域内,重复声明同一个变量。

{
  let name = '小鱼';
  var name = '小熊';  // SyntaxError: Identifier 'name' has already been declared
}

{
  const NAME = '小鱼';
  var NAME = '小熊';  // SyntaxError: Identifier 'name' has already been declared
}

因此,不能在函数内部重新声明参数

// 报错
function fun(name, age) {
  let name;  // SyntaxError: Identifier 'name' has already been declared
}

// 不报错
function fun(name, age) {
  {
    let name;
  }
}

2. const 命令

2.1 声明的变量是只读的

const 声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.14;
console.log(PI);  // 3.14

PI = 3;  // TypeError: Assignment to constant variable.

const 声明的变量不得改变值,这意味着,const 一旦声明变量,就必须立即初始化,不能留到以后赋值。

const PI;  // SyntaxError: Missing initializer in const declaration

2.2 不允许更改的是变量保存的内存地址

const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

const obj = {};

obj.name = '小鱼';
obj.age = 18;

obj = {};  // TypeError: Assignment to constant variable.

上面代码中,常量 obj 储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把 obj 指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性。


3 参考资料

阮一峰 ES6 入门

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值