﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-奇葛格的BLOG-随笔分类-JavaScript</title><link>http://www.blogjava.net/onlykeke/category/14421.html</link><description>红尘最可笑，我自乐逍遥</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:37:36 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:37:36 GMT</pubDate><ttl>60</ttl><item><title>javascript语言中的闭包[转]</title><link>http://www.blogjava.net/onlykeke/archive/2006/05/21/47330.html</link><dc:creator>奇葛格</dc:creator><author>奇葛格</author><pubDate>Sun, 21 May 2006 13:22:00 GMT</pubDate><guid>http://www.blogjava.net/onlykeke/archive/2006/05/21/47330.html</guid><wfw:comment>http://www.blogjava.net/onlykeke/comments/47330.html</wfw:comment><comments>http://www.blogjava.net/onlykeke/archive/2006/05/21/47330.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/onlykeke/comments/commentRss/47330.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/onlykeke/services/trackbacks/47330.html</trackback:ping><description><![CDATA[
		<h1 class="block_title">
				<a id="viewpost1_TitleUrl" href="/zkjbeyond/archive/2006/05/19/47025.html">javascript语言中的闭包</a>
		</h1>
		<div class="post">
				<div class="postcontent">
						<p>
								<strong>写在前面的话：<br /></strong>试图翻译自 <a href="http://jibbering.com/faq/faq_notes/closures.html">http://jibbering.com/faq/faq_notes/closures.html</a><br />文中大量提到《ECMA 262 》，我也没时间读这东西，可能有问题理解有误。希望纠正。<br />只译了前边部分，我得理解几天再继续下去。<br />英文水平差，凑合看吧。<br />国内找了半天没这篇文章中文版，献丑了就。<br />读后有种豁然开朗的感觉，清楚了很多javascript的问题。<br /></p>
						<p>
								<strong>一、Introduction</strong>
								<br />Closure (闭包)<br />A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression). </p>
						<p>    闭包是ECMAScript(javascript)语言强大的特征之一，如果没有真正的理解它的概念，不可能很好使用它。在一般浏览器环境中，它们很容易被建立，但也会造成比较难理解的代码逻辑。为了避免闭包引起的缺点，利用它所提供的优点，明白它的机制是重要的。javascript语言的闭包很大程度上依靠 scope chains(函数，变量的范围链) 和 javascript对象的灵活的属性机制 实现。<br />    闭包简单的解释是，ECMAScript允许inner functions(嵌套函数)：函数可以定义在另外一个函数里面（关于嵌套函数可以看看&lt;javascript权威指南&gt;）。这些内部的函数可以访问outer function（父函数）的local变量，参数，其它内部函数。当内部函数被构造，并可以在函数外被获得（函数当成返回值），这个内部函数被在 outer function返回后被执行（在outer函数外执行），那一个闭包形成了。（简单的理解，function被当成数据类型传递或动态执行）。 inner function还有权利访问 那些outer function（父函数）的local变量，参数，其它内部函数。那些outer function（父函数）的local变量，参数，其它内部函数在outer function返回前就有值，并返回的inner function需要改变这些值。<br /><br />我估计以下代码就是一个闭包。</p>
						<p> </p>
						<div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)">
								<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
								<span style="COLOR: rgb(0,0,0)">&lt;</span>
								<span style="COLOR: rgb(0,0,0)">script</span>
								<span style="COLOR: rgb(0,0,0)">&gt;</span>
								<span style="COLOR: rgb(0,0,0)">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />var g_count</span>
								<span style="COLOR: rgb(0,0,0)">=</span>
								<span style="COLOR: rgb(0,0,0)">0</span>
								<span style="COLOR: rgb(0,0,0)">;<br /><img id="Codehighlighter1_39_386_Open_Image" onclick="this.style.display='none'; Codehighlighter1_39_386_Open_Text.style.display='none'; Codehighlighter1_39_386_Closed_Image.style.display='inline'; Codehighlighter1_39_386_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_39_386_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_39_386_Closed_Text.style.display='none'; Codehighlighter1_39_386_Open_Image.style.display='inline'; Codehighlighter1_39_386_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" />function aaa(p)</span>
								<span id="Codehighlighter1_39_386_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_39_386_Open_Text">
										<span style="COLOR: rgb(0,0,0)">{</span>
										<span style="COLOR: rgb(0,128,0)">//</span>
										<span style="COLOR: rgb(0,128,0)">outer function</span>
										<span style="COLOR: rgb(0,128,0)">
												<br />
												<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />  </span>
										<span style="COLOR: rgb(0,0,0)">var outer_count</span>
										<span style="COLOR: rgb(0,0,0)">=</span>
										<span style="COLOR: rgb(0,0,0)">0</span>
										<span style="COLOR: rgb(0,0,0)">;<br /><img id="Codehighlighter1_110_187_Open_Image" onclick="this.style.display='none'; Codehighlighter1_110_187_Open_Text.style.display='none'; Codehighlighter1_110_187_Closed_Image.style.display='inline'; Codehighlighter1_110_187_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_110_187_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_110_187_Closed_Text.style.display='none'; Codehighlighter1_110_187_Open_Image.style.display='inline'; Codehighlighter1_110_187_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />  function innerfun(name,count)</span>
										<span id="Codehighlighter1_110_187_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">
												<img src="http://www.blogjava.net/images/dot.gif" />
										</span>
										<span id="Codehighlighter1_110_187_Open_Text">
												<span style="COLOR: rgb(0,0,0)">{</span>
												<span style="COLOR: rgb(0,128,0)">//</span>
												<span style="COLOR: rgb(0,128,0)">outer function中定义的另外一个inner function</span>
												<span style="COLOR: rgb(0,128,0)">
														<br />
														<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
												</span>
												<span style="COLOR: rgb(0,0,0)">    </span>
												<span style="COLOR: rgb(0,0,255)">return</span>
												<span style="COLOR: rgb(0,0,0)"> name</span>
												<span style="COLOR: rgb(0,0,0)">+</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">:</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">+</span>
												<span style="COLOR: rgb(0,0,0)">count</span>
												<span style="COLOR: rgb(0,0,0)">+</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">次;</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />  }</span>
										</span>
										<span style="COLOR: rgb(0,0,0)">
												<br />
												<img id="Codehighlighter1_210_383_Open_Image" onclick="this.style.display='none'; Codehighlighter1_210_383_Open_Text.style.display='none'; Codehighlighter1_210_383_Closed_Image.style.display='inline'; Codehighlighter1_210_383_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
												<img id="Codehighlighter1_210_383_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_210_383_Closed_Text.style.display='none'; Codehighlighter1_210_383_Open_Image.style.display='inline'; Codehighlighter1_210_383_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />  </span>
										<span style="COLOR: rgb(0,0,255)">return</span>
										<span style="COLOR: rgb(0,0,0)"> function()</span>
										<span id="Codehighlighter1_210_383_Closed_Text" style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)">
												<img src="http://www.blogjava.net/images/dot.gif" />
										</span>
										<span id="Codehighlighter1_210_383_Open_Text">
												<span style="COLOR: rgb(0,0,0)">{</span>
												<span style="COLOR: rgb(0,128,0)">//</span>
												<span style="COLOR: rgb(0,128,0)">返回一个匿名的inner函数</span>
												<span style="COLOR: rgb(0,128,0)">
														<br />
														<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
												</span>
												<span style="COLOR: rgb(0,0,0)">     var inner_count</span>
												<span style="COLOR: rgb(0,0,0)">=</span>
												<span style="COLOR: rgb(0,0,0)">0</span>
												<span style="COLOR: rgb(0,0,0)">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            </span>
												<span style="COLOR: rgb(0,0,255)">return</span>
												<span style="COLOR: rgb(0,0,0)"> innerfun(</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">g_count</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">,(</span>
												<span style="COLOR: rgb(0,0,0)">++</span>
												<span style="COLOR: rgb(0,0,0)">g_count))</span>
												<span style="COLOR: rgb(0,0,0)">+</span>
												<span style="COLOR: rgb(0,0,0)">innerfun(</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">outer_count</span>
												<span style="COLOR: rgb(0,0,0)">'</span>
												<span style="COLOR: rgb(0,0,0)">,(</span>
												<span style="COLOR: rgb(0,0,0)">++</span>    <span style="COLOR: rgb(0,0,0)">outer_count))</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">innerfun(</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">inner_count</span><span style="COLOR: rgb(0,0,0)">'</span><span style="COLOR: rgb(0,0,0)">,(</span><span style="COLOR: rgb(0,0,0)">++</span><span style="COLOR: rgb(0,0,0)">inner_count))</span><span style="COLOR: rgb(0,0,0)">+</span><span style="COLOR: rgb(0,0,0)">p;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />  }</span></span>
										<span style="COLOR: rgb(0,0,0)">
												<br />
												<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
										<br />
										<br />
								</span>  <span style="COLOR: rgb(0,0,0)">var fun1</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">aaa(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">fun1</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">);<br /> var fun2</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">aaa(</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">fun2</span><span style="COLOR: rgb(0,0,0)">"</span><span style="COLOR: rgb(0,0,0)">);<br /> alert(fun1)<br /> alert(fun1());</span><span style="COLOR: rgb(0,128,0)">//</span><span style="COLOR: rgb(0,128,0)">这时候才真正执行</span><span style="COLOR: rgb(0,128,0)"><br />  </span><span style="COLOR: rgb(0,0,0)">alert(fun2());<br /></span><span style="COLOR: rgb(0,0,0)">&lt;/</span><span style="COLOR: rgb(0,0,0)">script</span><span style="COLOR: rgb(0,0,0)">&gt;</span></div>
						<p>    不幸的，完全明白闭包需要知道它背后的机制和一些技术细节。<br /><strong>二、The Resolution of Property Names on Objects (javascript对象的属性)<br /></strong>    ECMAScript认可两类对象，“Native Object”和“Host Object”,Host Object属于Native Object的子类，在(ECMA 262 3rd Ed Section 4.3)中叫"Built-in Object"（内置对象）。Native objects属于语言级别，host objects被环境提供（浏览器等），例如，document objects,DOM nodes等。<br />    关于对象属性的存取，数据类型，原型对象prototype的使用，我这就不译了。<br />    可以参见<a href="/zkjbeyond/archive/2006/04/17/41531.html">我的另一篇文章</a><br /></p>
						<p>
								<strong>三、Identifier Resolution, Execution Contexts and Scope Chains</strong>
								<br />
								<strong>1、The Execution Context</strong>
								<br />    执行环境上下文（Execution Context）是个抽象的概念，the ECMSScript specification (ECMA 262 3rd edition) to define the behaviour required of ECMAScript implementations。规范没有说 execution contexts 应该怎样实现，但规范中提到execution contexts是个关联属性结构，因此你可以假想为一个有属性的对象，但不是公有的（public）。<br />    所有的javascript代码在一个execution context中执行。Global代码(.js文件中)在我叫做globla execution context中执行，每个函数的调用有个专属的execution context。注意，用eval函数执行的代码有个独特的execution context.(原文中说eval函数没常被程序员应用，确实如果掌握闭包使用后，还是可以避免一些eval使用的)。在section 10.2 of ECMA 262 (3rd edition)中详细讲述的execution context.<br />    当一个函数被调用，那相应的execution context被建立，如果另外的函数（或同一个函数递归调用），那新的execution context被建立，直到函数return(对于递归调用，execution context是独立的)。因此，javascript代码的执行会建立很多的execution contexts.<br />    当一个函数的execution context被建立(javascript中有global和function两种，eval没讨论)，按照顺序，有几个事情要发生。<br />   <b>（1）</b>在一个函数的execution context中，一个"Activation"对象被建立（我在<a href="/zkjbeyond/archive/2006/04/06/39514.html">其它文章</a>中叫调用对象）。the activation被另外规范解释。你可以把它当成一个对象，因为它有对象的属性，但它不是一般对象，它没有原型对象，并不能被javascript代码直接引用。<br />   <b>（2）</b>建立一个arguments对象，它和数组类似，以整数为索引来访问值，表示函数的参数。它有length和callee属性。这个arguments对象被当成activation对象的属性。在函数内可以直接访问得到。<br />   <b>（3）</b>下一步，execution context被分配一个 scope属性（scope chain后面讲到，我们可以把scope理解成对象的一个scope属性，值是scope chain）。一个scope由一列对象组成（或叫chain）。每个函数对象也有由chain组成的scope属性。函数的scope＝Activation object+上级对象的scope的属性.（这里的scope可以理解成servlet中的chain,一系列请求组成的链。）<br />   <b>（4）</b>Activation object的实例化。Activation object(<a href="/zkjbeyond/archive/2006/04/06/39514.html">调用对象</a>)可以看作Variable(变量)。<br />function fun(a,b){};fun('p'); a和b会当成调用对象的属性，但函数调用是参数不够，b的值为undefined。如果函数内有inner function，当成属性赋值给调用对象。变量实例化最后把local variables（函数内部声名的变量） 当成调用对象的参数。调用对象的属性 包括函数的参数、内部变量。<br />   <b>（5）</b>在函数内，local variables作为调用对象的属性出现，function (a){alert(s);   var s='a';}调用时，s的值是unidefine,直到执行到赋值语句后才有值。<br />   <b>（6）</b>arguments属性是以索引标识的参数，它和显示声明的参数是重复的，值也相同。如果local变量的签名和参数相同，那么它们三者一个变化，其它都会相应改变值。见下例<br />function a(p){alert( arguments [0]);alert(p);var p=1;alert(p);alert( arguments [0]);};a(0);<br />   <b>（7）</b>最后，为this关键字设置值。可能 new Function()的有些疑问。关于this关键字，<font color="#ff0000">感觉自己还没有彻底理解。</font><b class="bold">this关键字关联于执行时的作用域，而非定义时的作用域。(The this keyword is relative to the execution context, not the declaration context )</b></p>
						<p>    global execution context 的过程和上面有些不同，它没有arguments也不需要定义Activation object。global execution context也不需要scope chain,因为scope chain只有一个，就是global object.它的变量实例化过程和inner function其实都是根变量和函数,就是global对象的属性。global execution context用this应用global对象，在浏览器中为window.</p>
						<p>
								<strong>2、Scope chains and [[scope]]</strong>
								<br />    The scope chain of the execution context for a function call is constructed by adding the execution context's Activation/Variable object to the front of the scope chain held in the function object's [[scope]] property。我理解每个函数执行环境都有scope chain，子函数(inner function)的scope chain包括它的父函数的scope chain，如此递归对global对象。<br />    在ECMAScript中，函数是个对象，它们可以用function声明，或function表达式声明，或Function构造函数初始化。<br />    用Function构造的函数对象一直有个scope属性,指向的scope chain 仅包括 global 对象。<br />    用function表达式定义的函数对象，这类函数对象的scope chain被分配到内部的scope 属性。</p>
						<p>
								<b>（1）</b>简单的global函数，例如:-<br />function exampleFunction(formalParameter){<br />    ...   // function body code<br />}</p>
						<p>在global execution context的变量实例化阶段，the corresponding function object 被创建。global execution context有scope chain，只包含global object.因此，函数对象被分配一个指向global object的 scope属性（ internal [[scope]] property）。</p>
						<p>
								<b>（2）</b>A similar scope chain is assigned when a function expression is executed in the global context:-</p>
						<p>var exampleFuncRef = function(){<br />    ...   // function body code<br />}</p>
						<p>这个例子scope chain情形与上类似。有个区别是函数对象在代码执行过程才创建。（见<a href="/zkjbeyond/archive/2006/03/30/38191.html">我以前文章</a>）<br /><b>（3）</b>inner 函数的情形较为复杂，看下面代码：</p>
						<p>function exampleOuterFunction(formalParameter){<br />    function exampleInnerFuncitonDec(){<br />        ... // inner function body<br />    }<br />    ...  // the rest of the outer function body.<br />}<br />exampleOuterFunction( 5 );</p>
						<p>    outer函数在global execution context变量实例化阶段被创建，因此它的scope chain只包括global object.<br />   当global代码执行到调用exampleOuterFunction时，一个新的execution context被创建，(Activation)调用对象也被创建。这个新的execution context的scope chain由两部分组成，新的调用对象在顶层，outer函数scope chain（只包括global object）在后。新的execution context的变量实例化阶段（outer 函数体内）导致inner函数对象被创建，这个inner函数对象的[[scope]] property 被指向上述的哪个scope chain,也就是调用对象和global object.注意inner function也有调用对象。<br /></p>
						<p>引用了 http://wj.cnblogs.com/archive/2006/04/22/381851.html 回复内的代码<br /></p>
						<p>&lt;SCRIPT LANGUAGE="JavaScript"&gt;<br />&lt;!--<br />//global 代码实例化阶段，它知道global object.<br />function createAClosure() <br />{ <br />//当调用时，调用对象创建，execution context的scope chain 包括调用对象和global <br />//object.<br />var local = 0; <br />return function(){return ++local;}; //这个inner function 的scope //chain持有<br />//createAClosure的调用对象，所以也持有local的值<br />} <br />var c1 = createAClosure(); //调用对象和global object<br />var c2 = createAClosure(); //另外一个调用对象和global object<br />document.write(c1() + "&lt;br/&gt;"); <br />document.write(c1() + "&lt;br/&gt;"); <br />document.write(c1() + "&lt;br/&gt;"); <br />document.write(c2() + "&lt;br/&gt;"); <br />document.write(c2() + "&lt;br/&gt;"); <br />//--&gt;<br />&lt;/SCRIPT&gt;</p>
						<p>以上所有过程自动进行，代码不需要任何设置（造成很多人不知道闭包原因）。<br />scope chain 简单看来可以按照下面的代码来描述：</p>
						<p>函数体外Execution context 的scope chain  只有 global.<br />function fun(){<br /> 函数体内Execution context 的scope chain  fun的调用对象+global<br />    function innerfun(){<br />      inner函数体内Execution context 的scope chain innerfun的调用对象 + fun的调用对象 + global<br />    }</p>
						<p>}</p>
						<p>但是ECMAScript提供的with表达式会修改scope chain.with表达式，我是能不用就不用了，&lt;javascript权威指南&gt;中也说with会造成性能的集聚下降。原文贴在下面。有时间再仔细研究。</p>
						<p>The with statement evaluates an expression and if that expression is an object it is added to the scope chain of the current execution context (in front of the Activation/Variable object). The with statement then executes another statement (that may itself be a block statement) and then restores the execution context's scope chain to what it was before. </p>
						<p>A function declaration could not be affected by a with statement as they result in the creation of function objects during variable instantiation, but a function expression can be evaluated inside a with statement:- </p>
						<p>/* create a global variable - y - that refers to an object:- */<br />var y = {x:5}; // object literal with an - x - property<br />function exampleFuncWith(){<br />    var z;<br />    /* Add the object referred to by the global variable - y - to the<br />       front of he scope chain:-<br />    */<br />    with(y){<br />        /* evaluate a function expression to create a function object<br />           and assign a reference to that function object to the local<br />           variable - z - :-<br />        */<br />        z = function(){<br />            ... // inner function expression body;<br />        }<br />    }<br />    ... <br />}</p>
						<p>/* execute the - exampleFuncWith - function:- */<br />exampleFuncWith();<br />When the exampleFuncWith function is called the resulting execution context has a scope chain consisting of its Activation object followed by the global object. The execution of the with statement adds the object referred to by the global variable y to the front of that scope chain during the evaluation of the function expression. The function object created by the evaluation of the function expression is assigned a [[scope]] property that corresponds with the scope of the execution context in which it is created. A scope chain consisting of object y followed by the Activation object from the execution context of the outer function call, followed by the global object. </p>
						<p>When the block statement associated with the with statement terminates the scope of the execution context is restored (the y object is removed), but the function object has been created at that point and its [[scope]] property assigned a reference to a scope chain with the y object at its head. </p>
						<p>
								<strong>3、Identifier Resolution</strong>
								<br />   关于这部分我决定不按照原文直译。Identifier Resolution是一个过程，而不是具体的概念，我举个例子可能就明白了。</p>
						<p>&lt;SCRIPT LANGUAGE="JavaScript"&gt;<br />&lt;!--<br />var s_global='global';//scope chain {global} 中 <br />var s_outer='global';//scope chain {global} 中 <br />var s_inner='global';//scope chain {global} 中 <br />function outerfun(){//scope chain {global} 中 <br />    var s_outer='outer';//scope chain  {outerfun调用对象，global}<br /> pf('outer代码开始');<br /> pf(s_global);//global <br />    pf(s_outer);//outerfun调用对象<br />    pf(s_inner);//global </p>
						<p> function innerfun(){////scope chain  {outerfun调用对象，global}<br />    var s_inner='inner';//scope chain  {innerfun调用对象，outerfun调用对象，global}<br /> pf('inner代码开始');<br /> pf(s_global);//global <br />    pf(s_outer);//outerfun调用对象<br />    pf(s_inner);//innerfun调用对象<br /> }<br /> return innerfun;<br />}<br />function pf(msg){document.writeln('&lt;/br&gt;'+msg);};<br />pf('global代码开始');<br />pf(s_global);//global <br />pf(s_outer);//global <br />pf(s_inner);//global </p>
						<p>var a=outerfun();<br />a();<br />pf('第二个函数开始------------------------');<br />var b=outerfun();<br />b();<br />//--&gt;<br />&lt;/SCRIPT&gt;</p>
						<p>其实Identifier Resolution就是属性查找的过程。 先从scope chain 的第一个对象开始找，如果找不到再从scope chain的第二个对象找， global对象始终是scope chain 的最后一个对象，如果global object中也找不到属性，那为undefined.<br />有两个注意点：<br />   如果可能，这个查找过程会对对象的prototype（原型对象）查找。先找实例属性，再找原型属性。见<a href="/zkjbeyond/archive/2006/04/17/41531.html">我的其它文章</a>。<br />   在函数内，这个函数的调用对象包括的参数，local变量，inner函数等。<br /><br />如果有对javascript语言感兴趣的，欢迎交流批评。<br /><a href="/zkjbeyond/category/10156.html">http://www.blogjava.net/zkjbeyond/category/10156.html</a><br /></p>
						<p>参考：<br />    《javascript权威指南》<br />     <a href="http://jibbering.com/faq/faq_notes/closures.html">http://jibbering.com/faq/faq_notes/closures.html</a></p>
				</div>
				<div class="itemdesc">发表于 2006-05-19 11:46 <a href="/zkjbeyond/">原创专栏 开源</a></div>
		</div>
<img src ="http://www.blogjava.net/onlykeke/aggbug/47330.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/onlykeke/" target="_blank">奇葛格</a> 2006-05-21 21:22 <a href="http://www.blogjava.net/onlykeke/archive/2006/05/21/47330.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>