es6中提供將其餘數據轉化爲數組的快捷API

Array.from

Array.from方法主要用於將Array-Like Obj(包括DOM對象document.querySeletorAll(...))和iterable對象轉化爲數組。和下面說的spread操做符相比,它能夠直接將Array-Like obj進行轉化,而不須要這個類數組對象是iterable的。javascript

function add() {
        let arr = [].slice.apply(arguments);
    }
    
    function add() {
        let arr = Array.from(arguments);
    }
    
    --------
    
    //經過這個方法,將`Array-Like Obj`直接轉化爲了Array.所以可使用Array提供的方法
    var lis = Array.from(document.querySelectorAll('li'));
    lis.forEach(function(dom, index) {
        // do something
    });

此外,Array.from還接收第二個參數,和Array.prototype.map方法相似.java

function foo() {
        let args = Array.from(arguments, item => item + 1);
        console.log(args);
    }
    
    foo(1, 2, 3);    // 2 3 4

能夠利用Array.from來返回字符串的長度,由於在js裏面,大於uFFFF的Unicode字符長度是算爲2個的。es6

//這裏是由於String類型的數據是iterable的,因此能夠被Array.from轉化爲數組
    function countLen(str) {
        return Array.from(str).length;
    }

...args (rest參數)

rest參數主要是在定義函數的時候,用以獲取函數多餘的函數,這樣在函數內部便可不使用arguments對象.由於rest參數是一個數組,所以能夠直接利用Array提供的相應的API。數組

好比一個求和的函數:
    
    之前的寫法:
    function add() {
        [].reduce.call(arguments, function(x, y) {
            return x + y;
        });
    }
    
    es6:
    
    function add(...args) {
        args.reduce((x, y) => x + y);
    }

還可使用rest參數搭配解構賦值使用:數據結構

function foo(...args) {
        let [x = 0, y = 2] = args;
        //....
    }

在使用箭頭函數的時候:app

function foo(...args1) {
        var obj = {
            add: () => {
                console.log(arguments);
            }
        }
        obj.add(1, 2, 3);
    }
    
    foo(4, 5, 6);   //最後輸出 [4, 5, 6]

這裏由於箭頭函數沒有自身的this,它內部的this事實上是由所在的做用域提供的。所以arguments對象也是所在做用域提供的。因此會輸出[4, 5, 6]dom

這裏若是要正確獲取obj.add(1, 2, 3)提供的參數,可使用rest參數:函數

function foo(...args1) {
        var obj = {
            add: (...args2) => {
                console.log(args2);
            }
        }
        obj.add(1, 2, 3);
    }
    
    foo(4, 5, 6);    //最後輸出  [1, 2, 3]

spread操做符

spread操做符用以將一個iterable(部署了[Symbol.Iterator]接口)的value轉化爲用逗號分隔的參數序列。this

哪些數據結構部署了[Symbol.Iterator]的接口呢:prototype

  • Array

  • Maps

  • Sets

  • 部署了[Symbol.Iterator]接口的Array-like obj(arguments)

  • Dom data Structures

  • String

對象字面量:

var obj = {
        name: 'xl',
        age: 20
    }
    
    console.log(...obj);

是沒有部署[Symbol.Iterator]接口的,所以使用spread操做符時會報錯:

Uncaught TypeError: (var)[Symbol.iterator] is not a function(…)

同時,普通的Array-likeObj:

var obj = {
        0: 'x',
        1: 'l',
        length: 2
    }

一樣使用spread操做符時會報錯。若是將這個Array-likeObj轉化爲Array,則須要手動在這個obj上配置[Symbol.iterator]接口:

var obj = {
        *[Symbol.iterator]() {
            yield 'x';
            yield 'l'
        }
    }
    
    console.log(...obj);    //  x l

或者換用其餘的API:

方式1: let arr1 = Array.from(obj);
    
    方式2: let arr1 = [].slice.apply(obj);

像以前計算一組數當中最大的數:

Math.max.apply(null, [1, 2, 3]);
    
    --->>> Math.max(...[1, 2, 3]);      // 3

此外,spread操做符還能將部署了[Symbol.Iterator]接口的類數組對象轉爲用逗號分隔的參數序列:

var li = document.querySeletorAll('li');
    
    [...li];   //轉化爲數組後就能夠利用數組提供的API進行其餘的操做

Symbol.Iterator

上面屢次提到了iterable或者是部署了[Symbol.iterable]方法的value,事實上它們說的都是同一個意思,一個話去歸納的話就是: iterable的數據結構提供了統一的接口供外部去獲取自身的元素。它所提供的這個接口方法名稱就是[Symbol.iterator].

上文已經提到了哪些數據結構部署了[Symbol.Iterator]的接口。

哪些方法會調用[Symbol.Iterator]接口呢:

  • 解構賦值

let [a, b] = [1, 2];
  • for...of循環

for(let value of [1, 2]) {
    
    }
  • spread操做符

[...document.querySelectorAll('li')]
  • Promise.all()/Promise.race()

Promise.all(iterableOverPromises).then(···);
    Promise.race(iterableOverPromises).then(···);
  • yield*

yield* anIterable

關於iterableiterator單獨用一篇文章來寫吧。

相關文章
相關標籤/搜索