<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
生成器和迭代器這兩個東西平時作為一個切圖仔,一直都沒有使用到。感覺是隻有在面試之前才會的東西。面試過不了幾天,再次看這兩個詞一陣恍惚。
記憶力退化成這樣了麼?最大的原因一定是用得少了。然後呢?就是沒有真正的理解它們。我對於它們的認知常常有下面這些:
1. 我常常把迭代器和生成器理解成完全不同的東西。
2. 我常常把for、forEach、map、reduce
和for of
混為一談
3. 我常常把陣列、類陣列認為是可迭代物件
想來要真正的記住它,增加自己的武器庫,必須要弄明白這些東西才行。
我們首先是要搞明白什麼for of是幹什麼用的。
業務程式碼確實使用不上,但是如果不理解的話,等真到了可以使用的場景的時候,又是否真的能夠運用起來,甚至記起來呢?
所有人都知道一些概念for、forEach、map、reduce
這些是可以遍歷陣列的,for of
是用於遍歷迭代物件的。如下:
const arr = [1, 2, 3] arr.forEach((item, index) => { console.log(item) // 1, 2, 3 console.log(index) // 0, 1, 2 })
而巧合的是for of
也可以遍歷陣列
for (let key of arr) { console.log(key) // 1 2 3 }
將arr改變為const obj = { a: 1, b: 2, c: 3 }
的時候,兩者都沒有遍歷出結果。
前者是沒有反應,後者會直接報錯:TypeError: obj is not iterable
。翻譯一下,型別錯誤:obj 不是一個可迭代物件。
那麼什麼是可迭代物件呢?
我們先來看看下面這個例子:
const itemLi1 = document.getElementByTagName('li') const itemLi2 = document.querySelectorAll('li') for(let key of itemLi1) { console.log(item) } for(let key of itemLi2) { console.log(item) }
也就是說HTMLCollection
和NodeList
是可以迭代物件。其他的可迭代物件有Array、map、set、string
等等。如果說類陣列的話,是不是迭代物件呢?
const arrLike = { 0: 1, 1: 2, 2: 3, lenght: 3 } for (let i = 0; i < arrLike.length; i++) { console.log(arrLike[i]) // 1, 2, 3 } for (let of arrLike) { console.log(key) // uncachh TypeError: obj is not iterable }
for迴圈列印出了對應的結果,而for of 報錯了。類陣列不是可迭代的的物件。這又是為什麼呢?我們將類陣列和HTMLCollection型別列印出來比較一下。
而類陣列如下:
它們有一個明顯的不同,可迭代物件的原型鏈上面是包括Symbol.iterator
的。而這個就是讓陣列變成可迭代的根本原因。
也就是說,當目的物件的原型鏈上面包括Symbol.iterator
的時候,它才是可迭代物件。
物件是無序的,無序的東西自然不可以迭代
這裡使用到了Symbol型別,它在MDN上面的解釋就是用於生成全域性唯一的變數。而可迭代物件就是它的使用場景。受它的啟發,我們在業務當中,如果需要前端來生成一個唯一ID的時候,再次之前,通常都是建立一個UUID的函數來生成一個唯一ID。Symbol不用這麼麻煩,直接使用就可以了。
由此可知,Array.prototype[Symbol.iterater]
這個函數封裝了一些東西,使得for of
可以將物件的元素給列印出來。
換一句話來說,就是Array.prototype[Symbol.iterater] = function() {}
的執行生成一個迭代器物件。
也就是說,當Object.prototype
也有[Symbol.iterater]
的方法的時候,for of
也能夠遍歷它呢?我們來試試看吧。
Object.ptotoype[Symbol.iterator] = function value() {}
這不就是生成器的作用麼?
ES6給我提高了一個生成器的函數。既然叫做生成器,它生成的東西就是迭代器。
表現形式如下:
function * generation(iterableObject) { for(let i = 0; i < iterableObject; i++) { yield iterableObject[i] } }
由*
符號和yield
關鍵字組成。
當const iterator = generation([1, 2, 3])
, 其執行流程如下:
iterator.next() ==> { value: 1, done: false }
iterator.next() ==> { value: 2, done: false }
iterator.next() ==> { value: 3, done: false }
iterator.next() ==> { value: undefined, done: true }
到了第四次,value為undefined
的時候,done為true(也就是說,當done為true的時候,value一定為undefined)。所以說,yield
的作用有兩個:
{ value: .., done: flase/true }
這樣的形式。可以明顯的看出來,生成器有一個作用,通過next這個介面,可以看到迭代的過程。
既然說生成器生成了一個迭代器,那麼是不是說生成器執行後的結果就是一個迭代器呢?既然是迭代器,自然就可以被for of
給遍歷。
for (const key of generation([1, 2, 3]) { console.log(key) // 1, 2, 3 }
果然可以。
經典面試題: 自己實現一個next
這樣的介面呢?
上面已經有了實現的思路。通過一個識別符號和一個判斷就能夠使用ES5來使用,如下程式碼片段。
function generation(iterableObj) { let nextIndex = 0 function next() {} return { next: () => { return nextIndex < iterableObj.length ? { value: iterableObj[nextIndex++], done: false } : { value: undefined, done: true } } } }
當nextIndex下於陣列長度的時候,沒有迭代完畢。
注意:nextIndex++
是先跑nextIndex
,再自增。
何為介面,後臺給你一個url地址,這個是網路介面。next是設計師給你封裝的一個方法,你通過這個方法來達到上吧yield
的兩個作用,所以next()也是一個介面,前端介面。簡單來說,一個封裝好的方法就是一個介面。
正如第一節所說,Symbol.iterator
的方法是迭代器的關鍵。那麼我們也可以給Object
掛載上該方法。既然該方法可以讓物件變成迭代器,就可以直接使用上面ES5實現next
方法的程式碼片段。
const obj = { a: 1, b: 2, c: 3 } Object.prototype[Symbol.iterator] = function value() { const keys = Object.keys(Object(this)) let nextIndex = 0 function next() { return nextIndex < keys.length ? { value: [keys[nextIndex], obj[keys[nextIndex ++]]], done: false } : { value: undefined, done: true } } return { next } } for (const [key, value] in obj) { console.log(key) }
for迴圈和for in 看著很像,其實只是共用了for
這個關鍵字,它們都是JS引擎底層實現的東西。和forEach、map
這些是基於for迴圈的API不同,它們是在實現在for迴圈之上的。
Symbol.iterator
方法以上就是詳解JS前端使用迭代器和生成器原理及範例的詳細內容,更多關於JS前端迭代器生成器的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45