2013-12-14 11 views
10

całkowicie nowy dla JS, więc proszę wybaczyć, jeśli jest to niepokojąco oczywiste.Dlaczego muszę napisać "function (value) {return my_function (value);}" jako callback w node.js?

Załóżmy, że chcę przefiltrować listę ciągów za pomocą funkcji f odwzorowującej ciąg -> bool. To działa:

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

to zawiedzie:

filteredList = list.filter(f) 

Dlaczego ???

przykładem Kod:

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

Jeśli masz po prostu 'f', to nie ma różnicy. Jeśli wywołujesz funkcję jako metodę obiektu, może być. –

Odpowiedz

17

Ty przechodząc odniesienie do funkcji „test”, ale gdy zostanie wywołany obiekt wyrażenie regularne nie będzie wokół. Innymi słowy, wewnątrz "testu" wartość this będzie wynosić undefined.

Można tego uniknąć:

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

Sposób .bind() zwróci funkcję, która będzie zawsze uruchamiane przy wartości „regex” jako this.

+1

znowu uderz w poncz! :) –

+0

Dzięki, @Pointy! To wyjaśnia. (I @Scott też! =) – Juan

4

Powodem, dla którego często nie można tego zrobić, jest to, że funkcje używane jako metody nie są po prostu metodami. Jeśli użyjesz ich bez wywoływania ich jako metod, wówczas rozwiedzie się ich pierwotny kontekst. Możesz obejść to z Function.prototype.bind:

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