totally new to JS so please forgive if this is mind-bogglingly obvious.
Suppose I want to filter a list of strings with a function f that maps string -> bool. This works:
filteredList = list.filter(function(x) { return f(x); })
This fails:
filteredList = list.filter(f)
Why???
Code example:
~/projects/node (master)$ node
> var items = ["node.js", "file.txt"]
undefined
> var regex = new RegExp('\\.js$')
undefined
> items.filter(regex.test)
TypeError: Method RegExp.prototype.test called on incompatible receiver undefined
at test (native)
at Array.filter (native)
at repl:1:8
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
> items.filter(function(value) { return regex.test(value); } )
[ 'node.js' ]
>
You're passing a reference to the "test" function, but when it gets called the regular expression object won't be around. In other words, inside "test" the value of this
will be undefined
.
You can avoid that:
items.filter(regex.test.bind(regex))
The .bind()
method will return a function that'll always run with the value of "regex" as this
.
The reason you often can't do this is that functions used as methods are not simply methods. If you use them without invoking them as methods they are then divorced of their original context. You can get around this with Function.prototype.bind
:
items.filter(regex.test.bind(regex));
As others have said, this
is undefined
when the function reference is called. I'd like to offer a non-reflexive, slightly verbose, alternative:
items.filter(RegExp.prototype.test.bind(/regex/g));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With