开发者问题收集

Array.includes 的功能使用导致 TypeError [重复]

2018-07-10
179

我期望 [1].some([1].includes) 返回 true,但我收到一条错误消息:

Uncaught TypeError: Cannot convert undefined or null to object.

您知道是什么原因导致的吗?据我了解, Array.some 接受每个数组项调用的函数, [1].includes 应该会执行该函数。

2个回答

如果按原样传递该函数,则会丢失上下文:当将其作为回调调用时,严格模式下,其内部的 this 值为 undefined (非严格模式下为全局对象),而不是 [1] 。要解决此问题,您可以修复上下文:

[1].some([].includes.bind([1]))

请注意,使用哪个数组访问 includes 函数并不重要;您不妨将其写为...

[1].some( Array.prototype.includes.bind([1]) )

这有点不太简洁,但效率更高(因为没有创建直接数组)。不过,它几乎永远不会成为瓶颈;因此您应该更好地优化可读性。


不幸的是,这还不够。请参阅, Array.includes() 使用 两个 参数:

arr.includes(searchElement[, fromIndex])

... 并且 Array.some() 确实 为其提供了这两个参数(实际上甚至有三个,但 includes 只使用了两个)。这就是为什么这个...

[1,2,3].some([].includes.bind([1])); // true

... 有效,但是这个...

[2,1,3].some([].includes.bind([1])); // false

... 无效: [1] 数组中的查找从第 0、第 1、第 2 个元素开始 - 并且显然在第一个元素之后失败。

要解决此问题,您可以创建一个只接受一个参数的函数,例如 lodash 的 _.unary

[2,1,3].some(_.unary([].includes.bind([1]))) // now we're talking!

... 或者咬紧牙关,改用箭头函数。请注意,您仍然可以在此处使用具有绑定上下文的函数:

const checker = [].includes.bind([1]);
[2,1,3].some(el => checker(el));

... 以使其更加灵活。

raina77ow
2018-07-10

这取决于您使用的 JS 引擎中 includes 的具体实现,但通常标准库函数对于无点式编程不太适用。

通常这是因为上下文 ( this ) 未按预期分配。这可以通过尝试以下内容来显示:

[1].some([1].includes); // Error
[1].some([1].includes.bind([1])) // true

编辑:这个答案并不完全正确。您可能应该阅读 rain77ow 的答案 上面

Alex Young
2018-07-10