iT邦幫忙

2021 iThome 鐵人賽

DAY 28
2
Modern Web

初學者跪著學JavaScript系列 第 28

初學者跪著學JavaScript Day28 : 學迭代,學習不等待

  • 分享至 

  • xImage
  •  

一日客語:中文:報紙 客語:bo ziiˋ

最近很疑惑迭代物件和可迭代到底是什麼??於是查一下資料,發現很有趣

哪些可以迭代?

ArraySetMapString

能使用for/of迴圈來迭代


使用:一般物件

不可以迭代

let obj = {
    name: 'wendy',
    age: 18,
    [Symbol.iterator]: '勵志成為迭代物件',
};
for (let x of obj) {
    console.log(x);
}

//TypeError: obj is not iterable

使用陣列

可以迭代

let myArray = ['wendy', 20, 30];
for (let x of myArray) {
    console.log(x);
}
//wendy
//20
//30

會什麼會這樣呢?明明都是物件居然搞差別待遇!!!/images/emoticon/emoticon16.gif


先說說概念

圖例說明:

開始介紹他們

  • iterable object 可迭代物件: Array、 Set、 Map (可迭代的型別)

  • iterator object 迭代器物件 (自己本身可以迭代)

  • iteration object 迭代結果物件 (存放迭代每步驟的結果

不管是中文還是英文,名字長超像一開始很容易搞混!!


可迭代物件( iterable object)

具有 Symbol.iterator 的屬性,會回傳迭代器物件

可以使用 for/of 來迭代

能使用 spread 展開運算子

能使用解構賦值( Destructuring assignment )

let myArray = [10, 20];//可迭代物件
let myArrayIterator = myArray[Symbol.iterator]();

console.log(myArrayIterator); 
//Object [Array Iterator] {}

let mySet = new Set([1, 2]);//可迭代物件
console.log(mySet[Symbol.iterator]());
//[Set Iterator] { 1, 2 }

let myMap = new Map([
    [1, 'wendy'],
    [2, 'nick'],
    ['red', 'apple'],
]);
console.log(myMap[Symbol.iterator]()); 
//[Map Entries] { [ 1, 'wendy' ], [ 2, 'nick' ], [ 'red', 'apple' ] }

//使用不可迭代物件

let myNumber = 10;
console.log(myNumber[Symbol.iterator]); //undefined
let myObj = { 1: 'wendy', 2: 'ann' };
console.log(myObj[Symbol.iterator]); //undefined



迭代器物件 iterator object

具有 next()方法的物件,使用此 methods 會回傳迭代器結果物件

執行可迭代物件的 [Symbol.iterator] 的function

myArray[Symbol.iterator]()

回傳是一個迭代器 (iterator object) Array Iterator

怎麼知道他是迭代器物件? 因為他有 next()!!!!/images/emoticon/emoticon07.gif

迭代結果物件 iteration object

物件裡具有 value 和 done 的屬性

所以輸入myArray[Symbol.iterator]().next() 會出現

{
    value:xxx,
    done:false
}

let myArray = [10, 20];
let myIterator = myArray[Symbol.iterator]();
console.log(myIterator.next());//{ value: 10, done: false }
console.log(myIterator.next());//{ value: 20, done: false }
console.log(myIterator.next());//{ value: undefined, done: true }

迭代器可以透過 next(),一直產生出序列值

圖片出處:A Simple Guide to ES6 Iterators in JavaScript with Examples

如何做出可迭代物件

可迭代物件要有 [Symbol.iterator] 屬性,就可以使用 for / in 製作

一般物件無法迭代,直接報錯了

let obj = {
    name: 'wendy',
    age: 18,
    goal: '勵志成為迭代物件',
};
for (let x of obj) {
    console.log(x);
}

//TypeError: obj is not iterable

想成為迭代器嗎?

物件自己加一個 [Symbol.iterator] 屬性然後根據前面講述,把要求的條件加入

1.要有 next()
2.要有一個物件 {next:xxx,done:true/false}

let myObj = {
    name: 'wendy',
    age: 18,
    hair: 'black',
    [Symbol.iterator]: function () {
        let index = 0;
        let values = Object.values(this);
        return {
            next: () => ({ value: values[index++],
            done: index > values.length }),
        };
    },
};

let iterator = myObj[Symbol.iterator]();
console.log(iterator.next());//{ value: 'wendy', done: false }
console.log(iterator.next());//{ value: 18, done: false }
console.log(iterator.next());//{ value: 'black', done: false }
console.log(iterator.next());//{ value: undefined, done: true }

for (let y of myObj) {
    console.log(y);
}
//wendy
//18
//black

就可以做出自製迭代器, wow 是不是很棒啊,雖然有點廢,用 Object.values 就可以

但還是很開心做出來~

Make your objects iterable

是根據這篇大大自制迭代物件,來改寫

所以要做出可迭代物件就要手刻,但在ES6出現新語法生成器 (generator) 新定義的迭代器

function* animal() {
    yield 100;
    yield 200;
    yield 'wendy';
}

let genAnimal = animal();
console.log(genAnimal.next().value); //100
console.log(genAnimal.next().value); //200
console.log(genAnimal.next().value); //wendy
console.log(genAnimal.next().value); //undefined

for (x in genAnimal) {
    console.log(x);  
}
    //100
    //200
    //wendy
    //undefined

初學者跪著學JavaScript Day26:認識生成器,chris不生氣

讀完之後發現原來常用迭代方式背後原理是這樣

鐵人賽剩兩天~撒花/images/emoticon/emoticon42.gif


資料參考:
Make your objects iterable
JavaScript大全第七版
mdn
A Simple Guide to ES6 Iterators in JavaScript with Examples
謝謝array同學


上一篇
初學者跪著學JavaScript Day27 : 渣男給不完的promise
下一篇
初學者跪著學JavaScript Day29 : async 和 await
系列文
初學者跪著學JavaScript30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
juck30808
iT邦研究生 1 級 ‧ 2021-10-14 12:32:26

恭喜即將邁入完賽階段~

wendy iT邦新手 2 級 ‧ 2021-10-14 19:16:12 檢舉

謝謝你~也恭喜你 一起加油

我要留言

立即登入留言