ES6語法的新特性

之前面試被問到ES6新特性,箭頭函數,generator、Module等等,表示剛開始上手用ES6,目前還沒有很深入,所以這次想對ES6一些常用的特性進行整理。

let和const

主要是實現塊級作用域的。因爲在原生JS中,沒有塊級作用域。只有在函數中,才構成一個作用域,但是利用函數是可以實現一個類似於塊級作用域的。詳見這裏

不過,爲了更方便的解決類似於下面這種問題:

setTimeout(function(){
    for( var i = 0; i < 10; i++)
    {
        console.log(i);
    }
})

ES6引入了兩個新的特性,letconst

letvar有什麼區別呢?

1. `let`聲明的變量有塊級作用域,不能作爲全局對象的全局屬性被訪問,即不能通過window來訪問;
2. `let` 聲明的變量不能被重複聲明,而`var`沒有關係;
3. 像 `for(let i ......)`這種形式,會在每次迭代對`i`進行綁定。

const與let類似,唯一的不同就在於const聲明變量時必須初始化,並且初始化之後就不能再對值進行修改了,否則會報錯!

箭頭函數

箭頭函數出現的目的是爲了讓JS代碼顯得更簡潔一些。

// 六種語言中的簡單函數示例
    function (a) { return a > 0; } // JS
    [](int a) { return a > 0; }  // C++
    (lambda (a) (> a 0))  ;; Lisp
    lambda a: a > 0  # Python
    a => a > 0  // C#
    a -> a > 0  // Java

我們都知道函數式編程很普遍,而且原生JS來實現比較冗長,所以ES6新引入了一種箭頭函數的寫法。

那麼箭頭函數和普通函數有什麼區別呢?主要區別就是this的指向。在箭頭函數裏面是沒有自己的this的,裏面的this繼承自外圍作用域。而普通函數是有自己的作用域的,所以纔會在引入閉包的時候,this一般都指向全局window對象。

var obj = {
    name: 'heihei',
    sayName: function(){
        return function(){
            console.log(this);
        }
    }
}

var obj1 = {
    name: 'Hellen',
    sayName: function(){
        return ()=>{ console.log(this) };
    }
}

測試結果

另一點不同,就是箭頭函數裏面是訪問不到arguments參數列表的,所以只能通過不定參數和默認參數這兩個機制來實現。可參考這篇文章

class類

在原生ES5中,我們通常利用構造函數來創建對象,而ES6引入一種與Java,C++等更接近的方法來創建對象-class。

我們對比下構造函數和class有什麼不同。

 function Circle( radius ) {
     this.radius = radius;
     this.area = function(){
        return Math.pow(this.radius, 2) * Math.PI;
    }
 }

var c = new Circle(4);
var area = c.area();
console.log(area);
class Circle {
    constructor( radius ) {
        this.radius = radius;
    };
    area() {
        return Math.pow(this.radius, 2) * Math.PI;
    }
}

var c = new Circle(4);
var area = c.area();
console.log(area);

在寫法上,除了類的定義與構造函數不同,在用法上是相同的語法。不同的地方我們看下下面兩張圖就明白了。
這是利用構造函數構造的對象:
這裏寫圖片描述

利用Class創建的對象:
這裏寫圖片描述

Iterator(遍歷器)

在原生JS中,遍歷對象/數組有這麼幾種方式:

  • for循環
//最簡單也最直觀的循環遍歷
var arr = [2,6,5];
for(var i = 0; i < arr; i++) {
    console.log(arr[i]);
}
  • forEach
//寫法比上面的簡單很多;
//但是對於對象不使用,並且不能跳出循環,即用break,continue,return等
var arr = [2,6,5];
arr.forEach(function(data) {
    console.log(data);
})
  • for … in
//對於數組而言,是按照arr['0'],arr['1']來訪問的;
//不一定按順序訪問的
//專門適用於對象的遍歷
var arr = [2,6,5];
for(var index in arr) {
    console.log(arr[index]);
}

Iterator的出現就是爲解決上面的一些缺點出現的,爲的是給不同的數據結構產生統一的接口。只要部署一個Iterator接口,就可以爲for ... of 服務,從而實現遍歷。

Iterator的過程是這樣的:

  1. 創建一個指針對象,指向數據結構的起始位置;
  2. 調用指針對象的next方法,指針指向數據結構的第一個成員;
  3. 一次類推,直到返回數據結構的最後一個成員。

    Iteratornext方法返回的是一個對象:{ value: 成員對象的值, done:false/true }

其實在數組、字符串,以及ES6的Map和Set中,都有默認的Iterator接口,因爲有遍歷器接口,所以才能調for ... of來實現遍歷。那我們看看默認的Iterator接口是什麼樣的?
這裏寫圖片描述
上圖是一個數組對象的原型鏈上的方法。其中有一個Symbol.iterator函數,這個函數其實就是一個遍歷器接口。我們來使用一下:

這裏寫圖片描述

這個函數返回的是一個對象表示數組Iterator。並且在這個對象裏有next方法,這跟我們前面說的是相吻合的。
這裏寫圖片描述

每一次調用next方法之後,就會返回一個對象,value表示數據結構當前位置的數值,done表示是否到最後一個成員。

所以只要一個數據結構,有這個接口,都可以調用for…of方法來實現。
這裏寫圖片描述
這裏寫圖片描述

因爲Object裏面沒有Iterator接口,所以不能直接用for…of實現遍歷,那怎麼辦呢?
其實可以先調Object.keys將對象轉成數組。
這裏寫圖片描述

後期還會續上generator生成器對象(迭代器對象)以及modules等新特性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章