2013-12-14 19 views
10

völlig neu in JS so bitte verzeihen Sie, wenn das ist unglaublich offensichtlich.Warum muss ich "function (value) {return my_function (value);}" als Callback in node.js schreiben?

Angenommen, ich möchte eine Liste von Strings mit einer Funktion f filtern, die string -> bool abbildet. Dies funktioniert:

filteredList = list.filter(function(x) { return f(x); }) 

Dies schlägt fehl:

filteredList = list.filter(f) 

Warum ???

Code-Beispiel:

~/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' ] 
> 
+1

umgehen Wenn Sie nur 'f' haben, dann gibt es keinen Unterschied. Wenn Sie eine Funktion als eine Methode eines Objekts aufrufen, könnte es sein. –

Antwort

17

Sie einen Verweis auf die „Test“ Funktion übergeben, aber wenn es das reguläre Ausdruck Objekt wird nicht in der Nähe aufgerufen wird. Mit anderen Worten, innerhalb von "Test" wird der Wert thisundefined sein.

Sie können das vermeiden:

items.filter(regex.test.bind(regex)) 

Die .bind() Methode wird eine Funktion zurück, die immer mit dem Wert von „regex“ als this ausgeführt werden.

+1

Schlag auf den Schlag wieder! :) –

+0

Danke, @ Pointy! Das macht es klar. (Und @Scott auch! =) – Juan

4

Der Grund, warum Sie dies oft nicht tun können, ist, dass Funktionen, die als Methoden verwendet werden, nicht einfach Methoden sind. Wenn Sie sie verwenden, ohne sie als Methoden aufzurufen, werden sie von ihrem ursprünglichen Kontext getrennt. Sie können dies mit Function.prototype.bind:

items.filter(regex.test.bind(regex));