盤點(diǎn)JavaScript中的Iterable object(可迭代對(duì)象)
一、概念
可迭代(Iterable) 對(duì)象是數(shù)組的泛化。這個(gè)概念是說任何對(duì)象都可以被定制為可在 for..of 循環(huán)中使用的對(duì)象。
數(shù)組是可迭代的。但不僅僅是數(shù)組,很多其他內(nèi)建對(duì)象也都是可迭代的。
二、通過創(chuàng)建一個(gè)對(duì)象,就可以輕松地掌握可迭代的概念。
1.字符串是可迭代的
數(shù)組和字符串是使用最廣泛的內(nèi)建可迭代對(duì)象。
對(duì)于一個(gè)字符串,for..of 遍歷它的每個(gè)字符:
for (let char of "test") {
// 觸發(fā) 4 次,每個(gè)字符一次
alert( char ); // t, then e, then s, then t
}
對(duì)于代理對(duì)(surrogate pairs),它也能正常工作!
(譯注:這里的代理對(duì)也就指的是 UTF-16 的擴(kuò)展字符)
let str = '????';
for (let char of str) {
alert( char ); // ??,然后是 ??
}
2. 顯式調(diào)用迭代器(如何顯式地使用迭代器?)。
將會(huì)采用與 for..of 完全相同的方式遍歷字符串,但使用的是直接調(diào)用。這段代碼創(chuàng)建了一個(gè)字符串迭代器,并“手動(dòng)”從中獲取值。
let str = "Hello"; // 和 for..of 做相同的事//
for (let char of str)
alert(char);
let iterator = str[Symbol.iterator]();
while (true) {
let result = iterator.next();
if (result.done) break;
alert(result.value); // 一個(gè)接一個(gè)地輸出字符
}
注:
很少需要這樣做,但是比 for..of 給了更多的控制權(quán)。例如,可以拆分迭代過程:迭代一部分,然后停止,做一些其他處理,然后再恢復(fù)迭代。
3. Array.from
有一個(gè)全局方法 Array.from 可以接受一個(gè)可迭代或類數(shù)組的值,并從中獲取一個(gè)“真正的”數(shù)組。然后就可以對(duì)其調(diào)用數(shù)組方法了。
例:
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike); // (*)
alert(arr.pop()); // World(pop 方法有效)// World(pop 方法有效)
運(yùn)行結(jié)果:
在 (*) 行的 Array.from 方法接受對(duì)象,檢查它是一個(gè)可迭代對(duì)象或類數(shù)組對(duì)象,然后創(chuàng)建一個(gè)新數(shù)組,并將該對(duì)象的所有元素復(fù)制到這個(gè)新數(shù)組。
現(xiàn)在用 Array.from 將一個(gè)字符串轉(zhuǎn)換為單個(gè)字符的數(shù)組:
let str = '????';// 將 str 拆分為字符數(shù)組
let chars = Array.from(str);alert(chars[0]); // ??
alert(chars[1]); // ??
alert(chars.length); // 2
運(yùn)行結(jié)果:
注:
與 str.split 方法不同,它依賴于字符串的可迭代特性。
因此,就像 for..of 一樣,可以正確地處理代理對(duì)(surrogate pair)。(譯注:代理對(duì)也就是 UTF-16 擴(kuò)展字符。)
另外一種表達(dá)方式
技術(shù)上來說,它和下文做了同樣的事:
let str = '????';
let chars = []; // Array.from 內(nèi)部執(zhí)行相同的循環(huán)
for (let char of str) {
chars.push(char);
}
alert(chars);
運(yùn)行結(jié)果:
但 Array.from 精簡(jiǎn)很多。
甚至可以基于 Array.from 創(chuàng)建代理感知(surrogate-aware)的slice 方法(譯注:也就是能夠處理 UTF-16 擴(kuò)展字符的 slice 方法):
function slice(str, start, end) {
return Array.from(str).slice(start, end).join('');
}
let str = '??????';
alert(slice(str, 1, 3)); // ????// 原生方法不支持識(shí)別代理對(duì)(譯注:UTF-16 擴(kuò)展字符)
alert(str.slice(1, 3)); // 亂碼(兩個(gè)不同 UTF-16 擴(kuò)展字符碎片拼接的結(jié)果)
三、總結(jié)
本文基于JavaScript基礎(chǔ)。介紹了Iterable object(可迭代對(duì)象),應(yīng)用 for..of 的對(duì)象被稱為 可迭代的。通過創(chuàng)建一個(gè)對(duì)象,詳細(xì)的講解了字符串是可迭代的。顯式調(diào)用迭代器,以及在實(shí)際中 Array.from的應(yīng)用。
歡迎大家積極嘗試,有時(shí)候看到別人實(shí)現(xiàn)起來很簡(jiǎn)單,但是到自己動(dòng)手實(shí)現(xiàn)的時(shí)候,總會(huì)有各種各樣的問題,切勿眼高手低,勤動(dòng)手,才可以理解的更加深刻。
代碼很簡(jiǎn)單,希望對(duì)你學(xué)習(xí)有幫助。