let 命令
基本用法
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(`a[i]:${i}`);
};
}
a[6](); // 10,i作用域是全局,全局只有一个i
var b = [];
for (let j = 0; j < 10; j++) {
b[j] = function () {
console.log(`b[j]:${j}`);
};
}
b[6](); // 6,j作用域是本次循环,所以每次循环的j都是新变量
for (let k = 0; k < 3; k++) {
let k = "abc";
console.log(k);
} // 打印三次"abc",函数内部的k和循环变量k不在同一个作用域,各自有单独的作用域
不存在变量提升
console.log(a); // undefined
var a = 2;
console.log(b); // 报错ReferenceError
let b = 2;
暂时性死区
块级作用域内 let 声明的变量,作用域绑定为当前作用域,不会受外部影响,即在代码块内,使用 let 声明变量前,该变量都不可用,若使用该变量会报 ReferenceError 错误。
var temp = 123;
if (true) {
// typeof 不是百分之百安全的操作
typeof temp; // 报错ReferenceError
typeof abc; // undefined
temp = "abc"; // 报错ReferenceError
let temp;
}
function bar1(x = y, y = 2) {
return [x, y];
}
bar1(); // 报错ReferenceError
function bar2(x = 2, y = x) {
return [x, y];
}
bar2(); // 不报错,[2, 2]
var a = a; // 不报错
let b = b; // 报错ReferenceError
不允许重复声明
let 不允许在同一作用域内重复声明同一个变量名
function func(arg) {
// 报错
let a = 10;
var a = 1;
// 报错
let arg;
{
let arg; // 不报错
}
}
const 命令
基本用法
const 一旦声明变量,就必须立即初始化,不能留到以后赋值。其声明的变量只在所在的块级作用域内有效,不会提升,也存在暂时性死区,只能在声明后使用,不可重复声明。
本质
const 本质上是保证变量指向的那个内存地址不得改动,而不是变量的值不得改动。对于简单类型的数据(数值、字符创、布尔值),值就保存在变量指向的内存地址中,因此等于常量。对于复合类型的数据(对象、数组),变量指向的内存地址保存的只是一个指针,const 只能保证这个指针不变,不能保证它指向的数据结构是否不变。
const foo = {};
foo.prop = 123; // 添加pro属性,可以成功
foo = {}; // 将foo指向另一个对象,失败,报错TypeError
const a = [];
a.push("Hello"); // 成功
a.length = 0; // 成功
a = ["chen"]; // 报错
顶层对象的属性
顶层对象在浏览器中指的是 window 对象,在 Node 环境中指的是 global 对象。在 ES6 中,var 命令和 function 命令声明的全局变量依旧是顶层对象的属性; let 命令、const 命令、class 命令声明的全局变量不属于顶层对象的属性。