JS函数返回另一个函数
我想了解一些已经用于返回函数的变量。 这是示例代码JS函数返回另一个函数
Prototype = {}
Prototype.F =
{
bind: function()
{
var args = arguments, __method = args.shift(), object = args.shift();
return function()
{
return __method.apply(object, args.concat(arguments));
}
}
}
function ObjectA()
{
...
this.addListener = Prototype.F.bind(this.eventSource.addListener,
this.eventSource);
...
}
var a = ObjectA();
a.addListener(this); // assuming 'this' here will point to some window object
据我了解在绑定返回()函数不计算直到它被称为在最后一行。可以接受。所以addListener将包含一个包含'apply'的函数体。
但是,我不明白,当addListener被调用时,它会有什么样的参数?特别是_method和args将始终未初始化?
的功能bind
回报是closure在参数给bind
功能,所以__method
参数将是第一个参数bind
(在你的榜样通话,这将是this.eventSource.addListener
功能)。
闭包基本上是具有内在绑定数据的函数。这里有一个简单的例子:
function makeAlert(msg) {
return function() {
alert(msg);
}
}
var myalert = makeAlert("Hi there!");
myalert(); // Alerts "Hi there!"
通过makeAlert
返回的功能“关闭了”(保留访问)范围的事情,创造了它,包括msg
参数的makeAlert
函数调用中。这就是为什么当我们稍后调用该函数时,即使对makeAlert
的调用早已完成,它仍然有msg
。 More about closures here.
要记住关闭一个关键的事情是,他们保留一切这是在哪里范围内他们定义,不只是他们他们显然是在利用的东西访问。因此,例如:
function init() {
var data;
data = /* ...build some really big array of data...*/;
document.getElementById('foo').onclick = function() {
this.style.display = "none";
};
}
即使该事件处理程序无关的大数据阵列,它保持对它的引用,因此保持在调用init
后,内存中的数据已经完成。这是因为它所具有的链接是一个幕后对象(松散地称为“变量对象”),它是所有参数和局部变量的容器,它们在其定义的范围内。 (在这种情况下,如果你不需要所有的数据,只需在末尾设置data
到undefined
。事件处理程序仍然会引用data
,但该引用不再保存数组,所以数组的内存可以被回收。)
所以换句话说,如果js引擎会检测将来可能使用的任何函数,它将保存后续使用的范围,所以无论何时何时调用它,该函数都可以有一定的工作范围,并且已经决定了由js设计师,范围是功能已被创建。只是想知道这个范围是不可改变的?例如,我可以在内部函数中取消定义'data'?而且,通过访问范围从其他地方取消定义'data'? – Pablo 2010-04-28 15:46:06
@Michael:像Javascript中的所有对象一样,变量对象将被垃圾回收,如果没有引用它的话;该函数是一个引用变量对象的对象,它保持变量对象不被GC化。只要某些东西具有对该函数的引用,就会使该函数不被GC调用,从而使该变量对象不被GC化。你明白了。 :-)变量对象中的(属性名称)内容由代码确定;那些指向的东西可以像其他任何东西一样改变,通过给它们赋值。所以(继续) – 2010-04-28 18:45:57
@Michael :(继续)所以如果你想要数据指向的数组,但只有一次,你可以在第一次使用内部函数时给它赋值undefined。或者,更有用的是,如果(例如)在外部函数中有'count'成员,则可以在内部函数中增加它。像这样的东西。 (查看我博客上的链接文章以获取更多信息。) – 2010-04-28 18:47:18
_method和args将总是被初始化,因为你定义它们,当你第一次调用
this.addListener = Prototype.F.bind(this.eventSource.addListener, this.eventSource);
在那里,你会得到_method将是this.eventSource.addListener
,和args会成为那两个论点。
在功能范围内,arguments
是一个类似数组的对象,它包含调用函数时提供的值,而不管函数定义是否定义了参数。
所以本次通话:
Prototype.F.bind(this.eventSource.addListener, this.eventSource);
导致此:
var args = arguments, __method = args.shift(), object = args.shift();
arguments
包含2项:任何this.eventSource.addListener
和this.eventSource
点,当函数被调用。将2个项目的集合复制到参数中,然后将项目从集体移动到__method
和object
。
由于调用bind
实际上会生成另一个函数,因此新函数中的arguments
实例将会不同 - 它将具有在该调用时提供的参数。来自呼叫的原始arguments
到bind
保存在args
中,并与来自后面的函数调用的arguments
组合。
'F'是一个函数,它在一个名为'bind'的属性(写成对象字面值)上,它是一个返回函数的函数。 – RoToRa 2010-04-28 13:46:34
对不起,错字,我会更新。当然,我会结合。 – Pablo 2010-04-28 13:51:21