[英]Bug in Array.prototype.includes?
我在一個邊緣情況下遇到了Array.prototype.includes
奇怪行為。
鑒於Array.prototype.includes
對綁定上下文有效,可以像這樣使用它(它正在工作)
expect(Array.prototype.includes.call([1, 2], 1))).toBe(true)
簡單地說,我們綁定數組[1, 2]
和測試1
包含。
然后考慮一下,許多Array.prototype方法能夠將上下文綁定到提供的回調,因此例如Array.prototype.some
可以與Object.prototype.hasOwnProperty
結合使用,就像這樣
expect(["foo", "bar"].some(Object.prototype.hasOwnProperty, { foo: 0 })).toBe(true)
這里, .some
接受兩個參數, (callback, [thisArg])
,其中可選thisArg
,如果提供,則綁定到回調,因此前面的示例將{ foo: 0 }
綁定到回調Object.prototype.hasOwnProperty
,然后測試所有項目["foo", "bar"]
如果至少有一個是{ foo: 0 }
自有屬性。 這個例子也有效。
但是如果你嘗試使用Array.prototype.includes
作為回調,那么會發生一些奇怪的事情。
[0, 1].some(Array.prototype.includes, [1]) // => false
這里我們將array [1]
綁定到Array.prototype.includes
,如果包含至少一個,我們測試[0, 1]
每個項目。 但這種情況會返回false,這違背了我們的預期。
奇怪的是,如果綁定數組包含除1
以外的其他數字或包含多個項目,則測試通過
[0, 1].some(Array.prototype.includes, [0]) // => true
[0, 1].some(Array.prototype.includes, [1, 1]) // => true
// but
[0, 1].some(Array.prototype.includes, [1]) // => false
似乎數組[1]
處理不當。
在Node v.11.11.0 Node v.8.11.3和Chrome 73中測試
我基本上只測試了V8發動機。 任何人都可以在Chakra報告輸出嗎?
這不是一個錯誤includes
。 :-)
問題是includes
接受一個可選的第二個參數,它是開始搜索的索引, some
參數為其回調提供了三個參數:項目,索引和被搜索的對象。
所以
[0, 1].some(Array.prototype.includes, [1])
這些調用是(有效地):
[1].includes(0, 0)
- false,數組不包含0
[1].includes(1, 1)
- false,數組在索引0
處包含1
,但搜索從索引1
開始 這會定期出現。 例如,當嘗試使用parseInt
作為回調直接將字符串數組轉換為數字數組時,因為parseInt
的第二個參數(要使用的數字基數或基數):
console.log(["6", "9", "7"].map(parseInt));
9
和7
失敗,因為呼叫是(有效):
parseInt("6", 0)
- 有效,因為parseInt
忽略無效的基數0
。 parseInt("9", 1)
- NaN
因為parseInt
總是為基數1
返回NaN
parseInt("7", 2)
- NaN
因為"7"
不是基數2(二進制)中的有效數字 故事的寓意 :記住不常用的參數,即map
, some
, forEach
和各種其他方法提供給回調。 :-)
在一個代碼庫,我的工作中,他們有一個clamp
,也是接收功能,並確保,不管是多少個參數調用,它只會傳遞參數的所需數量的功能。 如果您使用這樣的includes
很多,您可以創建一個includes
:
function clamped(fn, count) { return function(...args) { return fn.apply(this, args.slice(0, count)); } } const includes = clamped(Array.prototype.includes, 1); console.log([0, 1].some(includes, [1])); // true console.log([0, 1].some(includes, [3])); // false
關於這一點的便利之處在於includes
可重復使用。
或者當然,只需使用包裝函數:
console.log([0, 1].some(function(entry) { return this.includes(entry); }, [1])); // true console.log([0, 1].some(function(entry) { return this.includes(entry); }, [3])); // false
當然,這些都是通用的解決方案。 如果您特別想知道數組a
包含數組b
中的任何條目,那么您可以構建更具體的實現來根據a
和b
的特性有效地處理它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.