1. 程式人生 > >es6 新增 let 與 var 比較

es6 新增 let 與 var 比較

用var的不足之處

不足一

var arr = [ ];
for(var i=0;  i<10;  i++){
    arr [i] = function(){
         alert(i)
    }
}
arr [8](); //結果:10

看程式碼,不難猜測程式碼的意圖是想給陣列a的元素賦值,每一個元素是一個函式,執行後彈出相對應的數字,比如:執行arr8;想alert出一個數字8,執行arr1; 想alert出一個數字1,依次類推。但是結果並不是我們預想的那樣。執行後實際彈出的是10;不管你執行的是arr[8]還是arr[5],或者是陣列內的其他元素,都是alert出一個數字:10。但這並不是我們想要的(不要說你故意這麼寫的,就是想彈出10就好了),為什麼是10呢(往下讀,有解釋)?至少目前我們可以知道了這是var不足的地方。

用let替換var之後 完美解決塊級作用域問題

var arr = [ ];
for(let i=0;  i<10;  i++){
    arr[i] = function(){
         alert(i)
    }
}
arr[8](); //結果:8

這是因為let宣告的變數僅僅在自己的塊級作用域起作用,出了這個塊級作用域就不起作用。

 任何一對花括號 { } 中的語句都屬於一個塊,在花括號裡面用let定義的所有變數在花括號外都是不可見的,我們稱之為塊級作用域。

不足二

用var 宣告變數的時候會出現“變數提升“的現象。

var a = 1;
(function(){
   alert(a);
   var a = 2;
})();//結果:undefined

實際執行順序如下
var a = 1;
(function(){
   var a;
   alert(a);
   a = 2;
})();

用let關鍵字來定義a;這樣a在程式碼塊內就不會提升了。那為什麼又報錯了呢,因為用let宣告的變數,在其塊級作用域內是封閉的,是不會受到外面的全域性變數a影響的,並且要先宣告再使用,所以a的值即不是1(因為不受外面的影響),也不是undefined(因為先聲明後使用),更不是2,未宣告定義就使用,只有報錯啦。

var a = 1;
(function(){
   alert(a);
   let a = 2;
})();   // 結果:報錯a未定義

使用let 需要注意

*在同一塊級作用域下,不允許重複宣告同一個變數

{
  var a =1;
  let a =2;  //報錯,因為a已經用var宣告過
}

{
  let a =1;
  let a= 2; //還是報錯,a已經用let宣告過。
}

*函式內不能用let重新宣告函式的引數

function say(word){
    let word = 'hello Jack';  //報錯:用let重新宣告word引數
   alert(word)
}
say('hello Lili');

總結:用let宣告變數只在塊級作用域起作用,適合在for迴圈使用,也不會出現變數提升現象。同一個程式碼塊內,不可重複宣告的相同變數,不可重複宣告函式內的引數。

es6也給我們提供了另一個關鍵字constconst是constant(常量)的縮寫,const和 let一樣,也是用來宣告變數的,但是const是專門用於宣告一個常量的,顧名思義,常量的值是不可改變的。以前用var宣告的變數,想怎麼改就怎麼改,同一個變數,後面的值可以輕鬆覆蓋原來的值,這次const宣告的變數,可由不得我們這麼任性地想改就改了。
const有以下幾個特點
1.不可修改
2.只有塊級作用域起作用
3.不存在變數提示,必須先聲明後使用
4.不可重複宣告同一個變數
5.聲明後必須賦值

常量還可以是一個物件,這裡在賦值過程中,我們可以分為傳值賦值和傳址賦值。

傳址:在賦值過程中,變數實際上儲存的是資料的地址(對資料的引用),而不是原始資料或者資料的拷貝。
用const來宣告一個物件型別的常量,就是傳址賦值。而不可修改的是物件在記憶體中的地址.我們修改的都是物件身上的屬性,所以並沒有違背常量不可修改的約定。

總結:const也是用於宣告一個常量,並必須賦值,聲明後不可修改,跟let一樣,只在塊級作用域起作用,不可重複宣告同一個變數,不會變數提升,宣告引用型別的常量時,要注意是傳址賦值。