具有高阶函数的字符串方法

时间:2018-08-08 01:05:15

标签: javascript

在尝试将String方法与高阶函数一起使用时,我遇到了奇怪的事情。这将引发错误:

['a', 'b'].some('boo'.includes)

我必须将谓词包装在另一个函数中以使其起作用。但是'boo'.includes已经不是一个函数吗?

这适用于普通功能:

const boo = {
    includes: () => true
};

['a', 'b'].some(boo.includes)

String方法是否有一些特殊的属性,可以防止它们像这样构成?

2 个答案:

答案 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的回调使用三个参数调用:currentValueindexarray,其this设置为{{ 1}},除非您将第二个参数传递给undefined。方法some带有两个参数:String.prototype.includessearch,其start用作要搜索的字符串。交互作用的结果是,this被调用而没有要搜索的字符串,因此会产生错误。

即使通过includes或通过向bind传递第二个参数来解决上述问题,也无法完全解决问题。问题的另一半是第二个论点。 some认为它是some,但是index认为它是includes。结果,直到字符串的第二个字符都不会搜索start,因此即使错误消失了,测试仍将返回false。

在这种情况下,不可避免要使用包装函数来获得所需的行为。