let 和 const 命令

411 阅读2分钟

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 命令声明的全局变量不属于顶层对象的属性。