JavaScript中Iterator迭代器接口和循環(huán)
JavaScript的迭代器(Iterator)介紹
迭代器是數(shù)據(jù)結構遍歷的一種機制(或者是什么我也不太懂的行業(yè)術語),為數(shù)據(jù)結構定義了統(tǒng)一的遍歷規(guī)則。 迭代器(Iterator)主要是提供for...of使用,或者說,數(shù)據(jù)結構只有實現(xiàn)了迭代器(Iterator)接口才能使用for...of進行遍歷數(shù)據(jù),當一種數(shù)據(jù)結構沒有實現(xiàn)迭代器(Iterator)接口時,去使用for...of操作,就會被拋出異常Uncaught TypeError: xxx is not iterable。
JavaScript的迭代器(Iterator)的接口規(guī)范和操作過程:
- 迭代器被調用時,返回一個指針對象,指針對象中必須包含一個
next()的方法,每次調用next()方法,都會返回一個代表當前成員的信息對象,具有value和done兩個屬性。value可為任意數(shù)據(jù)類型,done則是一個布爾類型,當調用next的方法時返回的對象中的done屬性為false時,表示還可以繼續(xù)進行遍歷,當done屬性為true時,表示遍歷結束(沒有的東西遍歷了)了。 - 迭代器(Iterator)對象的可選屬性
return()方法和throw()方法,也就是說當我們要自己去實現(xiàn)迭代器(Iterator)的時候,迭代器里必須要有next()方法,而return()方法和throw()是否要實現(xiàn)是可選的。而自己實現(xiàn)迭代器(Iterator)時,不管是next()、return()還是throw()方法必須有返回值并且是對象,否則進行遍歷的時候會拋出異常Uncaught TypeError: Iterator result xxx is not an object。 - 自己實現(xiàn)迭代器,只要給數(shù)據(jù)結構或者對象添加
[Symbol.iterator]屬性即可,其值必須是一個函數(shù),返回一個只針對象,需遵循第2點的規(guī)范。為什么必須是[Symbol.iterator]的屬性名,因為JavaScript的定義中,尋找遍歷器時就是用這個字段,這也是一個標準規(guī)范。
下面是自己實現(xiàn)迭代器的演示代碼:
const obj = {a: "age 18", b: 2};
// 實現(xiàn)迭代器
obj[Symbol.iterator] = function () {
const keys = Object.keys(obj);
let keyIndex = 0;
return {
next() {
if (keys.length === 0 || keyIndex >= keys.length) {
return {
value: undefined,
done: true
}
}
const key = keys[keyIndex],
value = [key, obj[key]];
keyIndex += 1;
return {
value,
done: false
}
}
};
}
// 使用for...of進行遍歷
for (let [key, value] of obj) {
console.log(`${key}--${value}`)
}
// a--age 18
// b--2返回參數(shù)簡寫,當返回正常值的時候,done字段可以省略,當循環(huán)結束的時候,value可以省略。但是注意不能兩個都不寫,不然會死循環(huán),而且必須要有條件結束的操作,不然也會死循環(huán),就像遞歸一樣,一定要有條件結束的操作
Number.prototype[Symbol.iterator] = function () {
let that = +this,
i = that < 0 ? that : 0;
that = that < 0 ? 0 : that;
return {
next() {
if (i <= that) {
const value = i;
i += 1;
return { value };
}
return { done: true };
}
};
};
for (const item of 20) {
console.log(item);
}
// 數(shù)組的擴展運算符也是調用迭代器的哦
console.log([...5]);// [0, 1, 2, 3, 4, 5]迭代器的可選參數(shù)return()和throw()
return()方法是在遍歷中斷的時候會調用,如使用了break關鍵字中斷或者拋出了異常都會調用這個方法。return()方法必須有返回參數(shù)并且要求是object類型的數(shù)據(jù),否則就會拋出異常Uncaught TypeError: Iterator result undefined is not an object,至于object里內容要求是什么,我測了一下,毫無影響,返回空對象也沒問題。
const obj = {
size: 5,
[Symbol.iterator]() {
return {
// 這里用箭頭函數(shù)為的是可以直接使用this
next: () => {
if (this.size >= 0) {
const value = this.size;
this.size -= 1;
return {
value
};
}
return {
done: true
};
},
return() {
console.log("中斷了");
return { done: true };
// 返回以下內容照樣不會有問題,但是最好不這么操作,因為代碼具有語義化才能更好的閱讀
// return {};
// return new Date();
}
};
}
};
for (const item of obj) {
if (item < 3) {
break;// 中斷了
}
console.log(item);
}throw()方法在迭代器中基本用不到,而是配合Generator使用,這里就不做過多的敘述。
原生具備 Iterator 接口的數(shù)據(jù)結構如下:
- Array
- Map
- Set
- String
- TypedArray
- 函數(shù)的 arguments 對象
- NodeList 對象
for...of循環(huán)與for...in循環(huán)
上面已經(jīng)詳細的說明了迭代器(Iterator)主要是提供for...of循環(huán)使用,所以for...of循環(huán)時調用的是迭代器(Iterator),而循環(huán)的值是由實現(xiàn)的迭代器(Iterator)而定,而for...in循環(huán)是循環(huán)鍵值。
const arr = ["a", "b", "c"];
// 原生的數(shù)組迭代器(Iterator)的實現(xiàn)遍歷時返回的是每一個元素
for (const item of arr) {
console.log(item);
// a
// b
// c
}
// for...in 返回的是key,這里是數(shù)組,key就是索引
for (const key in arr) {
console.log(key);
// 0
// 1
// 2
}還有一個更直觀的區(qū)別。for...of只是根據(jù)迭代器(Iterator)實現(xiàn)的內容返回結果,所以就不會遍歷不在范圍的東西,而for...in會把所有的鍵遍歷出來。
const arr = ["a", "b", "c"];
arr.testValue = 1;
for (const item of arr) {
console.log(item);
// a
// b
// c
}
for (const item in arr) {
console.log(item);
// 0
// 1
// 2
// testValue
}到此這篇關于JavaScript中Iterator迭代器接口與循環(huán)的文章就介紹到這了,更多相關JavaScript Iterator 內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
js防抖-節(jié)流函數(shù)的基本實現(xiàn)和補充詳解
這篇文章主要介紹了防抖-節(jié)流函數(shù)的基本實現(xiàn)和補充,文章從基礎概念到手寫對防抖-節(jié)流函數(shù)的實現(xiàn)進行講解,內容詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2023-01-01

