[英]Bug in Array.prototype.includes?
I encountered strange behavior of Array.prototype.includes
in one edge case. 我在一个边缘情况下遇到了
Array.prototype.includes
奇怪行为。
Given that Array.prototype.includes
works on bound context, one might use it like this (which is working) 鉴于
Array.prototype.includes
对绑定上下文有效,可以像这样使用它(它正在工作)
expect(Array.prototype.includes.call([1, 2], 1))).toBe(true)
simply put, we bound array [1, 2]
and test 1
for inclusion. 简单地说,我们绑定数组
[1, 2]
和测试1
包含。
Then consider, that many Array.prototype methods are able to bound context to provided callback, so for example Array.prototype.some
can be combined with Object.prototype.hasOwnProperty
like this 然后考虑一下,许多Array.prototype方法能够将上下文绑定到提供的回调,因此例如
Array.prototype.some
可以与Object.prototype.hasOwnProperty
结合使用,就像这样
expect(["foo", "bar"].some(Object.prototype.hasOwnProperty, { foo: 0 })).toBe(true)
Here, .some
accepts two parameters, (callback, [thisArg])
, where optional thisArg
, when provided, is bound to callback, thus previous example binds { foo: 0 }
to callback Object.prototype.hasOwnProperty
and then tests all items in ["foo", "bar"]
if at least one is own property of { foo: 0 }
. 这里,
.some
接受两个参数, (callback, [thisArg])
,其中可选thisArg
,如果提供,则绑定到回调,因此前面的示例将{ foo: 0 }
绑定到回调Object.prototype.hasOwnProperty
,然后测试所有项目["foo", "bar"]
如果至少有一个是{ foo: 0 }
自有属性。 This example is also working. 这个例子也有效。
But something strange happen, if you try to use Array.prototype.includes
as callback. 但是如果你尝试使用
Array.prototype.includes
作为回调,那么会发生一些奇怪的事情。
[0, 1].some(Array.prototype.includes, [1]) // => false
here we bind array [1]
to Array.prototype.includes
and we test every item of [0, 1]
if at least one is included. 这里我们将array
[1]
绑定到Array.prototype.includes
,如果包含至少一个,我们测试[0, 1]
每个项目。 But this case returns false, which is against our expectation. 但这种情况会返回false,这违背了我们的预期。
Strangely, if bound array contains other number than 1
or contains more than one item, the test passes 奇怪的是,如果绑定数组包含除
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
It seems like array [1]
is handled improperly. 似乎数组
[1]
处理不当。
Tested in Node v.11.11.0 Node v.8.11.3 and Chrome 73 在Node v.11.11.0 Node v.8.11.3和Chrome 73中测试
I tested basically just V8 engine. 我基本上只测试了V8发动机。 Can anyone report output in Chakra?
任何人都可以在Chakra报告输出吗?
It's not a bug in includes
. 这不是一个错误
includes
。 :-) :-)
The problem is that includes
accepts an optional second parameter, which is the index at which to start searching, and some
provides three arguments to its callback: The item, its index, and the object being searched. 问题是
includes
接受一个可选的第二个参数,它是开始搜索的索引, some
参数为其回调提供了三个参数:项目,索引和被搜索的对象。
So with 所以
[0, 1].some(Array.prototype.includes, [1])
These calls are made (effectively): 这些调用是(有效地):
[1].includes(0, 0)
- false, the array doesn't contain 0
[1].includes(0, 0)
- false,数组不包含0
[1].includes(1, 1)
- false, the array contains 1
at index 0
, but the search starts at index 1
[1].includes(1, 1)
- false,数组在索引0
处包含1
,但搜索从索引1
开始 This comes up periodically. 这会定期出现。 For instance, when trying to use
parseInt
as a callback directly to convert an array of strings into an array of numbers, because of parseInt
's second parameter (the number base, or radix, to use): 例如,当尝试使用
parseInt
作为回调直接将字符串数组转换为数字数组时,因为parseInt
的第二个参数(要使用的数字基数或基数):
console.log(["6", "9", "7"].map(parseInt));
The 9
and 7
fail becaue the calls are (effectively): 9
和7
失败,因为呼叫是(有效):
parseInt("6", 0)
- works because parseInt
ignores the invalid radix 0
. parseInt("6", 0)
- 有效,因为parseInt
忽略无效的基数0
。 parseInt("9", 1)
- NaN
because parseInt
always returns NaN
for radix 1
parseInt("9", 1)
- NaN
因为parseInt
总是为基数1
返回NaN
parseInt("7", 2)
- NaN
because "7"
is not a valid digit in base 2 (binary) parseInt("7", 2)
- NaN
因为"7"
不是基数2(二进制)中的有效数字 The moral of the story : Remember the not-commonly-used arguments that map
, some
, forEach
, and various other methods provide to callbacks. 故事的寓意 :记住不常用的参数,即
map
, some
, forEach
和各种其他方法提供给回调。 :-) :-)
In one codebase I was working in, they had a clamp
function that accepted a function and ensured that, regardless of how many arguments it was called with, it would only pass on the desired number of arguments. 在一个代码库,我的工作中,他们有一个
clamp
,也是接收功能,并确保,不管是多少个参数调用,它只会传递参数的所需数量的功能。 If you were using includes
like this a lot, you could create a clamped includes
: 如果您使用这样的
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
The handy thing about that is that that includes
is reusable. 关于这一点的便利之处在于
includes
可重复使用。
Or of course, just use a wrapper function: 或者当然,只需使用包装函数:
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
These are all meant to be general solutions, of course. 当然,这些都是通用的解决方案。 If you specifically want to know if array
a
contains any of the entries in array b
, there are more specific implementations you can build to handle that efficiently depending on the characteristics of a
and b
. 如果您特别想知道数组
a
包含数组b
中的任何条目,那么您可以构建更具体的实现来根据a
和b
的特性有效地处理它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.