2013-12-14 11 views
10

totalmente nuovo per JS quindi ti prego di perdonare se questo è sbalorditivo.Perché devo scrivere "function (value) {return my_function (value);}" come callback in node.js?

Supponiamo di voler filtrare un elenco di stringhe con una funzione f che associa stringa -> bool. Questo funziona:

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

Questo fallisce:

filteredList = list.filter(f) 

Perché ???

Codice esempio:

~/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

Se si dispone di 'f', quindi non vi è alcuna differenza. Se si chiama una funzione come metodo di un oggetto, potrebbe esserci. –

risposta

17

si sta passando un riferimento alla funzione di "test", ma quando viene chiamato l'oggetto espressione regolare non sarà intorno. In altre parole, all'interno di "test" il valore di this sarà undefined.

Si può evitare che:

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

Il metodo .bind() restituirà una funzione che sarà sempre eseguito con il valore di "espressione regolare", come this.

+1

battere di nuovo il pugno! :) –

+0

Grazie, @Pointy! Questo lo rende chiaro. (E anche @Scott! =) – Juan

4

Il motivo per cui spesso non è possibile fare ciò è che le funzioni utilizzate come metodi non sono semplicemente metodi. Se li usi senza invocarli come metodi, sono quindi divorziati dal loro contesto originale. È possibile aggirare questo con Function.prototype.bind:

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