代码之家  ›  专栏  ›  技术社区  ›  sliptype

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

  •  11
  • sliptype  · 技术社区  · 7 年前

    我在尝试使用具有高阶函数的字符串方法时遇到了一件奇怪的事情。这将引发错误:

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

    我必须将谓词包装在另一个函数中才能使其工作。但不是 'boo'.includes 已经是函数了?

    它使用简单的函数:

    const boo = {
        includes: () => true
    };
    
    ['a', 'b'].some(boo.includes)
    

    字符串方法是否有一些特殊的属性阻止它们像这样组合?

    2 回复  |  直到 7 年前
        1
  •  13
  •   ASDFGerte    7 年前

    "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) ,因此缺乏适当的 作为上下文。

    你当然可以用。 bind : ['a', 'b'].some(String.prototype.includes.bind("boo")) ,或使用可选的第二个参数thisArg some : ['a', 'b'].some(String.prototype.includes, "boo") . 这将消除错误。但是,你会注意到 一些 不仅传递元素,而且传递索引作为第二个参数,传递数组本身作为第三个参数。这是个问题,因为 includes 还为起始位置获取可选的第二个参数。这可能会导致不需要的行为,例如数组元素“b”位于索引1处,并且 "boo".includes("b", 1) === false .

    总而言之,你需要一个不同于 字符串.prototype.includes ,它只是更容易将它包装成一个新函数,该函数实际上可以满足您的需要: ['a', 'b'].some(e => "boo".includes(e)) ,正如你已经注意到的。

        2
  •  3
  •   Joseph Sible-Reinstate Monica    7 年前

    斯科特·马库斯的评论是错误的。在函数式编程中,传递函数而不传递它们所需的参数是完全正常的。实际问题是:

    传递给的回调 some 使用三个参数调用: currentValue , index ,和 array ,以及 this 设置为 undefined 除非您将第二个参数传递给 一些 . 方法 String.prototype.includes 接受两个参数: search start ,以及 用作要搜索的字符串。由于这种相互作用, includes 调用时没有要搜索的字符串,因此它会出错。

    即使你通过 bind 或者通过将第二个参数传递给 一些 ,但这并不能完全解决问题。问题的另一半是第二个论点。 一些 认为是 指数 但是 包括 认为是 开始 . 因此 b 在字符串的第二个字符之前不会搜索,因此即使错误将消失,测试仍将返回false。

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