久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

關(guān)于遍歷的那些事兒

 小仙女本仙人 2022-11-29 發(fā)布于北京

一、傳統(tǒng)遍歷

所謂傳統(tǒng)遍歷,,是區(qū)別于 ES6 遍歷器的遍歷

1. 遍歷數(shù)組

1.1 for, while

遍歷一個數(shù)組,,可以使用 for、while 循環(huán),。

1.2 實例的迭代方法

又或者調(diào)用 ES5 給 Array 原型添加的 5 個迭代方法,。這 5 個迭代方法接受兩個參數(shù):

  1. 在全部元素運(yùn)行的迭代函數(shù),這個函數(shù)可以接受三個參數(shù):
    • 元素的值
    • 元素的下標(biāo)
    • 數(shù)組本身
  2. 運(yùn)行在指定函數(shù)的 this(可選)

這 5 個迭代方法具體功能不太一致:

  1. every:如果迭代函數(shù)都返回 true,,則返回 true
  2. some:如果迭代函數(shù)有一個返回 true,,則返回 true
  3. filter:返回迭代函數(shù)返回 true 的元素組成的子數(shù)組
  4. forEach:單純執(zhí)行迭代函數(shù),,沒有返回值
  5. map:返回迭代函數(shù)返回值組成的數(shù)組

注意,,上述 5 個迭代方法都不會改變原數(shù)組本身

1.3 實例的歸并方法

ES5 還給給 Array 原型新增兩個歸并方法:reduce 與 reduceRight,。這兩個函數(shù)會在數(shù)組全部元素上迭代執(zhí)行一個函數(shù),,并構(gòu)建一個最終返回的值。這兩個方法接受兩個參數(shù):

  1. 迭代函數(shù),,它有四個參數(shù):
    • 前一個元素的迭代函數(shù)返回值
    • 元素值
    • 元素下標(biāo)
    • 數(shù)組對象
  2. 作為歸并基礎(chǔ)的初始值

reduce 是從數(shù)組首迭代到數(shù)組尾,,reduceRight 相反。它們的一個典型應(yīng)用場景是用來求數(shù)組和

let arr1 = [1, 2, 3];
let res = arr1.reduce((pre, cur) => pre+cur, 0);
console.log(res); // 6
1.4 缺點:
  1. for,、while 循環(huán):寫法麻煩
  2. 迭代,、歸并方法:無法使用 break、continue 以及外部函數(shù)的 return 去中止循環(huán)

2. 遍歷對象

2.1 枚舉性

遍歷對象的思路比較統(tǒng)一,,就是遍歷鍵名,,然后再用鍵名去訪問鍵值。而關(guān)于鍵名的遍歷,,需要提到一個概念:鍵名是否可以被枚舉,。

我們都知道,一個對象上的每一個屬性都有一個描述對象,,用來描述這個屬性的一下行為,,比如讀,、寫、是否可刪除,、是否可枚舉等,。

屬性描述對象有一個屬性 enumerable,它是一個布爾值,,表示屬性是否可枚舉,。

// 定義一個函數(shù),訪問 obj 上 key 屬性的可枚舉性 enumerable
let getEnmerable = (obj, key)=>{
	return Object.getOwnPropertyDescriptor(obj, key).enumerable;
}
// 一個對象的自定義屬性一般都是可枚舉的
getEnmerable({a: 1}, 'a'); // true

// 數(shù)組本質(zhì)也是一個對象
let arr = [1, 2, 3];
getEnmerable(arr, 0); // true,,說明數(shù)組的'0’屬性是枚舉的
getEnmerable(arr, 'length'); // false,,說明數(shù)組的'length’屬性是不可枚舉的
console.log(Object.keys(arr)) // ["0", "1", "2"]
2.2 遍歷對象鍵名的方法

遍歷對象鍵名的方法,常用的有 5 種,,它們遍歷的屬性范圍有所不同:

  1. for...in:自身及其原型上的可枚舉的,、非 Symbol 屬性
  2. Object.keys (obj):自身的可枚舉的、非 Symbol 屬性
  3. Object.getOwnPropertyNames (obj):自身的非 Symbol 屬性,,不管是否可以枚舉
  4. Object.getOwnPropertySymbols (obj):自身的 Symbol 屬性,,不管是否可以枚舉
  5. Reflect.ownKeys (obj):自身的全部屬性,不管是否可以枚舉已經(jīng)是否是 Symbol

只有 for...in 會去遍歷實例原型,,其他的遍歷方法都不會去遍歷實例原型,。推薦使用 Object.keys,它能適用我們正常開發(fā)的大部分場景,。

2.3 遍歷順序
  1. 首先,,遍歷屬性名為數(shù)值的屬性,按數(shù)字大小升序
  2. 再次,,遍歷屬性名為字符串的屬性,,按生成時間先后升序
  3. 最后,遍歷屬性名為 Symbol 屬性,,按生成時間先后升序

二、遍歷器

1. 什么是遍歷器

介紹完上面的遍歷后,,有沒有覺得,,api 一大堆又不通用,記起來很麻煩,。是的,,這就是為什么 ES6 要提出遍歷器的原因——提供一種統(tǒng)一的接口機(jī)制來處理所有不同的數(shù)據(jù)結(jié)構(gòu)

對應(yīng)著遍歷器,,ES6 提供了一種新的遍歷機(jī)制:for...of,,專門用來遍歷遍歷器和有遍歷器接口的數(shù)據(jù)結(jié)構(gòu)。

那,怎么得到遍歷器呢,?ES6 給一些數(shù)據(jù)結(jié)構(gòu)引入了 Symbol.iterator 這個唯一屬性,,這個屬性指向一個方法,這個方法可以用來生成對應(yīng)數(shù)據(jù)結(jié)構(gòu)的遍歷器對象,。

拿到這個遍歷器對象之后,,我們可以不斷地調(diào)用遍歷器對象的 next 方法來對數(shù)據(jù)結(jié)構(gòu)進(jìn)行遍歷。for...of 遍歷的本質(zhì)也是不斷調(diào)用數(shù)據(jù)結(jié)構(gòu)遍歷器對象的 next 方法,。

看一個例子:

// 定義一個簡單的數(shù)組
let arr = [1, 2, 3];

// 獲取遍歷器對象 
let iter = arr[Symbol.iterator] (); 

// 調(diào)用遍歷器對象上的next方法,,開始遍歷
console.log(iter.next()); // {value: 1, done: false}
console.log(iter.next()); // {value: 2, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // 遍歷完畢 {value: undefined, done: true}

// for...of 本質(zhì)就是調(diào)用數(shù)據(jù)集合的遍歷器對象上的 next 方法去進(jìn)行遍歷
for(let index of arr) {
	console.log(index) // 1 2 3
}

原生具備遍歷器接口的數(shù)據(jù)結(jié)構(gòu)有:

  1. Array
  2. Map
  3. Set
  4. String
  5. 函數(shù)的 arguments 對象
  6. NodeList 對象
  7. TypedArray

ps:如上文,純對象是沒有遍歷器接口的,。

擁有了遍歷器接口,,我們就可以統(tǒng)一使用 for...of 來遍歷上訴的這些數(shù)據(jù)結(jié)構(gòu),而不用死腦筋地去背每種數(shù)據(jù)結(jié)構(gòu)自己固定的 api 了,。

2. 數(shù)組的遍歷器

for...of 已經(jīng)可以遍歷數(shù)組得到數(shù)組每一個元素的值了,,但是如果你有特殊需求,除了數(shù)組元素值以外還需要數(shù)組的下標(biāo),,又或者你只需要數(shù)組的下標(biāo)……ES6 給數(shù)組原型上新添加了幾個方法,,可以滿足你的需求:

  1. arr.entries():生成遍歷結(jié)果為 [鍵名, 鍵值] 的遍歷器
  2. arr.keys():生成遍歷結(jié)果為 鍵名 的遍歷器
  3. arr.values():生成遍歷結(jié)果為 鍵值 的遍歷器

調(diào)用上述 api 生成特定的遍歷器后,我們可以再用 for...of 遍歷這個遍歷器,,就可以得到我們特定的遍歷需求,。

值得一提的是,調(diào)用這些 api 后,,我們用 for...of 遍歷的是一個遍歷器,,而如果我們直接 for...of 去遍歷數(shù)組 arr 本身,其實數(shù)組還是會調(diào)用 arr.values() 來生成一個遍歷器給 for...of 去遍歷,。

所以用 for...of 遍歷 arr.values() 和遍歷數(shù)組 arr 本身是一樣的,,最終 for...of 遍歷的都是遍歷器

arr.entries() 和解構(gòu)賦值一起使用,,食用口味更佳。

let arr = [23,4,45,4];
for (let [i, num] of arr.entries()) {
	console.log(i, num);
}

3. 對象的遍歷器

一開始是不是很好奇,,為什么對象沒有遍歷器接口,?因為對象存在的意義不是讓你來遍歷的,如果你需要一個可以遍歷的鍵值對的話,,可以用 Map 結(jié)構(gòu),,它是擁有遍歷器接口的

當(dāng)然,,如果你硬要遍歷對象的話,,也可以。

和數(shù)組類似,也有幾個特殊的方法去給對象生成特定的遍歷器,,不同的是,,這些方法不在對象原型上,而是在 Object 構(gòu)造函數(shù)上:

  1. Object.entries(obj):生成遍歷結(jié)果為 [鍵名, 鍵值] 的遍歷器
  2. Object.keys(obj):生成遍歷結(jié)果為 鍵名 的遍歷器
  3. Object.values(obj):生成遍歷結(jié)果為 鍵值 的遍歷器

老樣子,,配合解構(gòu)賦值才是遍歷器遍歷最好的使用方法:

let obj = {
	b: 1,
	0: 2,
	a: 3,
}
for(let [key, value] of Object.entries(obj)) {
	console.log(`${key}:${value}`);
	// 0: 2
	// b: 1
	// a: 3
}

4. Set、Map 的遍歷器

ES6 新增了兩類有趣的數(shù)據(jù)結(jié)構(gòu):Set,、Map,,它們也擁有遍歷器接口。要遍歷它們可以通過生成遍歷器(for...of 遍歷的本質(zhì)也是生成遍歷器),,所以它們的原型上也擁有這三寶:

  1. entries():生成遍歷結(jié)果為 [鍵名, 鍵值] 的遍歷器
  2. keys():生成遍歷結(jié)果為 鍵名 的遍歷器
  3. values():生成遍歷結(jié)果為 鍵值 的遍歷器
let map = new Map().set('a', 1).set('b', 2).set('c', 3);
for (let [key, num] of map) {
	console.log(key, num);
}

除了通過生成遍歷器的去遍歷以外,,其實 Set、Map 原型上也有一個不借用遍歷器遍歷的方法,,就是 forEach,。

另外,WeakSet 和 WeakMap 是不支持遍歷的,,因為它們對于對象的引用都是弱引用,。

三,、總結(jié)

Set 是一個類 Array 的結(jié)構(gòu),,但是我們可以看到,ES6 對于 Array 原型上的很多 api 都沒有再賦給 Set (比如 reduce,、map 等),,這其實也反映出 ES6 提出的遍歷器的目的——提出一種統(tǒng)一的接口機(jī)制來遍歷全部的數(shù)據(jù)結(jié)構(gòu),淘汰各種數(shù)據(jù)結(jié)構(gòu)自身原本過度泛濫的遍歷 api,。包括各種數(shù)據(jù)結(jié)構(gòu)上生成遍歷器的方法也都是同名的 entries,、keys、values ,,也體現(xiàn)出這一點,。

所以,以后我們編程的時候,,盡量保持一個習(xí)慣,,能用遍歷器機(jī)制去遍歷的,都盡量使用遍歷器機(jī)制遍歷,,保持一個統(tǒng)一良好的遍歷寫法,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多