向ES6看齊,用更好的JavaScript(一)

衆所周知,JavaScript做爲弱類型語言,一直是精華與糟粕共存,許多「詭異」的地方咱們不得不接受並使用。其實ES6(又稱ECMAScript 2015)在2015年6月就已經正式發佈了,其中提出的不少新的特性讓JavaScript更加完善和豐富,對於前端開發者可謂一大福音。html

目前各大瀏覽器的最新版本對ES6的支持度也愈來愈高,大部分的特性都實現了( ES6 支持 )。另外如今也有不少的轉換器(如Babel),將ES6和ES7的代碼轉換爲ES5的代碼,這就意味着咱們如今就可使用這些新特性應用到咱們的項目中去。前端

本篇對ES6中的關於變量部分的新特性進行介紹,本系列傳送門:git

1 利用let和const引入塊級做用域

以往JavaScript是不具備塊級做用域的,一個函數才能構成一個做用域,局部變量在整個函數內都是有定義的,舉個栗子es6

for(var i = 0;i < 10;i++){
    }
    
    console.log(i);  //輸出10

最後在for循環以後,i變量僅用於for循環,但在卻被泄露成全局變量造成變量污染,這就是不合理的地方,經過ES6中定義的let關鍵字能夠造成僅做用於該塊做用域的局部變量github

//ES6環境下
    for(let i = 0;i < 10;i++){
    }
    
    console.log(i);  //輸出ReferenceError(未定義)

利用Babel將這段ES6代碼轉換爲ES5代碼後,其實是對ES5的代碼對其原理進行模擬達到一致的效果,所以能夠幫助咱們的理解:編程

//Babel轉換後
    for (var _i = 0; _i < 10; _i++) {
    }

    console.log(i); //輸出ReferenceError(未定義)

能夠看到,對於let聲明的局部變量,若是外部有相同定義,會經過添加下劃線將其轉換爲另外的變量,表達意思就是let將該變量僅在該塊做用域內可用。數組

再舉個栗子:瀏覽器

var a = [];
    for (var i = 0; i < 3; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[1](); //輸出3
    a[2](); //輸出3

上面的代碼的三次循環中i始終爲同一個變量,值最後爲3。a數組中的函數讀到的i也是這個值,所以都是輸出3,這跟咱們想要的結果並不一致。而利用let這個新特性能夠很好的解決這個問題:babel

//ES6環境
    var a = [];
    for (let i = 0; i < 3; i++) {
      a[i] = function () {
        console.log(i);
      };
    }
    a[1](); //輸出1
    a[2](); //輸出2
//Babel轉換後
    var a = [];
    var _loop = function _loop(i) {
        a[i] = function () {
            console.log(i);
        };
    };
    
    for (var i = 0; i < 3; i++) {
        _loop(i);
    }
    a[1](); //輸出1
    a[2](); //輸出2

此次轉換後稍微變得複雜了一些,其實是新定義一個函數,將循環變量i做爲參數傳進去,能夠這樣理解ES6中代碼經過let將三次循環中的i固定於各自的塊做用域中,互不干擾。數據結構

另外關於let要注意的幾點:

console.log(a);   //輸出ReferenceError(未定義),let聲明的變量不會變量提高,這也是規範咱們的代碼先聲明後使用。
    let a = 3;    
    let a = 4;     //錯誤,let聲明的變量不能重複定義

總之,用let讓咱們的代碼更加規範避免了不少問題,所以儘量使用let代替var.

  • let相似const也能造成塊做用域,不一樣點在於const聲明的變量爲常量,不可改變

舉個栗子:

if(true){
        const MAX = 999;
        MAX = 3;  //報錯:"MAX" is read-only
    }
    console.log(MAX);//輸出ReferenceError(未定義)

能夠看出const也造成塊級做用域,並且值不可改變,有一點要注意的是不能改變的是const類型變量存儲的東西,舉個栗子更好理解:

const person = {};
    person.name = 'vicfeel';  //正確,person存儲的是指向該對象的地址,對象內容能夠改變
    person = {};  //報錯:"person" is read-only,該地址不能改變

2 變量解析與賦值

以往多個變量的賦值咱們使用以下的方式:

var a = 1;
    var b = 2;
    var c = 3;
    
    var d = 4,e = 5,f = 5;

ES6中增長一種更便捷的多變量賦值方法:

var [a,b,c] = [1,2,3];

系統會自動對數組內元素進行對應賦值,也就是說咱們也能夠用這種方式來進行變量的聲明:

//ES6環境下
    var arr = [1,2,3];
    var [a,b,c] = arr;

咱們用Babel看一下是如何模擬的:

//Babel轉換後
    var _ref = [1, 2,3];
    var a = _ref[0];
    var b = _ref[1];
    var c = _ref[2];

能夠看到是經過數組下標依次向後賦值,下面我對多種狀況進行了賦值測試:

{
        //數量不對應
        let [a,b,c] = [1,2];
        console.log(a);  //1
        console.log(b);  //2
        console.log(c);  //undefined
        //按照上面babel轉換的理解,c = _ref[2]不存在該要素所以c爲undefined
    }
    {
        //多層數組
        let [a,[b,c],d] = [1,[2,3],4];
        console.log(a);  //1
        console.log(b);  //2
        console.log(c);  //3
        console.log(d);  //4
    }
    {
        //多層不對應
        let [a,[b,c],d] = [1,[2],3];
        console.log(a);  //1
        console.log(b);  //2
        console.log(c);  //undefined
        console.log(d);  //3
    }
    {
        //對應值非數組
        let [a,b,c] = 1;  //報錯
        let [a,b,c] = false;  //報錯,等號右邊必須爲可遍歷對象
    }

瞭解映射的原理以後,一個很好的應用場景就是交換數值,如今能夠這樣簡單的實現:

//ES6環境下
    let [x,y] = [0,1];
    [x,y] = [y,x];
  • 除此以外,ES6還在映射賦值中加入了默認值
//ES6環境下
let [a, b = 2,c] = [1]; //y無對應值時,默認值則爲2
console.log(a);  //1
console.log(b);  //2
console.log(c);  //undefined

看一下ES5的模擬

//Babel轉換後
var _ref = [1];
var a = _ref[0];
var _ref$ = _ref[1];
var b = _ref$ === undefined ? 2 : _ref$; //經過‘===’嚴格等於判斷是否爲undefined,是的話採用默認值
var c = _ref[2];   //因此是undefined
  • 針對對象的映射賦值

直接看栗子:

//ES6環境下
    var { oA, oB } = { oA: "a", oB: "b" };
    console.log(oA); //"a"
    console.log(oB); //"b"

看一下ES5的模擬

//Babel轉換後
    var _oA$oB = { oA: "aaa", oB: "bbb" };
    var oA = _oA$oB.oA;   //原來是經過同名屬性進行對應
    var oB = _oA$oB.oB;
    
    console.log(oA);
    console.log(oB);

瞭解了對應的原理以後,咱們再作一下其它狀況的測試:

{
        //順序改變
        var { oA, oB } = { oB: "a", oA: "b" };
        console.log(oA); //"b"
        console.log(oB); //"a"
    }
    {
        //數量不對應
        var { oA, oB } = { oA: "a"};
        console.log(oA); //"a"
        console.log(oB); //undefined,等號右邊對象找不到oB屬性
    }

掌握這種方法,能夠簡化不少以前操做,如獲取一個對象的某些屬性,能夠經過如下方式:

//ES6環境下
    var person = {
       name:'Vicfeel',
       age:'23',
       sex:'Male'
    }
    
    let {name,age,sex} = person;
    
    console.log(name);//Vicfeel
    console.log(age); //23
    console.log(sex); //Male

參考Reference
http://www.ecma-international.org/ecma-262/6.0/index.html
http://es6.ruanyifeng.com/
http://www.cnblogs.com/Wayou/p/es6_new_features.html
http://www.cnblogs.com/snandy/archive/2015/05/10/4485832.html

博文做者:vicfeel
博文出處:http://www.cnblogs.com/vicfeel 本文版權歸做者和博客園共有,歡迎轉載,但須保留此段聲明,並給出原文連接,謝謝合做! 若是閱讀了本文章,以爲有幫助,您能夠爲個人博文點擊「推薦一下」!

相關文章
相關標籤/搜索