<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[刘新修]]></title> 
<link>http://liuxinxiu.com:80/index.php</link> 
<description><![CDATA[刘新修的个人博客 (Liuxinxiu'S Blog)]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[刘新修]]></copyright>
<item>
<link>http://liuxinxiu.com:80/JS_Closure/</link>
<title><![CDATA[学习Javascript闭包（Closure）及JS闭包的深入剖析【原创】]]></title> 
<author>刘新修 &lt;admin@yourname.com&gt;</author>
<category><![CDATA[H5/JS/CSS]]></category>
<pubDate>Mon, 24 Aug 2015 09:58:12 +0000</pubDate> 
<guid>http://liuxinxiu.com:80/JS_Closure/</guid> 
<description>
<![CDATA[ 
	<p><span style="color: rgb(255, 255, 255);"><span style="background-color: rgb(255, 0, 0);"><strong>A. 学习Javascript闭包（Closure） </strong></span></span></p><p>闭包（closure）是Javascript语言的一个难点，也是它的特色，很多高级应用都要依靠闭包实现。</p><p>下面就是我的学习笔记，对于Javascript初学者应该是很有用的。</p><p>第一、变量的作用域</p><p>要理解闭包，首先必须理解Javascript特殊的变量作用域。</p><p>变量的作用域无非就是两种：全局变量和局部变量。</p><p>Javascript语言的特殊之处，就在于函数内部可以直接读取全局变量。</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">var</span><span> n=999;&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">function</span><span> f1()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>　　alert(n);&nbsp;&nbsp;</span></li><li><span>&#125;&nbsp;&nbsp;</span></li><li class="alt"><span>f1(); <span class="comment">//999</span><span>&nbsp;&nbsp;</span></span></li></ol></div><p><span style="color: rgb(17, 17, 17); font-family: Georgia, serif; font-size: 16px; letter-spacing: -0.119999997317791px; line-height: 28.7999992370605px; word-spacing: 2.40000009536743px; background-color: rgb(245, 245, 213);">另一方面，在函数外部自然无法读取函数内的局部变量。</span></p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> f1()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　<span class="keyword">var</span><span> n=999;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;&nbsp;&nbsp;</span></li><li><span>alert(n); <span class="comment">//error</span><span>&nbsp;&nbsp;</span></span></li></ol></div><p><span style="color: rgb(17, 17, 17); font-family: Georgia, serif; font-size: 16px; letter-spacing: -0.119999997317791px; line-height: 28.7999992370605px; word-spacing: 2.40000009536743px; background-color: rgb(245, 245, 213);">这里有一个地方需要注意，函数内部声明变量的时候，一定要使用var命令。如果不用的话，你实际上声明了一个全局变量！</span></p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> f1()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　n=999;&nbsp;&nbsp;</span></li><li class="alt"><span>&#125;&nbsp;&nbsp;</span></li><li><span>f1();&nbsp;&nbsp;</span></li><li class="alt"><span>alert(n); <span class="comment">//999</span><span>&nbsp;&nbsp;</span></span></li></ol></div><p>第二、如何从外部读取局部变量？</p><p>出于种种原因，我们有时候需要得到函数内的局部变量。但是，前面已经说过了，正常情况下，这是办不到的，只有通过变通方法才能实现。</p><p>&nbsp;</p><p>那就是在函数的内部，再定义一个函数。</p><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> f1()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　<span class="keyword">var</span><span> n=999;&nbsp;&nbsp;</span></span></li><li class="alt"><span>　　<span class="keyword">function</span><span> f2()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　　　alert(n); <span class="comment">// 999</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>　　&#125;&nbsp;&nbsp;</span></li><li><span>&#125;&nbsp;&nbsp;</span></li></ol></div><div><div>在上面的代码中，函数f2就被包括在函数f1内部，这时f1内部的所有局部变量，对f2都是可见的。但是反过来就不行，f2内部的局部变量，对f1就是不可见的。这就是Javascript语言特有的&quot;链式作用域&quot;结构（chain scope），子对象会一级一级地向上寻找所有父对象的变量。所以，父对象的所有变量，对子对象都是可见的，反之则不成立。</div><div>既然f2可以读取f1中的局部变量，那么只要把f2作为返回值，我们不就可以在f1外部读取它的内部变量了吗！</div><div>&nbsp;</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> f1()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　<span class="keyword">var</span><span> n=999;&nbsp;&nbsp;</span></span></li><li class="alt"><span>　　<span class="keyword">function</span><span> f2()&#123;&nbsp;&nbsp;</span></span></li><li><span>　　　　alert(n);&nbsp;&nbsp; </span></li><li class="alt"><span>　　&#125;&nbsp;&nbsp;</span></li><li><span>　　<span class="keyword">return</span><span> f2; </span><span class="comment">//特别注意不要写成 return f2(); !!</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;&nbsp;&nbsp;</span></li><li><span><span class="keyword">var</span><span> result=f1();&nbsp;&nbsp;</span></span></li><li class="alt"><span>result(); <span class="comment">//999</span><span>&nbsp;&nbsp;</span></span></li></ol></div><div><div>三、闭包的概念</div><div>上一节代码中的f2函数，就是闭包。</div><div>各种专业文献上的&quot;闭包&quot;（closure）定义非常抽象，很难看懂。我的理解是，闭包就是能够读取其他函数内部变量的函数。</div><div>由于在Javascript语言中，只有函数内部的子函数才能读取局部变量，因此可以把闭包简单理解成&quot;定义在一个函数内部的函数&quot;。</div><div>所以，在本质上，闭包就是将函数内部和函数外部连接起来的一座桥梁。</div><div>&nbsp;</div><div><div><span style="color: rgb(255, 255, 255);"><span style="background-color: rgb(255, 0, 0);"><strong>B. 关于JS闭包调用、闭包取值的常见例子</strong></span></span></div><div>&nbsp;</div><div>只是一个通俗易懂的总结，希望对大家理解JS闭包有所帮助。</div><div>&nbsp;</div><div>案例一：</div><div>&nbsp;</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">var</span><span> b=20;&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">function</span><span> aa()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//var b=10;&nbsp;&nbsp; //如果子函数取不到就找window</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> </span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b++;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(b);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li><span>&#125;;&nbsp;&nbsp;</span></li><li class="alt"><span>aa()();&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span><span class="keyword">function</span><span> test()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> </span><span class="keyword">function</span><span>()&#123;alert(</span><span class="string">&quot;不作死就不会死！&quot;</span><span>)&#125;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;;&nbsp;&nbsp;</span></li><li><span>test()();&nbsp;&nbsp; </span></li></ol></div><div><div><strong><span style="color: rgb(255, 0, 0);">// test()();&nbsp;&nbsp;第一个括号执行test函数返回子函数，第二个括号执行test返回的函数</span></strong></div><div>&nbsp;</div><div>备注：为什么后边还要加一个括号？以前我直接test()这样调用，但是没有弹出结果，也没有保存，注意一定要之后在加括号，否则不会返回子函数的内容！</div><div>&nbsp;</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> a()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span> i=0;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">function</span><span> b()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(++i);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> b;&nbsp;&nbsp; </span><span class="comment">//返回b函数本身的内容，不能写成 return b() 这样就直接执行了</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&#125;&nbsp;&nbsp;</span></li><li><span>a()();&nbsp;&nbsp; </span></li></ol></div><div><div>这段代码有两个特点：</div><div>1. 函数b嵌套在函数a的内部；</div><div>2. 函数a返回函数b的内容；</div><div>&nbsp;</div><div>当调用执行: var c=a();c(); 实际上就创建了一个闭包，为什么呢？因为函数a外部变量引用了内部函数b，也就是说：</div><div>当函数a的内部函数b被a外部的变量引用时，就创建了一个闭包。</div><div>&nbsp;</div><div>如果你不想用两个括号引用：a()(); 还有2种方法，如下：</div><div>&nbsp;</div><div>1. 定义一个变量接受子函数的返回值，在执行变量所在函数 var c=a();c();</div><div>2. 让子函数自执行调用：</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">function</span><span> aa()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">var</span><span> x=10;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;(<span class="keyword">function</span><span> bb()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x++;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(x);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&#125;)();&nbsp;&nbsp;</span></li><li class="alt"><span>&#125;;&nbsp;&nbsp;</span></li><li><span>console.log(aa());&nbsp;&nbsp;</span></li></ol></div><div><div><strong><span style="color: rgb(255, 255, 255);"><span style="background-color: rgb(255, 0, 0);">B.关于闭包中出现的this 深度剖析</span></span></strong></div><div>&nbsp;</div><div>1. 必须了解下作用域的概念，父级作用域的变量可以被子集作用域直接访问，如果子集作用域中没有找到变量，那么会顺着作用域链逐层上爬，直到找到为止。</div><div>2. 函数闭包和this没有直接的关系，只有对类用new创建实例对象时this才有意义，不用new的话，this就只是等于windows对象</div><div>&nbsp;</div><div class="codeText"><div class="codeHead">JavaScript代码</div><ol start="1" class="dp-c"><li class="alt"><span><span class="keyword">var</span><span> name=</span><span class="string">&quot;The Windows&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">var</span><span> soho=</span><span class="string">&quot;The Soho&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">var</span><span> para=</span><span class="string">&quot;The Para&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li><span><span class="keyword">var</span><span> vars=</span><span class="string">&quot;The Vars&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span><span class="keyword">function</span><span> object()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.name=</span><span class="string">&quot;My Object&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//this.para=&quot;My Para&quot;;&nbsp;&nbsp;//公共变量para先找this.para=&quot;My para&quot; 如果没有定义就找window的The para</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.soho=</span><span class="string">&quot;My Soho&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.getNameFunc=</span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//var soho=&quot;My GetNameSoho&quot;; //先找当前定义的局部变量，如找不到就找上一层，都没有就找window 的变量</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(<span class="string">&quot;soho2:&quot;</span><span>+soho+</span><span class="string">&quot;&nbsp;&nbsp;this.name2:&quot;</span><span>+</span><span class="keyword">this</span><span>.name);&nbsp;&nbsp;</span><span class="comment">//soho2:My Soho&nbsp;&nbsp;this.name2:My Object</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> </span><span class="keyword">function</span><span>()&#123;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">this</span><span>.name=</span><span class="string">&quot;My NO-NameFunc&quot;</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;console.log(<span class="string">&quot;this.name3:&quot;</span><span>+</span><span class="keyword">this</span><span>.name+</span><span class="string">&quot;&nbsp;&nbsp;this.vars3:&quot;</span><span>+</span><span class="keyword">this</span><span>.vars); </span><span class="comment">//this.name3:My NO-NameFunc&nbsp;&nbsp;this.vars3:The Vars</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> </span><span class="keyword">this</span><span>.name;&nbsp;&nbsp;</span><span class="comment">//My NO-NameFunc</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#125;;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&#125;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;console.log(<span class="string">&quot;name1:&quot;</span><span>+name+</span><span class="string">&quot;&nbsp;&nbsp;this.name1:&quot;</span><span>+</span><span class="keyword">this</span><span>.name+</span><span class="string">&quot;&nbsp;&nbsp;para:&quot;</span><span>+para);&nbsp;&nbsp;</span><span class="comment">//name1:My Object&nbsp;&nbsp;this.name1:My Object&nbsp;&nbsp;para:The Para</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">return</span><span> getNameFunc;&nbsp;&nbsp;</span></span></li><li><span>&#125;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp; </span></li><li><span><span class="comment">//alert(object()()());</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>console.log(object()()());&nbsp;&nbsp;</span></li></ol></div><div>&nbsp;</div></div></div></div></div></div></div>
]]>
</description>
</item><item>
<link>http://liuxinxiu.com:80/JS_Closure/#blogcomment</link>
<title><![CDATA[[评论] 学习Javascript闭包（Closure）及JS闭包的深入剖析【原创】]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://liuxinxiu.com:80/JS_Closure/#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>