簡體   English   中英

Array.prototype.includes中的錯誤?

[英]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)); 

97失敗,因為呼叫是(有效):

  • parseInt("6", 0) - 有效,因為parseInt忽略無效的基數0
  • parseInt("9", 1) - NaN因為parseInt總是為基數1返回NaN
  • parseInt("7", 2) - NaN因為"7"不是基數2(二進制)中的有效數字

故事的寓意 :記住不常用的參數,即mapsomeforEach和各種其他方法提供給回調。 :-)


在一個代碼庫,我的工作中,他們有一個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中的任何條目,那么您可以構建更具體的實現來根據ab的特性有效地處理它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM