(问题 1)
在 Flanagan 的 JS Definitive Guide 中,他定义了Function
方法bind()
以防万一它不可用(在 ECMAScript 3 中不可用)。
它看起来像这样:
function bind(f, o) {
if (f.bind) return f.bind(o); // Use the bind method, if there is one
else return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
他用一个例子来说明它的用法(我已经修改了它以将第 3 行从 更改f.bind(o)
):
function f(y) { return this.x + y; } // This function needs to be bound
var o = { x : 1 }; // An object we'll bind to
var g = bind(f, o); // Calling g(x) invokes o.f(x)
g(2) // => 3
当我第一次看到这个时,我想“不会arguments
在我们定义的绑定函数中引用 arguments 变量吗?但是我们想要最终应用它的函数的 arguments 属性,就像上面示例中的 g ...... "
我验证了他的示例确实有效,并推测该行return f.apply(o, arguments)
直到var g = bind(f, o)
上面才被评估。也就是说,我想,当你返回一个函数时,你只是返回那个函数的源代码,不是吗?直到它被评估?所以我通过尝试一个稍微不同版本的绑定来测试这个理论:
function mybind2(f, o) {
var arguments = 6;
return function() { // Otherwise, bind it like this
return f.apply(o, arguments);
};
}
如果它只是简单地返回未评估的函数源,那么arguments = 6
在以后评估时它就无法存储,对吧?在检查之后,我仍然得到g(2)
=> 3。但后来我意识到——如果它只是返回未评估的代码,那么o
in是return f.apply(o, arguments)
如何通过的?
所以我决定必须发生的事情是这样的:
和变量(即使等于 6)被传递给函数o
。只是当函数最终被调用时,变量被解释器重新定义为(in ) 的参数,因此我试图传递的参数的原始值被替换了。但这意味着在此之前它只是将函数存储为文本,因为否则将只是程序中的数据,而不是可以被覆盖的变量。这个解释正确吗?arguments
arguments
g
arguments
g
g(2)
o
arguments
(问题 2)在同一页的前面,他定义了以下函数,该函数使用该apply
方法跟踪函数以进行调试:
function trace(o, m) {
var original = o[m]; // Remember original method in the closure.
o[m] = function() { // Now define the new method.
console.log(new Date(), "Entering:", m); // Log message.
var result = original.apply(this, arguments); // Invoke original.
console.log(new Date(), "Exiting:", m); // Log message.
return result; // Return result.
};
}
这里不是this
指我们定义的函数,而不是对象o
吗?或者这两件事是一回事吗?