2013-02-13 8 views
5

Niedawno spojrzał w kodzie firebugs console.log wywołując console.log.toString() i got to:Function.apply vs. funkcji Function.prototype.apply

function() { return Function.apply.call(x.log, x, arguments); } 

Dopóki Rozumiem to powoduje Function.apply być wywołana z jego this odnosząc się do x.log i argumentów: x i arguments. Ponieważ samo Function.apply wywołuje funkcje, które będą wywoływane, x.log będzie wywoływane z jego this odnosząc się do x i arguments jako jego argumenty.

Co prowadzi mnie do mojego pytania: Czy istnieje jakiś powód, by nazwać Function.apply w ten sposób, a nie tylko za pomocą Function.prototype.apply? Lub innymi słowy, czy jest jakaś różnica między powyższym a return x.log.apply(x, arguments)?

Edit: Ponieważ jest to open source Wziąłem szybki rzut oka na źródłowego Firebug i znaleźć miejsce, w którym ta jest tworzona (consoleInjector.js, linia 73):

// Construct a script string that defines a function. This function returns 
// an object that wraps every 'console' method. This function will be evaluated 
// in a window content sandbox and return a wrapper for the 'console' object. 
// Note that this wrapper appends an additional frame that shouldn't be displayed 
// to the user. 
var expr = "(function(x) { return {\n"; 
for (var p in console) 
{ 
    var func = console[p]; 
    if (typeof(func) == "function") 
    { 
     expr += p + ": function() { return Function.apply.call(x." + p + 
      ", x, arguments); },\n"; 
    } 
} 
expr += "};})"; 

// Evaluate the function in the window sandbox/scope and execute. The return value 
// is a wrapper for the 'console' object. 
var sandbox = Cu.Sandbox(win); 
var getConsoleWrapper = Cu.evalInSandbox(expr, sandbox); 
win.wrappedJSObject.console = getConsoleWrapper(console); 

jestem już prawie pewien, że ma to coś wspólnego z Function, aby znaleźć się w innym zakresie, o czym pisałem w moim pierwszym komentarzu do odpowiedzi pst, ale wciąż nie w pełni to rozumiem. Mogę zrobić trochę dalszych badań na ten temat.

+0

Jestem ciekawy, dlaczego kod nie jest tylko przy użyciu wyniku 'Cu.evalInSandbox (" Funkcja ", sandbox)' w standardowym podejściem zamknięcia (jak obiekt-obiekty są najwyraźniej zwrócone), ale najwyraźniej tam to jest powód. właściwie to nie ma większego znaczenia, ponieważ jedna z tych funkcji powinna zostać zamknięta; chyba że będzie więcej magii w 'evalInSandbox' .. –

Odpowiedz

4

Rozważ to:

Function.hasOwnProperty("apply")    // false 
Function.apply == Function.prototype.apply // true 
Function.__proto__ == Function.prototype  // true in FF which exposes proto 

Więc Function.apply działa, ponieważ funkcja jest [[prototyp]] jest Function.prototype. W tym przypadku oba powinny działać zgodnie z oczekiwaniami.

jednak pod uwagę, że normalne [GetProperty] zasady nadal obowiązują:

var f = function() {}; 
f.apply = "nubbits"; 
f.apply(/* err */); 

prawda, Pomyślę o tym „Kod wątpliwa”, aby zmienić zachowanie apply (a zwłaszcza w niezgodnym sposób), ale to możliwe, że te dwie formy różnią się. Osobiście, robię nie przyjmować takie hipotetyczne sytuacje i używam f.apply w moim kodzie.

+0

Zastanawiam się nad tym - dlaczego miałbym" lepiej "użyć' Function.prototype.apply' zamiast 'myFunc.apply' (drugiego pytania OP)? – Ian

+0

@Ian Być może preferuje się "wyraźną formę". Nie mogę wymyślić jakiegoś wyjątkowego powodu, który napotkałem w moim kodzie - ja, wolę 'fn.apply'. (A jeśli ktoś zmienia to, co robi, to jest na nich ..) –

+0

Czyliby to tylko po to, aby powstrzymać zmianę zachowania 'console.log.apply'? Trudno myśleć, że jest to jedyny powód ... Sądzę też, że można to zrobić z powodu "funkcji" (tej, do której nazywane jest 'apply '), aby znaleźć się w innym zakresie, który najprawdopodobniej był problem tutaj: http://stackoverflow.com/questions/14715140/why-does-prototyping-function-not-affect-console-log – YingYang

Powiązane problemy