6

我最近console.log通过调用查看了萤火虫的代码console.log.toString()并得到了这个:

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

只要我理解这会导致Function.apply被调用,它的this引用x.log和参数是xand arguments。由于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的回答的第一条评论中所说的,但我仍然不完全理解它。我可能会对此做进一步的研究。

4

1 回答 1

6

考虑一下:

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在我的代码中使用.

于 2013-02-13T21:14:06.077 回答