<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>army8735 &#187; 闭包</title>
	<atom:link href="http://army8735.org/tag/%e9%97%ad%e5%8c%85/feed" rel="self" type="application/rss+xml" />
	<link>http://army8735.org</link>
	<description>我可以A，我也可以-A，我可以同时A和-A。</description>
	<lastBuildDate>Fri, 25 Nov 2011 04:07:52 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>一个js闭包的小例子</title>
		<link>http://army8735.org/2009/07/20/62.html</link>
		<comments>http://army8735.org/2009/07/20/62.html#comments</comments>
		<pubDate>Mon, 20 Jul 2009 09:03:42 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[闭包]]></category>

		<guid isPermaLink="false">http://army.512j.com/blog/?p=62</guid>
		<description><![CDATA[上午看到无忧脚本里一个闭包的小讨论贴，下午就碰到blue来说一个js问题。眼不转头不抬回了句：“代码不全。”结果才发现，是我智商不全。
举个小例子：
&#60;ul&#62;
  &#60;li id="a1"&#62;1&#60;/li&#62;
  &#60;li id="a2"&#62;2&#60;/li&#62;
  &#60;li id="a3"&#62;3&#60;/li&#62;
&#60;/ul&#62;
写个代码：
for(var i = 0; i &#60; 4; i++) {
  var...]]></description>
			<content:encoded><![CDATA[<p>上午看到无忧脚本里一个闭包的小讨论贴，下午就碰到blue来说一个js问题。眼不转头不抬回了句：“代码不全。”结果才发现，是我智商不全。</p>
<p>举个小例子：</p>
<pre class="brush:html">&lt;ul&gt;
  &lt;li id="a1"&gt;1&lt;/li&gt;
  &lt;li id="a2"&gt;2&lt;/li&gt;
  &lt;li id="a3"&gt;3&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>写个代码：</p>
<pre class="brush:js">for(var i = 0; i &lt; 4; i++) {
  var oLi = document.getElementById("a" + i);
  oLi.onclick = function() {
    alert(i);
  }
}</pre>
<p>你会认为每个li元素分配的点击事件是弹出各自的序号吗？如果答案是“是”，那么答案就错了。最终结果会是，所有弹出的均是4，根本不是1、2、3。因为i的变量只保存了一个，每个li弹出的都是i，i最后是4，并非我们所想每个li元素会保存自己的序号。</p>
<p>再来看blue给的代码：</p>
<pre class="brush:js">function User( properties ) {
  //遍历对象属性，确保它作用域正确(如前所述)
  for ( var i in properties ) {
    //为属性创建获取器
    this[ "get" + i ] = function() {
      return  properties[i];
    };
    //为属性创建设置器
    this[ "set" + i ]  = function(val) {
      properties[i] = val;
    };
  }
}
//创建一个新user对象实例，传入一个包含属性的对象作为种子
var user = new User({
  name:  "Bob",
  age: 44
});
//请注意name属性并不存在，因为它在properties对象中，是私有的
alert(  user.name == null );
//然而，我们能够使用用动态生成的方法getname来访问它
alert( user.getname()  == "Bob" );
//最后，我们能看到，通过新生成的动态方法设置和获取age都是可以的
//user.setage( 22  );
alert( user.getname());</pre>
<p>最终会弹出什么？false、true和啥？当然不是Bob，会是44，这个原理和上面那个是一样的。</p>
<p>user.getname()中的那个i，在循环的时候确实是等于&#8221;name&#8221;，于是this["get" +  i]为类本身赋予了一个getname的方法，返回name的属性值，也就是Bob。可是在循环下一个的时候，i变成了age，于是return  properties[i]也变成了return properties["age"]了，这就是原因所在。</p>
<p>既然知道为什么了，那么有希望拯救吗？</p>
<p>当然有！</p>
<p>一种方法是将变量存到别的地方上去，比如开头的那个例子将序号存到元素的name属性上；当然技巧性的就是使用闭包了。</p>
<pre class="brush:js">function User( properties ) {
  for ( var i in  properties ) {
    this[ "get" + i ] = (function(s) {
      return  function() {
        return  properties[s];
      }
    })(i);
    this[ "set" + i ] = function(val)  {
      properties[i] = val;
    };
  }
}
var user = new  User({
  name: "Bob",
  age: 44
});
alert(  user.getname());</pre>
<p>试一试，效果如何？通过匿名函数的方法，将变量存到实参上面，如此就保存了每个变量，防止最后被替换掉。&</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2009/07/20/62.html/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

