摘要:前端開發群原文發表于,轉載請參閱轉載授權。查詢了和,委員會的提案,找到一些細節。前身早前的的提案名為,但由于有很多網站自行了其實主要是因為導致的,看起來就跟上面的代碼類似。而為了和其他特性保持一致所以內部也采用了實現。
ECMAScript 7 中新增了用于檢測數組中是否包含某個元素 Array.prototype.includes() API,想到了 Array 其實有很多相關 API 可以檢測到是否包含某個元素,比如 Array.prototype.indexOf,于是好奇為什么要實現這樣一個 "看起來功能有點重復的 API"。
前端開發 QQ 群:377786580
原文發表于 http://tasaid.com,轉載請參閱 轉載授權。
前言最近又看了下 ECMAScript 7 規范,看到新的規范中包含 Array.prototype.includes(),方法簽名如下:
Array.prototype.includes(value : any): boolean
Array.prototype.includes() 是用于檢測數組中是否包含某個元素。
[0, 1].includes(1) // true ["foo", "bar"].includes("baz") // false
想到了 Array 其實有很多相關 API 可以檢測到是否包含某個元素:
[0, 1].findIndex(i => i == 1) // 1 ["foo", "baz"].find(i => i == "foo") // foo ["foo", "baz"].indexOf("foo") // 0
Array.prototype.findIndex():返回數組中滿足提供的測試函數的第一個元素的索引。否則返回 -1
Array.prototype.find():返回數組中滿足提供的測試函數的第一個元素的值。否則返回 undefined
Array.prototype.indexOf():返回在數組中可以找到一個給定元素的第一個索引,如果不存在,則返回 -1
我們可以簡單的通過判斷實現類似 Array.prototype.includes() 的效果:
export const includes = (sources : any[] searchElement: any): boolean => { return !!~any.indexOf(searchElement) }
于是好奇為什么要實現這樣一個 "看起來功能有點重復的 API"。
查詢了 StackOverflow 和 TC39 (Technical Committee 39,JavaScript 委員會) 的 ECMAScript 提案,找到一些細節。
Array.prototype.includes 前身早前的 Array.prototype.includes 的提案名為 Array.prototype.contains,但由于有很多網站自行 hack 了 Array.prototype.contains(其實主要是因為 MooTools 導致的),看起來就跟上面的代碼類似。
JavaScript 中所有原生提供的方法屬性都是 不可枚舉的( enumerable ) 的,我們可以通過 Object.getOwnPropertyDescriptor(object: any, prototypeName : String) 來獲取這個屬性的屬性描述符 (Property Descriptor)。
Object.getOwnPropertyDescriptor(Array.prototype, "indexOf") // output { writable: true, enumerable: false, configurable: true, value: ?() }
給對象賦值,是不會改變原屬性的屬性描述符,我們可以給 Array.prototype.indexOf 重新賦值,之后獲取它的屬性描述符,會發現 indexOf 仍是不可枚舉的:
Array.prototype.indexOf = () => { return -1 } Object.getOwnPropertyDescriptor(Array.prototype, "indexOf") // output { writable: true, enumerable: false, configurable: true, value: ?() }
而這些網站自行 hack 的 contains() 是可以被枚舉的,也就是可以通過 for..in 讀出來。
發現問題了么?
如果規范實現 contains(),會導致 contains() 無法被 for..in 讀出來,而之前自行 hack 的 contains() 是可以被讀出來的,所以會出現代碼沒變動,但是在新規范推出后會產生 bug 的情況。
在 Array.prototype.contains 初稿階段,考慮到新的規范不能讓世界上許多現有的網站出問題,所以改名成了 Array.prototype.includes。
細節 起源雖然我們可以使用 indexOf() 來模擬 includes() 的行為,但是 indexOf() 在語義上無法清晰的描述這個場景。
includes() 是明確的判斷 "是否包含該項",而 indexOf() 是 "查找數組中第一次出現對應元素的索引是什么,再針對返回的索引進一步處理邏輯",例如下面的代碼:
// indexOf if (~arr.indexOf(1)) { // do something } // includes if (arr.includes(1)) { // do something }為什么叫做 includes 而不是 has
has 是用于 key 的,而 includes 是檢測 value 的:
let foo = new Map() foo.set("name", "linkFly") foo.has("name") // trueSameValueZero
Array.prototype.includes 底層使用了 SameValueZero() 進行元素比較。
目前 ES2015 草案中有四種相等算法:
抽象標準相等比較:實現接口是 == 運算符
嚴格相等比較:實現接口是 === 運算符,Array.prototype.indexOf 就是使用這種比較
SameValueZero():沒有直接暴露的接口,內部實現接口是 Map 與 Set
const foo = new Map() foo.set(0, "0") // Map(1) {0 => "0"} foo.set("0", "zero") // Map(2) {0 => "0", "0" => "zero"} foo.get(0) // 0 foo.get("0") // zero
SameValue():實現接口是 Object.is()
NaN === NaN // false Object.is(NaN, NaN) // true -0 === +0 // true Object.is(-0, +0) // false
和 SameValue() 不同的是,SameValueZero() 不區分 +0 和 -0。而 includes 為了和 JavaScript 其他特性保持一致 所以內部也采用了 SameValueZero 實現。
所以 Array.prototype.includes 也不區分 +0 和 -0 ,當然也可以檢測 NaN:
[-0].includes(+0) // true [NaN].includes(NaN) // true [NaN].indexOf(NaN) // -1
具體的相等比較運算符差異請參閱 MDN - Equality comparisons and sameness。
具體 Array.prototype.includes 實現的細節可以參考 ecma-262/ECMAScript 7 實現規范。
參考和引用tc39 - Array.prototype.includes Proposal
Having a non-enumerable Array.prototype.contains may not be web-compatible
ECMAScript? 2016 Language Specification - Array.prototype.includes
ECMAScript? 2015 Language Specification - SameValueZero
stackoverflow - How do I check if an array includes an object in JavaScript?
http://2ality.com/2016/02/array-prototype-includes.html
Bugzilla@Mozilla - non-enumerable Array.prototype.contains is not web-compatible (breaks jsfiddle.net)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/85023.html
摘要:寫的姿勢前兩天去帝都參加第三屆前端開發者大會,見了很多老朋友,也認識了很多新朋友。 推薦 1. 組件化設計思維 – 從規范到工具的構建與探索 http://www.zcool.com.cn/artic... 阿里巴巴在中臺戰略的背景下,設計提效又再次推動著設計思維的變革。設計師們不僅僅需要出色地完成業務需求的設計,同時還需要思考設計的價值,也就是經常提到的最佳方案性價比。我們需要在設計...
摘要:寫的姿勢前兩天去帝都參加第三屆前端開發者大會,見了很多老朋友,也認識了很多新朋友。 推薦 1. 組件化設計思維 – 從規范到工具的構建與探索 http://www.zcool.com.cn/artic... 阿里巴巴在中臺戰略的背景下,設計提效又再次推動著設計思維的變革。設計師們不僅僅需要出色地完成業務需求的設計,同時還需要思考設計的價值,也就是經常提到的最佳方案性價比。我們需要在設計...
摘要:由于網景公司希望能在靜態頁面上添加一些動態效果,于是叫這哥們在兩周之內設計出了語言。所以簡單說來就是,是一種語言標準,而是網景公司對標準的一種實現。 JavaScript基礎拾遺 study notes by Tingting 為啥說JavaScript的基礎 在平時開發時,我們更多的是在寫PHP的邏輯層,但是在寫后臺時多多少少會寫一寫JavaScript的代碼,有時候我們就會遇到對j...
摘要:還規定了無窮及其它的相應規范,有興趣可自行查找相關資料。其它相同數值相等。類型中,引用同一對象,相等。不同點對的判斷上各有不同。以為代表的相等和相等以為代表的不相等和相等以為代表的相等和不相等相同類型采用嚴格比較。 相等不相等? 先來隨便舉幾個?吧~ 0 == true //? [1] == [1] //? [1] == 1 ...
摘要:可選到該位置前停止讀取數據,默認等于數組長度。找出第一個符合條件的數組元素,參數是一個回調函數,所有數組元素依次執行該回調函數,直到找出第一個返回值為的元素,然后返回該元素?;卣{函數可以接受三個參數,依次為當前的值當前的位置和原數組。 ECMAScript 5.1 中提供的數組方法 ECMA-262/5.1 規范 判斷是否是數組 Array.isArray ( arg ) // fal...
閱讀 632·2021-11-22 15:32
閱讀 2720·2021-11-19 09:40
閱讀 2313·2021-11-17 09:33
閱讀 1263·2021-11-15 11:36
閱讀 1864·2021-10-11 10:59
閱讀 1475·2019-08-29 16:41
閱讀 1780·2019-08-29 13:45
閱讀 2150·2019-08-26 13:36