繁体   English   中英

原型方法上的JS Array.prototype.filter

[英]JS Array.prototype.filter on prototype method

有一种更简单的方法来在没有匿名函数的原型方法上调用过滤器吗?

我想知道是否有与myArray.filter(function(it){ it.method() })

这看起来很接近可能有用的东西(它没有):

function X() {}
X.prototype.method = function() { console.log(this); }

[new X(), new X()].filter(X.prototype.method.call);

相反,我在最新的Firefox和Chrome中都遇到了TypeError,这是因为它不能完全按我的意愿行事:

x = function() { console.log(this) }
x.call(123) //logs 123
y = x.call //reports that y is of type function in console
y(123) //TypeError: Function.prototype.call called on incompatible undefined
y.call(x, 123); //this is what you really need

我尝试使用bind,也许我错过了它,但如果它不是单行,那么它并不比匿名方法形式更好:

function X() {}
X.prototype.method = function() { console.log(this); }

y = X.prototype.method.call
y.bind(X.prototype.method)

[new X(), new X()].filter(y);

让我们设置一些变量:

var method = X.prototype.method,
    array = [new X(), new X()];    

您的尝试现在可以写成:

array.filter(method.call);

问题是call被调用但没有this 它需要this method method.call恰恰是一样的原始Function.prototype.call ,没有绑定任何this 仅仅说method.call没有给你一个绑定到methodcall版本。 为了安排call绑定到右边this method ,你需要绑定它:

array.filter(method.call.bind(method));

走过这个:

  1. method.call.bind(method)返回一个新版本的Function#call ,它绑定到X#method ; 把它想象成method.call(waiting) ,它等待用一个值来调用,该值将针对特定的X实例调用X#method

  2. Array#filter将数组中的每个参数传递给Function#call绑定版本,这会产生method.call(elt, remaining_args...) ,它相当于elt.method(remaining_args...)

输出:

> array.filter(method.call.bind(method));
  X {method: function}
  X {method: function}

一些糖

一个人可以用一个小包装器使这个更具语义和可读性,我们称之为thisify

function thisify(fn) { return fn.call.bind(fn); }

array.filter(thisify(method));

使用context参数进行filter

您可以使用filter及其兄弟(除了reduce )之前使用的context参数,基本上,让filter为您执行绑定,如果您选择以这种方式查看它,

Array#filter(fn, context) === Array#filter(fn.bind(context))

所以我们可以写:

array.filter(method.call, method);

这对我来说实际上看起来更干净 我怀疑它是否会变得简单得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM