Is there an easier way to call filter on a prototype method without an anonymous function?
I wonder if there is an equivalent to myArray.filter(function(it){ it.method() })
.
This looks close to what might work (it doesn't):
function X() {}
X.prototype.method = function() { console.log(this); }
[new X(), new X()].filter(X.prototype.method.call);
Instead I get a TypeError in both latest Firefox and Chrome, it's because it doesn't quite do what I want:
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
I tried using bind, maybe I'm missing it, but if it's not a one-liner, it's not any better than the anonymous method form:
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);
Let's set up some variables:
var method = X.prototype.method,
array = [new X(), new X()];
Your attempt can now be written as:
array.filter(method.call);
The problem is that call
is getting called but with no this
. It needs a this
of method
. method.call
is precisely the same as the raw Function.prototype.call
, with no binding to any this
. Merely saying method.call
does not give you a version of call
bound to method
. To arrange for call
to be bound to the right this
, namely method
, you need to, well, bind it:
array.filter(method.call.bind(method));
Walking through this:
method.call.bind(method)
returns a new version of Function#call
which is bound to X#method
; think of it as method.call(waiting)
, which is waiting to be called with a value which will call X#method
against a particular instance of X.
Array#filter
passes each argument in the array to that bound version of Function#call
, which results in method.call(elt, remaining_args...)
, which is the equivalent of elt.method(remaining_args...)
.
Output:
> array.filter(method.call.bind(method));
X {method: function}
X {method: function}
One could make this more semantic and readable with a little wrapper, which we will call thisify
:
function thisify(fn) { return fn.call.bind(fn); }
array.filter(thisify(method));
context
parameter to filter
You could use the little-used context
parameter of filter
and its brethren (except reduce ), essentially, letting filter
do the binding for you, if you choose to look at it that way, since
Array#filter(fn, context) === Array#filter(fn.bind(context))
So we can just write:
array.filter(method.call, method);
That actually looks cleaner to me. I doubt if it could get much simpler than that.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.