成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

遍歷得到數組 Or Iterator 遍歷器?

開發 前端
熟悉 ES 語法數據結構的朋友一定很清楚,原生對象數據結構并不支持 obj.keys()、obj.values()和 obj.entries() 方法,數組與 map、set 等數據結構才支持。但仍可以通過 Object.keys(obj)、Object.values(obj)、Object.entries(obj)獲取原生對象中可遍歷的屬性組成數組類型數據結構。

[[433429]]

一、背景

故事的開頭是這樣的...

在遍歷數組與對象屬性時,對使用 obj.keys()、obj.values()和 obj.entries() 還是 Object.keys(obj)、Object.values(obj)、Object.entries(obj)方法產生了一些困惑。話不多說,先放問題:

需求:想要遍歷一個對象,并獲取遍歷對象的屬性值 實現:Object.keys()、Object.values() 和 Object.entries() 方法 問題:一不小心同數組的 entries(),keys()和 values() 方法混淆了~QAQ

二、keys()、values()、entries()遍歷方法

熟悉 ES 語法數據結構的朋友一定很清楚,原生對象數據結構并不支持 obj.keys()、obj.values()和 obj.entries() 方法,數組與 map、set 等數據結構才支持。但仍可以通過 Object.keys(obj)、Object.values(obj)、Object.entries(obj)獲取原生對象中可遍歷的屬性組成數組類型數據結構。

也就是說,keys()、values()和 entries() 方法有兩種:

ES5-ES2017 相繼引入 Object.keys 、Object.values 和 Object.entries 方法,返回一個數組,成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名/鍵值/鍵值對,可以用 for...of 循環進行遍歷;

ES6 提供 entries(),keys() 和 values() -- 可用于遍歷數組/Map/Set 等類數組數據結構實例,返回一個(Iterator)遍歷器對象,可以用 for...of 循環進行遍歷。

注意這里又有兩點區別:

兩者調用語法不同,顯而易見;

前者返回的是一個可迭代的對象,而后者返回的是一個真正的數組。

有沒有被繞暈?那我們先來看第一個問題吧 -- 調用語法的不同

Q1: Object.keys 、Object.values 和 Object.entries 方法

為了區分這兩種調用語法,我們必須得來回顧下原型鏈的相關知識。

因為這里的 entries(),keys()和 values() 方法正是是調用原型對象構造函數上的方法。如下圖可以看到,對于一個普通對象,這三個方法在 Object 對象的[[prototype]]下的 constructor 中:

而對于一個數組結構來說,這三個方法可以在數組原型鏈中和原型鏈上層對象原型的 constructor 中同時找到:

即 Object.keys(arr)調用的是數組原型鏈頂層原型對象 constructor 的方法,而數組本身也支持的 arr.keys()方法,則是調用數組原型鏈上的方法。

即對象只支持前種調用方式,而數組同時支持這兩種調用:

同時我們知道在 JavaScript 中,對象是所有復雜結構的基礎。也正對應了其他復雜結構原型鏈的頂端是對象原型結構。現在應該能夠知道為何普通對象不支持 obj.keys()、obj.values()和 obj.entries() 方法了,但到這里就不得不提出另一個疑問了:

Q2: 如何讓一個對象支持 obj.keys()、obj.values()和 obj.entries() 方法呢?

理論上,我們是可以為一個對象構造任意方法,那么如何實現和數組一樣的遍歷方法呢?本質上這個方法是能夠生成一個遍歷器。

  1. let objE = { 
  2.   data: [ 'hello''world' ], 
  3.   keys: function() { 
  4.     const self = this; 
  5.     return { 
  6.       [Symbol.iterator]() { 
  7.         let index = 0; 
  8.         return { 
  9.           next() { 
  10.             if (index < self.data.length) { 
  11.               return { 
  12.                 value: self.data[index++], 
  13.                 done: false 
  14.               }; 
  15.             } 
  16.             return { value: undefined, done: true }; 
  17.           } 
  18.         }; 
  19.       } 
  20.     } 
  21.   } 
  22. }; 

上述,我們自己創建了一個 data 對象,并實現了它自己的 data.values() 方法。同時,我們依然可以對它調用 Object.values(data) 方法。

從上面的方法不難看出,我們在對象中通過添加 Symbol.iterator 手動構造了一個輸出遍歷器函數,關于遍歷器的討論我們在下一節討論,現在先來討論調用返回結果的區別。

Q3: 兩種調用方法返回結果:遍歷器與數組

1)第一種調用方法,根據定義可知:返回一個數組,數組成員是參數對象自身的(不含繼承的)所有可遍歷(enumerable)屬性的鍵名/鍵值/鍵值對。

敲重點!!!這三個方法只返回對象自身的可遍歷屬性,即屬性描述對象的 enumerable 為 true。

我們可以通過 for ... in 循環來實現相同的遍歷效果。

2)而第二種方法,返回一個遍歷器:顧名思義,遍歷器也可以滿足循環遍歷的需求。

本質上,遍歷器的定義是一種接口,為各種不同的數據結構提供統一的訪問機制。接下來就來了解下適用于不同數據結構的遍歷器。

三、Iterator 遍歷器

首先我們知道,目前主要有四種表示“集合”的數據結構:數組(Array)、對象(Object)、Map 和 Set,這里表示"集合"的對象例如 NodeList 集合類數組對象,而遍歷器可以使我們遍歷訪問這些集合。

實際上,原生具備 Iterator 接口的數據結構包括 Array、Map、Set、String、TypedArray、函數的 arguments 對象和 NodeList 對象。

具體遍歷器的概念可參考阮一峰老師 ES6 入門 Iterator 一章,已經十分詳細清楚:

因此,Iterator 遍歷器本質上為所有數據結構,提供了一種統一的訪問機制,即 for...of 循環。

關于遍歷,我們前面已經講到了遍歷對象屬性,這里再提一嘴:

1. 遍歷類數組對象/Array/Map/Set 等數組數據結構實例

當使用 for...of 循環遍歷某種數據結構時,該循環會自動去尋找 Iterator 接口。一種數據結構只要部署了 Iterator 接口,我們就稱這種數據結構是“可遍歷的”(iterable)。ES6 規定,默認的 Iterator 接口部署在數據結構的 Symbol.iterator 屬性,換句話說,一個數據結構只要具有 Symbol.iterator 屬性,就可以認為是“可迭代/遍歷的”(iterable)。

2. 獲取對象可遍歷屬性

Object.keys 、Object.values 和 Object.entries 方法只返回對象自身的可遍歷屬性,通過屬性描述對象的 enumerable 標識改對象屬性是否可以遍歷。同時因為普通對象 not iterable,即普通對象不具有 Symbol.iterator 屬性,所以無法通過 for...of 循環直接遍歷,否則會報錯 Uncaught TypeError: obj is not iterable。

可見,數組及類數組的遍歷(迭代)與普通對象中的提到的遍歷是不同的,這分別取決于各自的 iterable 和 enumerable 屬性。

3. for ... of

ES6 中引入 for...of 循環,很多時候用以替代 for...in 和 forEach() ,并支持新的迭代協議。for...of 語句在可迭代對象上創建一個迭代循環,調用自定義迭代鉤子,并為每個不同屬性的值執行語句。

那么終極問題:如何實現 Symbol.iterator 方法,使普通對象可被 for of 迭代?其實在 Q2 部分已經實現了。

嘗試給普通對象實現一個 Symbol.iterator 接口:

  1. // 普通對象 
  2. const obj = { 
  3.   foo: 'value1'
  4.   bar: 'value2'
  5.   [Symbol.iterator]() { 
  6.     // 這里 Object.keys 不會獲取到 Symbol.iterator 屬性 
  7.     const keys = Object.keys(obj); // 得到一個數組 
  8.     let index = 0; 
  9.     return { 
  10.       next: () => { 
  11.         if (index < keys.length) { 
  12.           // 迭代結果 未結束 
  13.           return { 
  14.             value: this[keys[index++]], 
  15.             done: false 
  16.           }; 
  17.         } else { 
  18.           // 迭代結果 結束 
  19.           return { value: undefined, done: true }; 
  20.         } 
  21.       } 
  22.     }; 
  23.   } 
  24. for (const value of obj) { 
  25.   console.log(value); // value1 value2 
  26. }; 

for...of 循環內部調用的是數據結構的 Symbol.iterator 方法,for...of 循環可以使用的范圍包括數組、Set 和 Map 結構、某些類似數組的對象(比如 arguments 對象、DOM NodeList 對象)、后文的 Generator 對象,以及字符串。

for...of 循環作為 ES6 新引入的一種循環,具有以下明顯優勢(按需使用):

有著同 for...in 一樣的簡潔語法,但是沒有 for...in 那些缺點(無序,不適用于遍歷數組)。

不同于 forEach 方法,它可以與 break、continue 和 return 配合使用。

提供了遍歷所有數據結構的統一操作接口。

以上是我從 keys()、values()、entries() 遍歷方法出發對遍歷器產生的幾點思考,如有不足之處,歡迎指正~~~

 

責任編輯:武曉燕 來源: 微醫大前端技術
相關推薦

2009-11-17 15:07:16

PHP數組遍歷

2009-11-16 16:23:10

PHP數組遍歷

2021-03-29 12:01:00

遍歷數組for循環

2019-07-25 10:08:05

JavaScript數組轉換

2009-09-08 09:59:26

LINQ遍歷多個數組

2009-11-17 15:00:19

PHP遍歷數組

2024-04-25 07:54:46

遍歷數組PythonFor循環

2022-09-07 11:52:48

forforEach前端

2023-11-07 10:10:36

設計模式元素

2021-06-18 10:05:14

JavaScript數組遍歷

2020-06-30 10:37:55

JavaScript開發技術

2021-01-11 07:51:16

DOM對象節點樹

2021-06-15 10:01:27

JavaScript數組遍歷Entries

2021-02-05 23:08:10

JS代碼循環

2021-08-02 10:01:09

Iterator接口Java項目開發

2009-09-16 17:21:53

LINQ遍歷

2022-10-26 09:27:59

Python編程迭代器協議

2018-04-28 19:01:54

JavaScript數組Promise

2010-04-16 10:24:17

Oracle存儲過程

2021-07-22 07:20:24

JS 遍歷方法前端
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产不卡一区 | 日韩精品在线看 | 欧美一级视频免费看 | 夜夜爽99久久国产综合精品女不卡 | 91夜夜夜| 日韩在线中文字幕 | 成人av激情 | av中文在线观看 | 国产综合久久 | av黄色免费在线观看 | 国产高清视频在线 | 欧美一级片黄色 | 91精品国产91久久久久久吃药 | 激情欧美一区二区三区中文字幕 | 午夜看电影在线观看 | 国产日产精品一区二区三区四区 | 福利av在线 | 欧美日韩成人在线 | 国产97视频在线观看 | 国产精品亚洲一区 | 国产亚洲一区二区三区 | 在线免费观看黄视频 | 成人欧美在线 | 日本不卡免费新一二三区 | av日韩在线播放 | 91精品久久久久久久久久入口 | 亚洲精品久久久一区二区三区 | 国产高清在线精品一区二区三区 | 亚洲精品一区二区三区蜜桃久 | 亚洲成人观看 | 成人h视频 | 久久黄色精品视频 | 在线视频国产一区 | 免费观看av| 中文字幕在线免费 | 成人一级毛片 | 亚洲一区二区三区四区五区中文 | 欧美日韩国产中文 | 欧美一区二 | 日韩在线不卡 | 欧美不卡在线 |