javascript - Function.apply vs. Function.prototype.apply


Jag tittade nyligen på koden för firebugs console.log genom att anropa console.log.toString() och fick detta:

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

Så länge jag förstår detta orsakar att Function.apply kallas med dess this som refererar till x.log och argumenten som x och arguments. Eftersom Function.apply själv kallar på funktioner kommer detta att resultera i att x.log kallas med dess this som refererar till x och arguments som dess argument.

Vilket leder mig till min fråga: Finns det någon anledning att kalla Function.apply på detta sätt istället för att bara använda Function.prototype.apply? Eller med andra ord, finns det någon skillnad mellan ovanstående och return x.log.apply(x, arguments)?

Redigera: Eftersom det är öppen källkod tog jag en snabb titt på Firebug-källkoden och hittade platsen där detta skapas (consoleInjector.js, rad 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);

Jag är nästan säker nu på att detta har något att göra med att Function är i ett annat omfång, vilket är vad jag sa i min första kommentar till psts svar, men jag förstår det fortfarande inte fullt ut. Jag kanske gör lite mer forskning om det.

Svar #1

Tänk på detta:

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

Så Function.apply fungerar eftersom Functions [[prototype]] är Function.prototype. I det här fallet borde båda fungera som önskat.

Tänk dock på att de normala [GetProperty]-reglerna fortfarande gäller:

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

Visserligen skulle jag betrakta det som "tvivelaktig kod" att ändra beteendet hos apply (och särskilt på ett inkompatibelt sätt), men det är möjligt att de två formerna skiljer sig åt .. Personligen tar jag inte hänsyn till sådana hypotetiska situationer och jag använder f.apply i min kod.