ES6:let和const

407 阅读4分钟

这是我参与新手入门的第一篇文章

为什么要使用let和const

使用var来声明变量时,存在三个问题:

  • 变量声明提升
  • 可重复定义
  • 全局变量挂载到window上

var --变量声明提升

什么是变量声明提升:即可以先使用再定义,值为undefined,定义变量后会提升至函数的最顶部

例如:

console.log(a);	//undefined ===>a已声明未赋值(var a)默认得到undefined值
var a=10;

var--可重复声明

var 声明变量时可重复定义,后面定义的值会覆盖前面的值

var a=10;
var a=15;
console.log(a); // 15

var --全局变量挂载到window上

当我们使用 var 声明一个全局变量时,它会挂载到window上

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

window有很多方法和属性,当我们声明的全局变量名称和window上属性或方法同名时,可能会导致window上属性或方法不可使用

let和const的使用

let和const都是用来声明变量的,用法类似于var,但使用let/const来声明变量时,可以避免var的缺陷

let 的使用

使用let来声明变量,声明的所有变量只在let命令所在的代码块中有效

{
    let a=10;
    var b=20;
}
console.log(b);	// 20
console.log(a);	// ReferenceError: a is not defined

{
    let a=10;
    var b=20;
    console.log(a); //10
}
console.log(b); //20

不存在变量提升

console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a=10;

不可重复声明

let a=10
let a=20;	//SyntaxError: Identifier 'a' has already been declared

块级作用域

在ES6中,let为JavaScript新增了块级作用域

简单来说,let和{ }组成了块级作用域,let声明的变量只有在其所在作用域中才可以使用

{
    let a=10;
    {
        let b=20;
    }
    console.log(a); // 10
    console.log(b); // ReferenceError: b is not defined
}
function test(){
    let a=10;
    if(true){
        let a=20;
    }
    console.log(a);//10
}
{
    let a=10;
    {
        let b=20;
    }
    console.log(b);//ReferenceError: b is not defined
}

临时死区(暂时性死区)

   let a=10;
   {
       console.log(a); //ReferenceError: Cannot access 'a' before initialization
       let a=20;
   }

可以看到,当我们在全局定义了一个a,在块级作用域里也定义了一个a,首先它会在块级作用域里寻找a,不允许区外面找(let所声明的变量就绑定了这个区域,不再受外部影响),发现有,但我们在它没有声明前使用了a,这就造成了临时死区。

再来一个例子:

let a=10;
    {
        console.log(a); //ReferenceError: Cannot access 'a' before initialization
        let a=20;
        {
            console.log(a); // 20
        }
    }

可以看到第一个在第一个块级作用域里造成了临时死区

const的使用

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

const PI=3.14159;
console.log(PI); //3.14159
PI=3;	//Assignment to constant variable.

使用const声明变量时,必须给声明的变量赋值,否则会报错

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

const 的作用域与let相同,只在声明所在的块级作用域里有效

const a=10;
{
    const a=20;
    console.log(a)	//20
}
{
    const a=10;
}
console.log(a)	// a is not defined

const 同样也存在临时死区

const a=10;
{
    console.log(a)	//ReferenceError: Cannot access 'a' before initialization
    const a=20;
}

同样的,const 与 let 一样,都不允许重复声明

let a=10;
const b=20;

let a=30;	//SyntaxError: Identifier 'a' has already been declared
const b=30;	//SyntaxError: Identifier 'b' has already been declared

如何改变const声明变量的值

上面说到使用const 声明的变量一旦给定一个常量,就不能改变,那么能不能改变其声明变量的值呢?

首先我们要先了解const的本质,并不是变量的值不能改变,而是变量指向的那个内存地址不得改动。对于简单的数据(数值,字符串,布尔值),值就保存在变量指向的那个内存地址。但对于复合类型的数据(对象,数组),变量指向的内存地址,保存的只是一个指针,const 只能保证这个指针是固定的,但对于所指向的数据结构是否是可变的,就不能控制了。所以我们可以使用对象和数组的方法来改变const所声明的值。

使用对象改变const声明的值

const foo={};
foo.a=12;
console.log(foo.a);	//12
foo.a=13;
console.log(foo.a)	//13

如果把foo指向另一个内存地址,则会报错

const foo={}
foo={} //这里将foo指向了另一个对象  TypeError: Assignment to constant variable.

使用数组改变const声明的值

const a=[];
a.push(123);
console.log(a[0]);	//123
a.length=10;
console.log(a.length)	//10

同样的,与使用对象一样,改变a的内存地址时也会报错

const a=[];
a=123	//Assignment to constant variable