Symbol.iterator和for…of

Symbol.iterator

ECMAScript 2015的幾個(gè)補(bǔ)充,并不是新的內(nèi)置實(shí)現(xiàn)或語法,而是協(xié)議。這些協(xié)議可以被任何遵循某些約定的對(duì)象來實(shí)現(xiàn)。

ES6新增了兩個(gè)協(xié)議:

  1. 可迭代協(xié)議:對(duì)象必須具有Symbol.Iterator屬性,屬性值為一個(gè)函數(shù),當(dāng)這個(gè)對(duì)象被迭代時(shí),就會(huì)調(diào)用該函數(shù),返回一個(gè)迭代器。
  2. 迭代器協(xié)議:描述了迭代器對(duì)象的具體規(guī)則。

what

  1. 在Js中迭代器對(duì)象實(shí)現(xiàn)了可迭代協(xié)議,迭代器對(duì)象由Symbol.iterator屬性的值返回。
  2. Symbol.iterator屬性的值是一個(gè)函數(shù),它返回一個(gè)迭代器對(duì)象。
  3. 迭代器指的是擁有next方法的對(duì)象。
  4. 該next方法必須返回一個(gè)帶有value和done的對(duì)象。

why

除了ArrayObject,ES6新增了數(shù)據(jù)結(jié)構(gòu)Set、Map,這樣的話,JS中就有了四種表示集合的數(shù)據(jù)結(jié)構(gòu)。這時(shí),js就需要一種統(tǒng)一的用來遍歷這些集合的接口。迭代器Iterator就是這個(gè)接口,具體表現(xiàn)在各數(shù)據(jù)結(jié)構(gòu)的Symbol.Iterator屬性上。

注意:對(duì)象Object沒有這個(gè)接口,因?yàn)閷?duì)象是非線性的數(shù)據(jù)結(jié)構(gòu),一旦部署這個(gè)接口相當(dāng)部署一種線性轉(zhuǎn)換。

how

1.數(shù)據(jù)結(jié)構(gòu)默認(rèn)的Iterator接口,可以通過for...of使用。解構(gòu)賦值用的也是Iterator接口。

let obj = {
    [Symbol.iterator] () {
    let val = 0
        return {
            next () {
                if (val > 5) {
                    return {done: true}
                }
                return {value: val++,done: false}
            }
        }
    }
}

for (let val of obj) {console.log(val)}

let iterator = obj[Symbol.iterator]
iterator.next()
iterator.next()
iterator.next()
iterator.next()
iterator.next()
iterator.next()

2.使用generator函數(shù)

let obj = {
    [Symbol.iterator]: function* () {
        yield 1;
        yield 2;
        yield 3;
    }
}
for (let val of obj) {console.log(val)}

which

下面這些數(shù)據(jù)結(jié)構(gòu)默認(rèn)實(shí)現(xiàn)了迭代器接口

  1. 字符串
  2. 數(shù)組
  3. Map
  4. Set
  5. NodeList
  6. arguments
  7. TypedArray

for...of

what

for...of語法借鑒自C++、Java、C# 和 Python,作為用來遍歷所有數(shù)據(jù)結(jié)構(gòu)的統(tǒng)一方法。

why

和迭代器一起設(shè)計(jì),迭代器主要供for...of消費(fèi)

how

let arr = ['a', 'b', 'c'];
for (let pair of arr) {
  console.log(pair);
}
for (let pair of arr.entries()) {
  console.log(pair);
}
for (let pair of arr.keys()) {
  console.log(pair);
}
for (let pair of arr.values()) {
  console.log(pair);
}

compare

for的缺陷:

// 取值比較麻煩
for (var index = 0; index < myArray.length; index++) {
  console.log(myArray[index]);
}

為了解決for麻煩的問題,引入的forEach

// 問題:無法跳出循環(huán)
myArray.forEach(function (value) {
  console.log(value);
});

for...in的缺陷:

1. 會(huì)遍歷所有可枚舉的屬性,包括原型鏈(是否可遍歷只和該對(duì)象上的屬性enumerable有關(guān),和在哪里無關(guān))
2. 除了數(shù)組中的元素,會(huì)遍歷數(shù)組的私有屬性
3. 專門為對(duì)象設(shè)計(jì)
var a = []
Object.getOwnPropertyDescriptor(a.__proto__,'find') // false 這些原生方法默認(rèn)enumerable為false

屬性描述符中的configurable

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容