ES6中let、const和var的區別


 

1、基本用法

ES6 新增了let命令,用來聲明變量。

let 的用法類似於 var,但所聲明的變量只在 let 命令所在的代碼塊內有效(一個“{}”相當於一個代碼塊)

{
  let a = 123;
  var b = 123;
}

a // ReferenceError: a is not defined.
b // 123

let 在 for 循環中的運用:生成十個按鈕,每個按鈕點擊時依次彈出 1-10

for(let i=1;i<=10;i++){
    var btn=document.createElement('button');
    btn.innerText=i;
    btn.onclick=function(){
        alert(i)
    };
    document.body.appendChild(btn);
}

 

2、不存在變量提升

var 命令會發生“變量提升”現象,即變量可以在聲明之前使用,值為 undefined

let 命令改變了語法行為,它所聲明的變量一定要在聲明后使用,否則報錯。

// var 命令
console.log(a); // 輸出undefined
var a = 123;

// let 命令
console.log(b); // 報錯ReferenceError
let b = 123;

上面代碼中,

變量 用 var 命令聲明,會發生變量提升。腳本開始運行時,變量 已經存在了,但是沒有值,所以會輸出 undefined

變量 用 let 命令聲明,不會發生變量提升。在聲明它之前,變量 是不存在的,這時如果用到它,就會拋出一個錯誤。

 

3、暫時性死區

只要塊級作用域內存在 let 命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。

var c = 123;

if (true) {
  c = 'abc'; // 報錯ReferenceError
  let c;
}

上面代碼中,存在全局變量 c,但是塊級作用域內 let 又聲明了一個局部變量c,導致后者綁定這個塊級作用域,所以在 let 聲明變量前,對 賦值會報錯。

ES6 明確規定:如果區塊中存在 let 和 const 命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。

所以在代碼塊內,使用 let 命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。

 

4、不允許重復聲明

let 不允許在相同作用域內,重復聲明同一個變量。

// 報錯
function func() {
  let a = 1;
  var a = 2;
}

// 報錯
function func() {
  let a = 1;
  let a = 2;
}

// 報錯
function func() {
  var a = 1;
  let a = 2;
}

因此,不能在函數內部重新聲明參數。

function func(b) {
  let b;
}
func() // 報錯

function func(b) {
  {
    let b;
  }
}
func() // 不報錯

 

 

二、const

 

1、基本用法

const 命令用來聲明一個只讀的常量(除了引用類型,一旦聲明該常量的值就不能改變)

const p = 3.14;
p // 3.14

p = 3;
// 報錯TypeError: Assignment to constant variable.

const 一旦聲明就必須立即初始化,不能留到以后賦值。

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

const 的作用域與 let 命令相同:只在當前所在的塊級作用域內有效。

if (true) {
  const b = 123;
}

b // 報錯Uncaught ReferenceError: MAX is not defined

 

2、不存在變量提升、暫時性死區

const 命令聲明的常量也是不提升,同樣存在暫時性死區,只能在聲明的位置后面使用。

if (true) {
  console.log(c); // 報錯ReferenceError
  const c = 5;
}

 

3、不允許重復聲明

const 聲明的常量,也與 let 一樣不可重復聲明。

// 報錯
function func() {
  const a = 1;
  var a = 2;
}

// 報錯
function func() {
  const a = 1;
  const a = 2;
}

// 報錯
function func() {
  var a = 1;
  const a = 2;
}
 

4、本質

const 並非變量的值不能改,而是變量指向的那個內存地址所保存的數據不能改動。

對於簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同於常量。

但對於復合類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個指向實際數據的指針,const 只能保證這個指針是固定的,至於它指向的數據結構是不是可變的,就完全不能控制了。

const a = {};

// 為 a 添加一個屬性,可以成功
a.num = 123;
a.num // 123

// 將 a 指向另一個對象,就會報錯
a = {}; // TypeError: "foo" is read-only

下面是另一個例子。

const b = [];
b.push('Hello'); // 可執行
b.length = 0;    // 可執行
b = ['123'];     // 報錯

如果想將對象凍結,應該使用 Object.freeze 方法。

const c = { num: '123' };
Object.freeze(c);      // 凍結
c.num = '321';
console.log(c.num);    // 123

上面代碼中,常量c指向一個凍結的對象,所以改變屬性不起作用,嚴格模式時還會報錯。

除了將對象本身凍結,對象的屬性也應該凍結。下面是一個將對象徹底凍結的函數。

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

  

 

三、let、const和var的區別總結

 

var let const
在當前作用域內有效 只在當前塊級作用域內有效 只在當前塊級作用域內有效
能重復聲明 不能重復聲明 不能重復聲明
存在變量提升 暫時性死區 暫時性死區
聲明變量時可不賦值 聲明變量時可不賦值

聲明常量時需賦值

(常量除非為引用類型,否則不可修改)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM