ajax-javascript-范围链、call对象与闭包
闭包基础
都知道,局部变量隐藏全局变量,为什么会隐藏?
因为函数对象的[[scope]]内部属性,闭包能实现也因为有这个对象。
Excution Context&Scope&Call Object
当函数被调用时,解释器为其创建一个上下文,当函数返回时,解释器回到最初的上下文。解释器形成一个上下文栈。上下文包含:全局上下文和局部上下文。
创建上下文会伴随一系列对象的创建,包含:
Call Object:此对象包含一个arguments属性指向argumets对象。
argumentsObject:保含的是调用者指定的参数和被调用函数无关。赋值给Call Object的arguments属性。
Scope Object:创建scope对象,并加入scope链,把call Object加入到链头,然后赋值给function object的[[scope]]属性。
Variable Object:在此初始化了三种类型的变量:局部变量被初始化为undefined。如果正式的参数(注意不是arguments中的参数)在arguments中有值,用值初始化,否则也初始化为undefined。初始化内部函数。Variable Object指向Call,他们相同。
上面是局部上下文,全局上下文比较简单,只包含一个globle对象。别的对象不会被创建,因为没有意义。
可以看到只要通过函数对象的[[scope]]内部属性,就能得到函数所需的所有运行信息。
注:
正式参数:这里指实际参数。
上面只是简要说明,只是解释了和闭包有关部分,并不严格,详细的参见ecma-262。
Eval&with
eval创建新的上下文
with会打破现在的上下文
闭包
在Js中函数嵌套被返回时闭包就形成。因为函数有内置的[[scope]]属性,保持了内层函数的引用,也就保持了整条从内部到globle链的引用。整条链资源不能被释放,当然也能访问链上的变量。
解释闭包的例子
var y=30;
function f(y){ //范围f开始
return function g() //范围g开始
{
var z=10;
document.write(x+y+z)
} //范围g结束
} //范围f结束
var f1 = f(5); 输出20 //范围globle结束
在g()被执行时,g()的[[scope]]会指向下面的链:
首先是g的call object:包含变量z。
然后是g的scope对象
再后面是f的call objec:包含y
再后是f的scop
再后是globle object:包含x,y
因此执行时,由于g存活,整条链就可以使用,闭包得以形成。变量定位也从当前call object开始,会隐藏同名的y(参数y隐藏全局y)。
另一种隐藏是prototype chain,虽然都隐藏变量,但他们完全不同,也没有任何关系,详细见,上一篇继承。
MicrosoftAjax.js中的闭包
createCallback& createDelegate
事件不用闭包的实现方式:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
</head>
<body>
<input type="button" id="Submit1" value="Test Closure" />
<script type="text/javascript">
function TestC(buttonId, message)
{
this._message = message;
var btn = document.getElementById(buttonId);
btn.onclick = function(){m.showMessage()}
}
TestC.prototype.showMessage = function()
{
alert(this._message);
}
var m = new TestC('Submit1', 'aaaa');
</script>
</body>
</html>
下面的语句定死了函数:
btn.onclick = function(){m.showMessage()}
但是如果用btn.onclick=this.showMessage;由于this指向button,代码又没有办法工作。
只能借助闭包和Apply:
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Untitled Page</title>
</head>
<body>
<input type="button" id="Submit1" value="Test Closure" />
<script type="text/javascript">
var createDelegate= function Function$createDelegate(instance, method) {
/// <param name="instance" mayBeNull="true"></param>
/// <param name="method" type="Function"></param>
/// <returns type="Function"></returns>
return function() {
return method.apply(instance, arguments);
}
}
function TestC(buttonId, message)
{
this._message = message;
var btn = document.getElementById(buttonId);
btn.onclick=this.showMessage;
}
TestC.prototype.showMessage = function()
{
alert(this._message);
}
var m = new TestC('Submit1', 'aaaa');
</script>
</body>
</html>
更多闭包例子
下面文中有很多闭包例子,可以在页面执行,看到效果,可以直观感受下什么是闭包
http://www.javascriptkit.com/javatutors/closures.shtml
看看最新的JS调试器:
http://weblogs.asp.net/scottgu/archive/2007/07/19/vs-2008-javascript-debugging.aspx
总的介绍
http://www.cnblogs.com/bluewater/archive/2007/07/17/821471.html
namespace
http://www.cnblogs.com/bluewater/archive/2007/07/18/822485.html
继承
http://www.cnblogs.com/bluewater/archive/2007/07/19/823815.html