在尝试将String方法与高阶函数一起使用时,我遇到了奇怪的事情。这将引发错误:
['a', 'b'].some('boo'.includes)
我必须将谓词包装在另一个函数中以使其起作用。但是'boo'.includes
已经不是一个函数吗?
这适用于普通功能:
const boo = {
includes: () => true
};
['a', 'b'].some(boo.includes)
String方法是否有一些特殊的属性,可以防止它们像这样构成?
答案 0 :(得分:13)
"boo".includes
只不过是String.prototype.includes
。但是,在字符串“ boo”上调用它会将this
设置为“ boo”,这为函数提供了适当的上下文。例如。 "boo".includes("b")
与String.prototype.includes.call("boo", "b")
相同。
将其作为参数传递,例如['a', 'b'].some('boo'.includes)
与['a', 'b'].some(String.prototype.includes)
相同,因此缺少适当的this
作为上下文。
您当然可以使用例如bind
:['a', 'b'].some(String.prototype.includes.bind("boo"))
,或为some
:['a', 'b'].some(String.prototype.includes, "boo")
使用可选的第二个参数thisArg。这将消除错误。但是,您会发现some
不仅传递元素,还传递索引作为第二个参数,并将数组本身传递给第三个。这是一个问题,因为includes
也为起始位置采用了可选的第二个参数。这会导致可能的不良行为,例如数组元素“ b”位于索引1和"boo".includes("b", 1) === false
处。
总而言之,您需要一个与String.prototype.includes
截然不同的函数,以使其更容易包装在一个实际上可以实现您想要的功能的新函数中:
['a', 'b'].some(e => "boo".includes(e))
,您已经注意到了。
答案 1 :(得分:3)
Scott Marcus的评论不正确。在函数式编程中,不带参数就传递函数是完全正常的。这是实际的问题:
传递给some
的回调使用三个参数调用:currentValue
,index
和array
,其this
设置为{{ 1}},除非您将第二个参数传递给undefined
。方法some
带有两个参数:String.prototype.includes
和search
,其start
用作要搜索的字符串。交互作用的结果是,this
被调用而没有要搜索的字符串,因此会产生错误。
即使通过includes
或通过向bind
传递第二个参数来解决上述问题,也无法完全解决问题。问题的另一半是第二个论点。 some
认为它是some
,但是index
认为它是includes
。结果,直到字符串的第二个字符都不会搜索start
,因此即使错误消失了,测试仍将返回false。
在这种情况下,不可避免要使用包装函数来获得所需的行为。