為什麼es6里的object不可迭代?

即不能用for of 遍歷


@魯小夫 的答案是從技術實現的角度說的,即直接原因是在Object.prototype上沒有實現 [Symbol.iterator]() 方法。不過題主也許想問的是為什麼這樣設計,畢竟前ES6時代的 for-in 可以遍歷所有屬性。下面我講一下我的看法。

Iterator的作用是將迭代行為與collection本身分離。但每次都要 new XXXIterator(collection) 很麻煩,[Symbol.iterator]() 的機制相當於提供了默認迭代器。那麼問題就是,如果允許直接 for-of 一個普通對象,其默認迭代行為應該是什麼?這個問題乍一看,似乎沒什麼,直接照搬 for-in 的行為嘛。但是其實一直以來 for-in 的行為就受到詬病,在許多場合我們只希望拿 own properties,因此不得不在 for-in 里用 hasOwnProperty/propertyIsEnumerable 之類的方法過濾。而這是一個低效又麻煩的方式。所以在ES5之後,我們一般不再使用 for-in,而是使用 Object.keys(obj).forEach(...) 來遍歷所有 own properties。那好,我們用這個行為吧?但是慢著,ES6引入了Symbol,我們 for-of 的時候要不要算上 symbols 呢?假如覺得應該包括的話,那麼又有一個問題,是不是要按照 Object.keys() 一樣排除掉 enumerable 為 false 的呢?

總結起來,對象的property至少有三個方面的因素:

1. property的來源:是僅 own property 還是包括原型鏈上的;

2. key的類型:是僅 string 還是包括 symbol 在內;

3. property的[[Enumerable]] attribute:是僅可枚舉(enumerable為true)還是包括不可枚舉的。

這三個因素組合出來就有8種可能。

如果再考慮迭代 key、value、[key, value] 這三種可能,就多達24種組合。

到底哪一種適合作為默認迭代行為?雖然我們可以排除一些,但是要收斂到唯一一種非常難。不像數組,我們直覺上默認迭代就應該那樣;對於對象,有太多不同的用法。既然如此,我們不如把如何迭代留給程序員。比如你可以:

for (const k of Object.keys(obj)) ... // enumerable own keys
for (const [k, v] of Object.entries(obj)) ... // enumerable own [key, value]s
for (const k of Object.getOwnPropertyNames(obj)) // all own keys
for (const s of Object.getOwnPropertySymbols(obj)) // all own symbols
for (const k of Reflect.ownKeys(obj)) // all own keys (include symbols)

其他組合可以自行實現(比如寫個generator)。

最後,理論上未來社區如果形成一致意見,委員會也可以添加 Object.prototype[Symbol.iterator]() 方法,指定某種行為,比如與 Reflect.ownKeys() 對應的 own entries,那樣就可以直接 for-of 對象了。不過我認為這種可能性基本為零。


瀉藥

因為 object 沒有實現 iterator protocol


答主應該是問什麼不部署Iterator介面。這個阮一峰老師的es6入門有說明過。

大概就是:

  1. 對象的哪個屬性先遍歷,哪個屬性後遍歷是不確定的,需要開發者手動指定。

  2. 部署了遍歷器介面的對象其實就是ES6里的Map結構,如果你需要的話,直接使用Map就好了

這裡貼上原文:

對象(Object)之所以沒有默認部署Iterator介面,是因為對象的哪個屬性先遍歷,哪個屬性後遍歷是不確定的,需要開發者手動指定。本質上,遍歷器是一種線性處理,對於任何非線性的數據結構,部署遍歷器介面,就等於部署一種線性轉換。不過,嚴格地說,對象部署遍歷器介面並不是很必要,因為這時對象實際上被當作Map結構使用,ES5沒有Map結構,而ES6原生提供了。


換 es6 map


因為已經有Map了


推薦閱讀:

作為一名前端開發工程師,哪門後端語言最適合掌握?
2016 年前端開發領域有什麼趨勢值得關注?
如何系統的學習nodejs?
為什麼互聯網公司開始用node.js做web服務的中間件?有什麼好處嗎?
前端構建工具webpack有什麼缺陷?

TAG:JavaScript | ECMAScript2015 |