Function.apply vs. Function.prototype.apply

Function.apply vs. Function.prototype.apply

本文关键字:Function apply prototype vs      更新时间:2023-09-26

我最近通过调用console.log.toString()查看了firebug console.log的代码,得到了以下内容:

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

只要我理解这会导致Function.apply被调用,其this指的是x.log,自变量是xarguments。由于Function.apply本身调用函数,这将导致x.log被调用,其this引用xarguments作为其自变量。

这就引出了我的问题:有什么理由用这种方式调用Function.apply而不仅仅是使用Function.prototype.apply吗?或者换句话说,上述内容与return x.log.apply(x, arguments)之间有什么区别吗?

编辑:由于它是开源的,我快速查看了firebug源代码,并找到了创建它的位置(consoleInjector.js,第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);

我现在几乎可以肯定,这与Function处于不同的范围有关,这是我在对pst的回答的第一次评论中所说的,但我仍然不完全理解。我可能会对此做一些进一步的研究。

考虑一下:

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

因此Function.apply之所以有效,是因为Function的[[prototype]]是Function.prototype。在这种情况下,两者都应该按需工作。

但是,请考虑正常的[GetProperty]规则仍然适用:

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

诚然,我认为更改apply的行为(尤其是以不兼容的方式)是"有问题的代码",但这两种形式可能不同。。就我个人而言,我确实而不是适应这种假设情况,并且我在代码中使用f.apply