2012-01-29 30 views
6

W kodzie poniżej mogę użyć print zamiast console.log i program może działać poprawnie. Jednak chciałbym skorzystać console.log ale mamJak przekazać plik console.log jako argument do mojej funkcji JavaScript?

nielegalnym inwokację

przy starcie

function forEach(array, action) { 
    for (var i=0; i<array.length; i++) 
     action(array[i]); 
} 

forEach(["blah", "bac"], console.log); 
+0

będzie działać, jeśli przechodzą tylko 'console' i nazywają' log' wewnątrz dla całej funkcji. –

Odpowiedz

7

Ogólnie nie można przekazywać metod bezpośrednio do wywołań zwrotnych w JavaScript.this jest zobowiązany w momencie wywołania funkcji, w zależności od tego, co tworzą to nazwać i nie ma automatycznego wiązania metod (jak tam jest, na przykład, Python)

//does not work. 
var obj = { 
    x: 17, 
    f: function(){ return this.x; } 
}; 

//inside doSomething, f forgets its "this" should be obj 
doSomething(obj.f) 

W tych przypadkach, może użyć Function.prototype.bind (lub podobną funkcję z biblioteki wyboru, ponieważ bind nie jest obecny w IE < = 8)

//works (for normal methods - see next bit for console.log in particular) 
var obj = { 
    x: 17, 
    f: function(){ return this.x; } 
}; 

doSomething(obj.f.bind(obj)) 

Niestety, to nie zawsze wystarcza do console.log. Ponieważ nie jest to faktyczna funkcja w IE, (jest to obiekt będący złym hostem), nie można używać do tego celu metody powiązania, stosowania i wywoływania w tej przeglądarce, więc jedyne obejście wraca do zawijania połączenia w anonimowej funkcji

doSomething(function(x){ 
    return console.log(x); 
}); 

Od owijania konsoli.Zaloguj anonimowej funkcji jest długa i irytujące typu I zwykle dodać następujące globalną funkcję kiedy jestem rozwijających się i debugowanie:

function log(message){ return function(x){ 
    return console.log(message, x); 
};}; 

forEach(['asd', 'zxc'], log('->')); 
4

stąd: Create shortcut to console.log() in Chrome

Można zastąpić console.log z console.log.bind(console)

Wyjaśnienie dzięki @ Julian D:

Ponieważ console.log skieruje wewnętrznie this i oczekuje, że być console. Jeśli "odłączysz" metodę log, np. podobnie jak var log = console.log, to powiązanie zostanie utracone, a to nie będzie już wskazywać na console (w tym przypadku zamiast tego na window - jeśli jesteś w przeglądarce). Jest to celem .bind(obj): zwraca metodę, w której wewnętrznie this zostaje ustalona na obj.

+0

, ale dlaczego nie możesz zrobić "log = console.log", a następnie? – meze

+2

@meze: ponieważ 'console.log' odwoła się wewnętrznie do' this' i oczekuje, że będzie to 'console'. Jeśli "odłączysz" metodę "log", np. jak 'var log = console.log', to powiązanie zostanie utracone, a' this' nie będzie już wskazywał 'konsoli' (w tym przypadku zamiast' window' - jeśli jesteś w przeglądarce). Jest to celem '.bind (obj)': zwraca metodę, w której wewnętrznie 'this' pozostaje ustawiony na' obj'. –

+0

Pamiętaj, że 'bind' nie jest dostępny we wszystkich przeglądarkach. Zobacz odpowiedź z @frm dla rozwiązania, które nie wymaga "bind". –

3

można rozwiązać problemu, korzystając anonimową funkcję działając jako pomost między forEach() i console.log()

forEach(["blah", "bac"], function (element) { 
    console.log(element); 
}); 

Twój forEach() pozostaje agnostykiem o przewodnika i nie trzeba się pogodzić z bind() zdać działające odniesienie do console.log().

Powiązane problemy