Iterables
iterable 就是 array 的大眾化,讓物件可以使用 for...of 迴圈。
Symbol.iterator
自己創造一個可以迴圈的物件。
let range = {
from: 1,
to: 5
};
// We want the for..of to work:
// for(let num of range) ... num=1,2,3,4,5
// 創造可迴圈物件
let range = {
from: 1,
to: 5
};
// 1. call to for..of initially calls this
range[Symbol.iterator] = function() {
// ...it returns the iterator object:
// 2. Onward, for..of works only with this iterator, asking it for next values
return {
current: this.from,
last: this.to,
// 3. next() is called on each iteration by the for..of loop
next() {
// 4. it should return the value as an object {done:.., value :...}
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
};
// now it works!
for (let num of range) {
alert(num); // 1, then 2, 3, 4, 5
}
// 執行了 2 個 for..of
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
this.current = this.from;
return this;
},
next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
for (let num of range) {
alert(num); // 1, then 2, 3, 4, 5
}
String is iterable
// string
for (let char of "test") {
// triggers 4 times: once for each character
alert( char ); // t, then e, then s, then t
}
// 可以使用在擴展符號
let str = '𝒳😂';
for (let char of str) {
alert( char ); // 𝒳, and then 😂
}
Calling an iterator explicitly
let str = "Hello";
// does the same as
// 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); // outputs characters one by one
}
Iterables and array-likes
iterables 是有 Symbol.iterator 方法的物件
array-like 是有 index 跟 length 的物件
// string 2 者都是,可以使用 for..of,也有 index & length,但無法使用 array 的方法。
// array-like
let arrayLike = { // has indexes and length => array-like
0: "Hello",
1: "World",
length: 2
};
// Error (no Symbol.iterator)
for (let item of arrayLike) {}
Array.from
Array.from() 可以將 iterable / array-like 帶入返回新的 array。
// array-like 轉成 array
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike); // (*)
alert(arr.pop()); // World (method works)
// iterables 轉成 array
// assuming that range is taken from the example above
let arr = Array.from(range);
alert(arr); // 1,2,3,4,5 (array toString conversion works)
Array.from(obj[, mapFn, thisArg])
// Array.from 可以使用 map 函式
// assuming that range is taken from the example above
// square each number
let arr = Array.from(range, num => num * num);
alert(arr); // 1,4,9,16,25
// string 轉成 array
let str = '𝒳😂';
// splits str into array of characters
let chars = Array.from(str);
alert(chars[0]); // 𝒳
alert(chars[1]); // 😂
alert(chars.length); // 2
// 和上面的方法做了一樣的事
let str = '𝒳😂';
let chars = []; // Array.from 内部完成了同样的循环
for (let char of str) {
chars.push(char);
}
alert(chars);
Last updated