﻿<?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-BaSaRa 目前关心的是UI技术-随笔分类-Javascript</title><link>http://www.blogjava.net/BaSaRa/category/11655.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 15:01:20 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 15:01:20 GMT</pubDate><ttl>60</ttl><item><title>好久没更新了，今天查了一下在Firefox下解决Event传递的方法，不错</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/28/55538.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 28 Jun 2006 06:35:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/28/55538.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/55538.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/28/55538.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/55538.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/55538.html</trackback:ping><description><![CDATA[
		<font color="#000000">地址：<a href="http://blog.joycode.com/lostinet/archive/2005/02/27/44999.aspx">http://blog.joycode.com/lostinet/archive/2005/02/27/44999.aspx</a><br /><br />我佛山人的不错：<br />用了try...catch因为在IE下会报错但对页面没有影响<br /><br />try { // 让firefox下的event调用像IE下的一样<br /> window.constructor.prototype.__defineGetter__("event", function(){ <br /> var o = arguments.callee.caller; <br /> var e; <br /> while(o != null){<br />  e = o.arguments[0]; <br />  if(e &amp;&amp; (e.constructor == Event || e.constructor == MouseEvent)) return e; <br />  o = o.caller; <br /> } <br /> return null; <br />}); <br />}catch(e) {}<br /><br />用了这段函数则可以直接写 event(window.event) 来操作event(Event)对象了，很方便<br /><br />如果要操作document的事件，好象这个函数无效吧，所以我这样写<br /> window.document.onkeyup = function(e) {<br />  var ev = e||window.event;<br />  if (ev.keyCode==27 &amp;&amp; dojo.style.getStyle(dojo.widget.byId('detailDiv').domNode, "display")!="none")<br />   dojo.widget.byId('detailDiv').domNode.style.display = "none";<br /> };</font>
<img src ="http://www.blogjava.net/BaSaRa/aggbug/55538.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-28 14:35 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/28/55538.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]如何优化JavaScript脚本的性能 </title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52904.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 15 Jun 2006 01:13:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52904.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/52904.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52904.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/52904.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/52904.html</trackback:ping><description><![CDATA[<div class="postText">
<div class="storycontent">
<p>作者：ShiningRay @ <a href="http://www.nirvanastudio.org/"><font color="#667755">Nirvana Studio</font></a></p>
<p>随着网络的发展，网速和机器速度的提高，越来越多的网站用到了丰富客户端技术。而现在Ajax则是最为流行的一种方式。JavaScript是一种解释型语言，所以能无法达到和C/Java之类的水平，限制了它能在客户端所做的事情，为了能改进他的性能，我想基于我以前给JavaScript做过的很多测试来谈谈自己的经验，希望能帮助大家改进自己的JavaScript脚本性能。</p>
<h1>语言层次方面</h1>
<h2>循环</h2>
<p>循环是很常用的一个控制结构，大部分东西要依靠它来完成，在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。for(;;)和while循环的性能应该说基本（平时使用时）等价。</p>
<p>而事实上，如何使用这两个循环，则有很大讲究。我在测试中有些很有意思的情况，见附录。最后得出的结论是：</p>
<ul>
    <li>
    <p>如果是循环变量递增或递减，不要单独对循环变量赋值，应该在它最后一次读取的时候使用嵌套的++或&mdash;操作符。</p>
    </li>
    <li>
    <p>如果要与数组的长度作比较，应该事先把数组的length属性放入一个局部变量中，减少查询次数。</p>
    </li>
</ul>
<h2>局部变量和全局变量</h2>
<p>局部变量的速度要比全局变量的访问速度更快，因为全局变量其实是全局对象的成员，而局部变量是放在函数的栈当中的。</p>
<h2>不使用Eval</h2>
<p>使用eval相当于在运行时再次调用解释引擎对内容进行运行，需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版（关于闭包的内容请参考函数式编程的有关内容）</p>
<h2>减少对象查找</h2>
<p>因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。</p>
<p>这一点可以和循环结合起来，因为我们常常要根据字符串、数组的长度进行循环，而通常这个长度是不变的，比如每次查询a.length，就要额外进行一个操作，而预先把var len=a.length，则就少了一次查询。</p>
<h2>字符串连接</h2>
<p>如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。</p>
<p>如果要连接多个字符串，应该少使用+=，如</p>
<pre>s+=a;<br />s+=b;<br />s+=c;</pre>
<p>应该写成</p>
<pre>s+=a + b + c；</pre>
<p>而如果是收集字符串，比如多次对同一个字符串进行+=操作的话，最好使用一个缓存。怎么用呢？使用JavaScript数组来收集，最后使用join方法连接起来，如下</p>
<pre>var buf = new Array();<br />for(var i = 0; i &lt; 100; i++){<br />	buf.push(i.toString());<br />}<br />var all = buf.join(&quot;&quot;);</pre>
<h2>类型转换</h2>
<p>类型转换是大家常犯的错误，因为JavaScript是动态类型语言，你不能指定变量的类型。</p>
<p>1. 把数字转换成字符串，应用&quot;&quot; + 1，虽然看起来比较丑一点，但事实上这个效率是最高的，性能上来说：</p>
<p>(&quot;&quot; +) &gt; String() &gt; .toString() &gt; new String() </p>
<p>这条其实和下面的&ldquo;直接量&rdquo;有点类似，尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。</p>
<p>String()属于内部函数，所以速度很快，而.toString()要查询原型中的函数，所以速度逊色一些，new String()用于返回一个精确的副本。</p>
<p>2. 浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。</p>
<p>另外，和第二节的对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。</p>
<p>3. 对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()，因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高</p>
<h2>使用直接量</h2>
<p>其实这个影响倒比较小，可以忽略。什么叫使用直接量，比如，JavaScript支持使用[param,param,param,...]来直接表达一个数组，以往我们都使用new Array(param,param,...)，使用前者是引擎直接解释的，后者要调用一个Array内部构造器，所以要略微快一点点。</p>
<p>同样，var foo = {}的方式也比var foo = new Object();快，var reg = /../;要比var reg=new RegExp()快。</p>
<h2>字符串遍历操作</h2>
<p>对字符串进行循环操作，譬如替换、查找，应使用正则表达式，因为本身JavaScript的循环速度就比较慢，而正则表达式的操作是用C写成的语言的API，性能很好。</p>
<h2>高级对象</h2>
<p>自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。</p>
<h1>DOM相关</h1>
<h2>插入HTML</h2>
<p>很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低，如果需要直接插入HTML，可以找一个容器元素，比如指定一个div或者span，并设置他们的innerHTML来将自己的HTML代码插入到页面中。</p>
<h2>对象查询</h2>
<p>使用[&ldquo;&rdquo;]查询要比.items()更快，这和前面的减少对象查找的思路是一样的，调用.items()增加了一次查询和函数的调用。</p>
<h2>创建DOM节点</h2>
<p>通常我们可能会使用字符串直接写HTML来创建节点，其实这样做</p>
<ol>
    <li>
    <p>无法保证代码的有效性</p>
    </li>
    <li>
    <p>字符串操作效率低</p>
    </li>
</ol>
<p>所以应该是用document.createElement()方法，而如果文档中存在现成的样板节点，应该是用cloneNode()方法，因为使用createElement()方法之后，你需要设置多次元素的属性，使用cloneNode()则可以减少属性的设置次数&mdash;&mdash;同样如果需要创建很多元素，应该先准备一个样板节点。</p>
<h2>定时器</h2>
<p>如果针对的是不断运行的代码，不应该使用setTimeout，而应该是用setInterval。setTimeout每次要重新设置一个定时器。</p>
<h1>其他</h1>
<h2>脚本引擎</h2>
<p>据我测试Microsoft的JScript的效率较Mozilla的Spidermonkey要差很多，无论是执行速度还是内存管理上，因为JScript现在基本也不更新了。但SpiderMonkey不能使用ActiveXObject</p>
<h2>文件优化</h2>
<p>文件优化也是一个很有效的手段，删除所有的空格和注释，把代码放入一行内，可以加快下载的速度，注意，是下载的速度而不是解析的速度，如果是本地，注释和空格并不会影响解释和执行速度。</p>
<h1>总结</h1>
<p>本文总结了我在JavaScript编程中所找到的提高JavaScript运行性能的一些方法，其实这些经验都基于几条原则：</p>
<ol>
    <li>
    <p>直接拿手头现成的东西比较快，如局部变量比全局变量快，直接量比运行时构造对象快等等。</p>
    </li>
    <li>
    <p>尽可能少地减少执行次数，比如先缓存需要多次查询的。</p>
    </li>
    <li>
    <p>尽可能使用语言内置的功能，比如串链接。</p>
    </li>
    <li>
    <p>尽可能使用系统提供的API，因为这些API是编译好的二进制代码，执行效率很高</p>
    </li>
</ol>
<p>同时，一些基本的算法上的优化，同样可以用在JavaScript中，比如运算结构的调整，这里就不再赘述了。但是由于JavaScript是解释型的，一般不会在运行时对字节码进行优化，所以这些优化仍然是很重要的。</p>
<p>当然，其实这里的一些技巧同样使用在其他的一些解释型语言中，大家也可以进行参考。</p>
<h1>参考</h1>
<ul>
    <li>
    <p><a href="http://www.umsu.de/jsperf/"><font color="#667755">http://www.umsu.de/jsperf/</font></a> 各种浏览器的测试对比</p>
    </li>
    <li>
    <p><a href="http://home.earthlink.net/~kendrasg/info/js_opt/"><font color="#667755">http://home.earthlink.net/~kendrasg/info/js_opt/</font></a> </p>
    </li>
</ul>
<h1>附录1</h1>
<p>由于是以前做过的测试，测试代码已经不全，我补充了一部分如下：</p>
<pre>var print;
if(typeof document != &quot;undefined&quot; ){
print = function(){
document.write(arguments[0]);
}
}else if(typeof WScript != &quot;undefined&quot; ){
print = function(){
WScript.Echo(arguments[0],arguments[1],arguments[2]);
}
}
function empty(){
}
function benchmark(f){
var i = 0;
var start = (new Date()).getTime();
while(i &lt; pressure){
f(i++);
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
}
/*
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
c = [i,i,i,i,i,i,i,i,i,i];
i++;
}
end = (new Date()).getTime();
WScript.Echo(end-start);
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
c = new Array(i,i,i,i,i,i,i,i,i,i);
i++;
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
*/
function internCast(i){
return &quot;&quot; + i;
}
function StringCast(i){
return String(i)
}
function newStringCast(i){
return new String(i)
}
function toStringCast(i){
return i.toString();
}
function ParseInt(){
return parseInt(j);
}
function MathFloor(){
return Math.floor(j);
}
function Floor(){
return floor(j);
}
var pressure = 50000;
var a  = &quot;&quot;;
var floor = Math.floor;
j = 123.123;
print(&quot;-------------\nString Conversion Test&quot;);
print(&quot;The empty:&quot;, benchmark(empty));
print(&quot;intern:&quot;, benchmark(internCast));
print(&quot;String:&quot;);
benchmark(StringCast);
print(&quot;new String:&quot;);
benchmark(newStringCast);
print(&quot;toString:&quot;);
benchmark(toStringCast);
print(&quot;-------------\nFloat to Int Conversion Test&quot;);
print(&quot;parseInt&quot;);
benchmark(ParseInt);
print(&quot;Math.floor&quot;);
benchmark(MathFloor);
print(&quot;floor&quot;)
benchmark(Floor);
function newObject(){
return new Object();
}
function internObject(){
return {};
}
print(&quot;------------\nliteral Test&quot;);
print(&quot;runtime new object&quot;, benchmark(newObject));
print(&quot;literal object&quot;, benchmark(internObject));
</pre>
<h1>附录2</h1>
<p>代码1：</p>
<pre>    for(var i=0;i&lt;100;i++){
arr[i]=0;
}</pre>
<p><br /></p>
<p>代码2：</p>
<pre>    var i = 0;
while(i &lt; 100){
arr[i++]=0;
}</pre>
<p><br /></p>
<p>代码3：</p>
<pre>    var i = 0;
while(i &lt; 100){
arr[i]=0;
i++;
}</pre>
<p><br /></p>
<p>在firefox下测试这两段代码，结果是代码2优于代码1和3，而代码1一般优于代码3，有时会被代码3超过；而在IE 6.0下，测试压力较大的时候（如测试10000次以上）代码2和3则有时候优于代码1，有时候就会远远落后代码1，而在测试压力较小（如5000次），则代码2&gt;代码3&gt;代码1。</p>
<p>代码4：</p>
<pre>    var i = 0;
var a;
while(i &lt; 100){
a = 0;
i++;
}</pre>
<p><br /></p>
<p>代码5：</p>
<pre>    var a;
for(var i=0;i&lt;100;i++){
a = 0;
}</pre>
<p>上面两段代码在Firefox和IE下测试结果都是性能接近的。</p>
<p>代码6：</p>
<pre>    var a;
var i=0;
while(i&lt;100){
a=i;
i++;
}</pre>
<p><br /></p>
<p>代码7：</p>
<pre>    var a;
var i=0;
while(i&lt;100){
a=i++;
}</pre>
<p><br /></p>
<p>代码8：</p>
<pre>    var a;
for(var i=0;i&lt;100;i++){
a = i;
}</pre>
<p><br /></p>
<p>代码9：</p>
<pre>    var a;
for(var i=0;i&lt;100;){
a = i++;
}</pre>
<p>这四段代码在Firefox下6和8的性能接近，7和9的性能接近，而6, 8 &lt; 7, 9；</p>
<p>最后我们来看一下空循环</p>
<p>代码10：</p>
<pre>    for(var i=0;i&lt;100;i++){   }</pre>
<p><br /></p>
<p>代码11：</p>
<pre>    var i;
while(i&lt;100){        i++;    }
</pre>
<p>最后的测试出现了神奇的结果，Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值，于是我没有放在一开始给大家看。</p>
</div>
<br /><br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=747880</p>
</div><img src ="http://www.blogjava.net/BaSaRa/aggbug/52904.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-15 09:13 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/15/52904.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转] JavaScript 2 已经确定发布日期 </title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52896.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 15 Jun 2006 00:53:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52896.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/52896.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/15/52896.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/52896.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/52896.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ECMAScript Edition 4在经历了多年停顿后终于重上轨道。在最近的Brendan Eich的演讲中，已提出ES4的Deadline将是2007年第一季度。他还预测，JS2将在4年里取代JS1。<br />　　根据Brendan Eich的演讲稿，FireFox的未来版本将逐步加入以ECMAScript Edtion 4为蓝本的JavaScript 2的支持，到2007年第二季度，FireFox 3将包含基本完整的JavaScript 2。<br /><br />Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=753266<br /><img src ="http://www.blogjava.net/BaSaRa/aggbug/52896.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-15 08:53 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/15/52896.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[引用] 对闭包的理解</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/13/52377.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Tue, 13 Jun 2006 03:13:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/13/52377.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/52377.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/13/52377.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/52377.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/52377.html</trackback:ping><description><![CDATA[<div class="postbody">今天在群里面瞎谈，就谈到&ldquo;闭包&rdquo;上来了，何种语言支持闭包？自己g下吧，其中JavaScript是支持闭包概念的一种语言/脚本(?)。以下是我对他的见解(以javascript举例)。<br /><br />先了解下在一个对象内如何声明变量，一下以Test对象为例：<br />Public变量：<br />
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br />}</span></div>
或者
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Test.prototype.x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;</span></div>
公共变量简而言之，外界对象可以对公共变量访问，并且公共变量可以在对象的构造函数中声明外，还可以在对象的prototype成员中声明。换句话说，你可以在任何时候添加公共变量（利用prototype）。prototype是一个特别的成员变量，js就是利用这个成员变量的特性来实现继承的。当一个成员被检索且没有在对象中发现的时候，那么它就会从对象构造器的prototype成员中获取他。如果要从外界调用这个对象的方法，或者是通过这个方法操作这个对象里面的所有成员，你可以通过prototype加入：<br />
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">Test.prototype.Plus&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()&nbsp;{<img src="http://www.cnblogs.com/Images/dot.gif" alt="" />}</span></div>
<br />Private变量：
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;self&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Plus1()&nbsp;{<img src="http://www.cnblogs.com/Images/dot.gif" alt="" />}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;pPlus&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Plus2()&nbsp;{<img src="http://www.cnblogs.com/Images/dot.gif" alt="" />}<br />}</span></div>
私有的变量只能由成员的私有方法或者是特权方法（Privileged，下面讲到）访问，需要注意的是，上面的Plus1()这个方法和pPlus()这个方法是一样的，只是声明的方式不通而已，他们都是私有方法，他和特权变量的声明方法很相似，只是少了个this多了个var，但是他们是不同的，应该特别注意。另外一点是，私有变量是在无法被外界访问的同时，他也不能由对象的公共方法访问。私有方法只是在构造函数内的内部方法。私有变量只能在构造函数中声明。<br /><br />Privileged变量：<br />
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.pPlus&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()&nbsp;{<img src="http://www.cnblogs.com/Images/dot.gif" alt="" />}<br />}</span></div>
什么叫Privileged（特权）变量呢？特权方法可以访问私有方法和私有变量，同时他对外界是可见的。你可以重新声明这个私有方法或者是删除他（重新对这个特权方法赋值，null值表示删除），但是不能改变他。特权变量也只能在构造函数中声明。<br /><br />好了，对象声明介绍到这里，这些声明模式都是由js的closure（闭包）特性所支持的，下面介绍闭包。<br /><br />在一个闭包内，你可以暂且(?)理解成在构造函数内，内部函数总是可以访问函数外部的变量和参数的。就算在内部函数return后，闭包内的所有变量都会被保存起来，就好像一个上下文一样。下面我以一个例子说明这个问题，例子来源在群内，由YOK提供（例子已经被修改，只是用来简单说明问题）。<br /><br />说明：按test按钮输出相加的值，期望值为3。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input&nbsp;type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">button</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;value</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test&nbsp;(x,&nbsp;y)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;y&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;y;<br />}<br />Test.prototype.add&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.y);<br />}<br /><br /></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Test(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br />document.getElementById('test').onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t.add;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span></div>
<br />运行例子，但是输出&quot;NaN&quot;。这是什么问题呢，我最初调试的时候，以为是this的问题，我原本理解成在add方法中this是指向test按钮（其实this指向window对象），而他不包含x和y的两个变量，所以输出错误。首先，这个理解是正确的，但是你要如何修改才能获取正确的结果呢。我们已经知道，在Test构造函数中，我们声明的x，y是两个私有变量，你不可能在外部访问到，所以必须另觅他路。我们利用特权变量来解决。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input&nbsp;type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">button</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;value</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;NAME</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test&nbsp;(x,&nbsp;y)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;x&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;x;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;y&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;y;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.add&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">&nbsp;特权变量，可以访问私有变量，又对外公开</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(x&nbsp;</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">&nbsp;y);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Test(</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">,&nbsp;</span><span style="COLOR: #000000">2</span><span style="COLOR: #000000">);<br />document.getElementById('test').onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t.add;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span></div>
<br />上面呈现的是闭包的其中一个特性，下面用来说他的另外一个特性。
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input&nbsp;type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">button</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;value</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;NAME</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test&nbsp;()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;z&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.add&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(z</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Test();<br />document.getElementById('test').onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t.add;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span></div>
每次输出，值都会增加1，说明闭包内上下文就算add方法return后都会被保存。<br /><br />最后说下怎么动态替换行为（这里是按钮click的行为）。<br />
<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">input&nbsp;type</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">button</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;id</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;value</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">&nbsp;NAME</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">test</span><span style="COLOR: #000000">&quot;</span><span style="COLOR: #000000">/&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;Test&nbsp;()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;z&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;self&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;pBtn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.selfSubtract&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;z</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;z</span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(z);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pBtn.onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;self.selfPlus;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.selfPlus&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;z</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(z);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pBtn.onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;self.selfSubtract;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.getFunction&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">function</span><span style="COLOR: #000000">&nbsp;(btn)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pBtn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;btn;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">&nbsp;self.selfSubtract;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}<br /><br /></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;t&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000">&nbsp;Test();<br /></span><span style="COLOR: #0000ff">var</span><span style="COLOR: #000000">&nbsp;btn&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;document.getElementById('test');<br />btn.onclick&nbsp;</span><span style="COLOR: #000000">=</span><span style="COLOR: #000000">&nbsp;t.getFunction(btn);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">script</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">body</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #000000">&lt;/</span><span style="COLOR: #000000">html</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br /></span></div>
以上是我对他的一点见解，closure是js的一个特性而已，我们可以利用这个特性使设计更灵活，其他语言，我google到的好像叫Lua，不知道他是什么，他也支持。由于对js了解不深，请高手斧正确，enjoy it~~~ :) </div><img src ="http://www.blogjava.net/BaSaRa/aggbug/52377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-13 11:13 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/13/52377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>兼容IE和Firefox的数据岛方法</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51710.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 09 Jun 2006 07:53:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51710.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/51710.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51710.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/51710.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/51710.html</trackback:ping><description><![CDATA[<p>看我们老大的代码，不错，特地奉献出来<br /><br />首先，HTML页面：<br /><font style="BACKGROUND-COLOR: #c0c0c0">&lt;script type=&quot;text/javascript&quot; src=&quot;xmlPathDemo.js&quot;&gt;&lt;/script&gt;<br />&lt;h2&gt;XML Order Database&lt;/h2&gt;<br />&lt;form&gt;<br />&nbsp;&lt;table border=&quot;0&quot;&gt;<br />&nbsp;&nbsp;&lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;SKU&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;SKU&quot;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;Price&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;Price&quot;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;Quantity&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;Quantity&quot;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;Total&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;Total&quot;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&nbsp;&lt;tr&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;Description&lt;/td&gt;<br />&nbsp;&nbsp;&nbsp;&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;Description&quot;&gt;&lt;/td&gt;<br />&nbsp;&nbsp;&lt;/tr&gt;<br />&nbsp;&lt;/table&gt;<br />&nbsp;&lt;input type=&quot;button&quot; value=&quot; &lt;&lt; &quot; onClick=&quot;getDataPrev();&quot;&gt;<br />&nbsp;&lt;input type=&quot;button&quot; value=&quot; &gt;&gt; &quot; onClick=&quot;getDataNext();&quot;&gt;<br />&lt;/form&gt;<br /><br />其次：一个XML数据源：<br />&lt;?xml version=&quot;1.0&quot; ?&gt;<br />&lt;Order&gt;<br />&nbsp;&lt;Account&gt;9900234&lt;/Account&gt;<br />&nbsp;&lt;Item id=&quot;1&quot;&gt;<br />&nbsp;&nbsp;&lt;SKU&gt;1234&lt;/SKU&gt;<br />&nbsp;&nbsp;&lt;PricePer&gt;5.95&lt;/PricePer&gt;<br />&nbsp;&nbsp;&lt;Quantity&gt;100&lt;/Quantity&gt;<br />&nbsp;&nbsp;&lt;Subtotal&gt;595.00&lt;/Subtotal&gt;<br />&nbsp;&nbsp;&lt;Description&gt;Super Widget Clamp&lt;/Description&gt;<br />&nbsp;&lt;/Item&gt;<br />&nbsp;&lt;Item id=&quot;2&quot;&gt;<br />&nbsp;&nbsp;&lt;SKU&gt;6234&lt;/SKU&gt;<br />&nbsp;&nbsp;&lt;PricePer&gt;22.00&lt;/PricePer&gt;<br />&nbsp;&nbsp;&lt;Quantity&gt;10&lt;/Quantity&gt;<br />&nbsp;&nbsp;&lt;Subtotal&gt;220.00&lt;/Subtotal&gt;<br />&nbsp;&nbsp;&lt;Description&gt;Mighty Foobar Flange&lt;/Description&gt;<br />&nbsp;&lt;/Item&gt;<br />&nbsp;&lt;Item id=&quot;3&quot;&gt;<br />&nbsp;&nbsp;&lt;SKU&gt;9982&lt;/SKU&gt;<br />&nbsp;&nbsp;&lt;PricePer&gt;2.50&lt;/PricePer&gt;<br />&nbsp;&nbsp;&lt;Quantity&gt;1000&lt;/Quantity&gt;<br />&nbsp;&nbsp;&lt;Subtotal&gt;2500.00&lt;/Subtotal&gt;<br />&nbsp;&nbsp;&lt;Description&gt;Deluxe Doohickie&lt;/Description&gt;<br />&nbsp;&lt;/Item&gt;<br />&nbsp;&lt;Item id=&quot;4&quot;&gt;<br />&nbsp;&nbsp;&lt;SKU&gt;3256&lt;/SKU&gt;<br />&nbsp;&nbsp;&lt;PricePer&gt;389.00&lt;/PricePer&gt;<br />&nbsp;&nbsp;&lt;Quantity&gt;1&lt;/Quantity&gt;<br />&nbsp;&nbsp;&lt;Subtotal&gt;389.00&lt;/Subtotal&gt;<br />&nbsp;&nbsp;&lt;Description&gt;Muckalucket Bucket&lt;/Description&gt;<br />&nbsp;&lt;/Item&gt;<br />&nbsp;&lt;NumberItems&gt;1111&lt;/NumberItems&gt;<br />&nbsp;&lt;Total&gt;3704.00&lt;/Total&gt;<br />&nbsp;&lt;OrderDate&gt;07/07/2002&lt;/OrderDate&gt;<br />&nbsp;&lt;OrderNumber&gt;8876&lt;/OrderNumber&gt;<br />&lt;/Order&gt;<br /><br />引用这个JS：<br />try{<br />&nbsp;var i = -1;<br />&nbsp;var orderDoc = new ActiveXObject(&quot;MSXML2.DOMDocument.3.0&quot;);<br />&nbsp;orderDoc.load(&quot;order.xml&quot;);<br />&nbsp;var items = orderDoc.selectNodes(&quot;/Order/Item&quot;);<br />}catch(e){}</font></p>
<p><font style="BACKGROUND-COLOR: #c0c0c0">function getNode(doc, xpath) {<br />&nbsp;varretval = &quot;&quot;;<br />&nbsp;var value = doc.selectSingleNode(xpath);<br />&nbsp;if (value) retval = value.text;<br />&nbsp;return retval;<br />}</font></p>
<p><font style="BACKGROUND-COLOR: #c0c0c0">function getDataNext() {<br />&nbsp;i++;<br />&nbsp;if (i &gt; items.length - 1) i = 0;<br />&nbsp;<br />&nbsp;document.forms[0].SKU.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/SKU&quot;);<br />&nbsp;document.forms[0].Price.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/PricePer&quot;);<br />&nbsp;document.forms[0].Quantity.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/Quantity&quot;);<br />&nbsp;document.forms[0].Total.value = getNode(orderDoc,&quot;/Order/Item[&quot; + i + &quot;]/Subtotal&quot;);<br />&nbsp;document.forms[0].Description.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/Description&quot;);<br />}</font></p>
<p><font style="BACKGROUND-COLOR: #c0c0c0">function getDataPrev() {<br />&nbsp;i--;<br />&nbsp;if (i &lt; 0) i = items.length - 1;<br />&nbsp;<br />&nbsp;document.forms[0].SKU.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/SKU&quot;);<br />&nbsp;document.forms[0].Price.value = getNode(orderDoc,&quot;/Order/Item[&quot; + i + &quot;]/PricePer&quot;);<br />&nbsp;document.forms[0].Quantity.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/Quantity&quot;);<br />&nbsp;document.forms[0].Total.value = getNode(orderDoc,&quot;/Order/Item[&quot;+ i + &quot;]/Subtotal&quot;);<br />&nbsp;document.forms[0].Description.value = getNode(orderDoc, &quot;/Order/Item[&quot; + i + &quot;]/Description&quot;);<br />}&nbsp;&nbsp;</font></p>
<p><font style="BACKGROUND-COLOR: #c0c0c0">window.onload = function() {<br />&nbsp;getDataNext();<br />}<br /><br /><font style="BACKGROUND-COLOR: #ffffff">好了，运行看看，和IE的数据岛功能一样</font></font></p><img src ="http://www.blogjava.net/BaSaRa/aggbug/51710.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-09 15:53 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/09/51710.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>文摘：《JavaScript，世界上最被误解的语言》</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51702.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 09 Jun 2006 07:42:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51702.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/51702.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/51702.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/51702.html</trackback:ping><description><![CDATA[<p>　　JavaScript, 亦称为 Mocha 、LiveScript，也叫做 JScript ECMAScript ，是世界上流行的编程语言之一。事实上世界上差不多每台个人电脑都至少安装了一个JavaScript解释器。JavaScript的流行完全在于它作为WWW的脚本语言的角色。 </p>
<p>　　不管它有多么流行，极少有人了解JavaScript是一个十分动态的通用面向对象编程语言。这怎能成为一个秘密呢？为什么这个语言如此被误解？ </p>
<p>&nbsp;</p>
<p><font size="2"><strong>关于名字</strong></font></p>
<p><font size="2"><br /></font>　　这个Java-前缀暗示了JavaScript和Java的关系，也就是JavaScipt是Java的一个子集也就是不如Java强大。看上去这个名称就故意制造混乱，然后随之而来的是误解。JavaScript并不是解释型的Java语言。Java是解释型的Java，JavaScript是另一种语言。 </p>
<p>　　JavaScript和Java的语法很相似，就象Java和C的语法相似一样。但它也不是Java的子集就像Java也不是C的子集一样。在应用上，Java要远比原先设想的好得多（Java原称Oak）。 </p>
<p>　　JavaScript并不是由Sun公司──Java的老家──开发的。JavaScript是由Netscape公司开发。它本来叫做LiveScript，这个名字倒并不是那样容易混淆。 </p>
<p>　　这个-Script 后缀暗示了它似乎不是一个完整的编程语言──大多数人以为脚本语言就不算真正的编程语言。但其实这是一个专长的问题。相对C而言，JavaScript牺牲了性能但带来更强的表达力和动态性。</p>
<p>&nbsp;</p>
<p><font size="2"><strong>披着C外衣的Lisp</strong></font></p>
<p><strong><font size="2"></font></strong><br />　　JavaScript的C风格的语法，包括大括号和复杂的for 语句，让它看起来好象是一个普通的过程式语言。这是一个误导，而事实上JavaScript和函数式语言如Lisp和Scheme有更多的共同之处。它用数组代替了列表，用对象代替了属性列表，而且函数是第一型的，同时还有闭包。你不需要Lisp那些括号就可以用lambda算子。 </p>
<p>&nbsp;</p>
<p><strong><font face="黑体" size="3"><font face="宋体" size="2">思维定势</font></font></strong></p>
<p><strong><font face="黑体" size="3"><font face="宋体" size="2"></font><br /></font></strong>　　JavaScript是原本只是被设计在Netscape Navigator 中运行的。Netscape的成功让JavaScript成为几乎所有浏览器的标准配置。这导致了对JavaScript的思维定势。JavaScript简直就是程序语言中的George Reeves （一位曾扮演超人的演员，但后来死于枪杀，被官方认为自杀，细节不详──译注）。而事实上，JavaScript也适合很多和Web无关的应用程序。 </p>
<p>&nbsp;</p>
<p><font size="2"><strong>不断改变的目标</strong></font></p>
<p><font size="2"><strong></strong><br /></font>　　JavaScript的第一个版本功能十分弱。它缺少异常处理、内部函数和继承。而它的现在的形态，它已经是一套完整的面向对象语言。但很多看法都是认为它的形式还不成熟。 </p>
<p>　　管理这个语言的ECMA委员正在开发扩展，原意是很好，而这样做却会加剧这个语言本来就最严重的问题：版本太多了。这也造成了很多混乱。 </p>
<p>&nbsp;</p>
<p><strong><font size="2">设计错误</font></strong></p>
<p><strong><font size="2"></font></strong><br />　　没有什么编程语言是完美的，JavaScript当然也有它的设计上的错误，如+的重载同时表示加和带类型自动转换的串连接，和有错误倾向的 with 语句&mdash;&mdash;应该避免使用。Javascript的保留字策略过于严格。引入分号也是一个很大的错误，正则表达式的记号也是。这些错误会很容易导致编程错误，并导致语言的设计的全局层面上的问题。幸运的是，这些问题可以用一个很好的lint程序来避免。 </p>
<p>这个语言的设计从整体上看还是十分健全的。但很令人惊讶的是， ECMAScript委员会好象根本不想修正这些错误。也许他们对重新设计一个更感兴趣。 </p>
<p>&nbsp;</p>
<p><font size="3"><strong><font size="2">肮脏的实现</font></strong></font></p>
<p><font size="3"><strong><font size="2"></font><br /></strong></font>JavaScript的早期实现错误百出。这对该语言带来了很恶劣的影响。更糟糕的是，这些实现还被嵌入的更错误百出的浏览器中。</p>
<p>&nbsp;</p>
<p><strong>拙劣的书籍</strong></p>
<p><strong></strong><br />　　几乎所有的书籍都十分恐怖。里面到处是错误、蹩脚的例子还自创一套拙劣的惯例。语言中重要的特性却常常解释不好，或者干脆完全不写。我翻阅了几十本JavaScript的书，我只推荐两本：JavaScript: The Definitive Guide (4th Edition) by David Flanagan and Dynamic HTML (2nd Edition) by Danny Goodman. 都来自于 O'Reilly. </p>
<p>&nbsp;</p>
<p><strong>不够标准的标准</strong></p>
<p><strong></strong><br />　　该语言的官方标准规格说明书由ECMA发布。但该规格书也是质量奇差。它难以阅读也难以理解。它也对拙劣书籍的问题作出了自己的一份&ldquo;贡献&rdquo;，因为作者无法使用这个标准文档来增加他们对语言的认识。ECMA和TC39委员会应该为此感到深深的羞愧。 </p>
<p>&nbsp;</p>
<p><strong>业余爱好者</strong></p>
<p><strong></strong><br />大部分写JavaScript的人都不是程序员。他们缺乏训练写好程序的修养。JavaScript有如此丰富的表达能力，他们可以任意用它来写代码，以任何形式。这给JavaScript带来了一个名声──它是专门为外行设计的，不适合专业的程序员。这显然不是事实。 </p>
<p>&nbsp;</p>
<p><strong>面向对象</strong></p>
<p><strong></strong><br />　　JavaScript是不是面向对象的？它拥有对象，可以包含数据和处理数据的方法。对象可以包含其它对象。它没有类，但它却有构造器可以做类能做的事，包括扮演类变量和方法的容器的角色。它没有基于类的继承，但它有基于原型的继承。 </p>
<p>　　两个建立对象系统的方法是通过继承（是一个&hellip;&hellip;）和通过聚合（有一个&hellip;&hellip;）。JavaScript两个都有，但它的动态性质让它可以在聚合上超越。 </p>
<p>　　一些批评说JavaScript不是真正面向对象的因为它不能提供信息的隐藏。也就是，对象不能有私有变量和私有方法：所有的成员都是公共的。 </p>
<p>　　但又有证明了JavaScript对象可以拥有私有变量和私有方法。当然，极少有人认识到，因为JavaScript是世界是最受误解的程序嘛！ </p>
<p>　　另外还有批评说JavaScript不能提供继承，这里证明了JavaScript不仅能支持传统的继承还能应用其它的代码复用模式。 </p>
<p>&nbsp;</p>
<p>作者：Douglas Crockford</p>
<p>翻译：<font face="Nimbus Roman No9 L, serif">ShiningRay</font> </p><img src ="http://www.blogjava.net/BaSaRa/aggbug/51702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-09 15:42 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/09/51702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从ajax.cn摘录下来的ajax设计模式，其实也是《ajax in action》的第三章主要内容：）</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51605.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 09 Jun 2006 01:20:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51605.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/51605.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/09/51605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/51605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/51605.html</trackback:ping><description><![CDATA[<p>//Facade模式实例<br />var net=new Object();<br />net.READY_STATE_UNINITIALIZED=0;<br />net.READY_STATE_LOADING=1;<br />net.READY_STATE_LOADED=2;<br />net.READY_STATE_INTERACTIVE=3;<br />net.READY_STATE_COMPLETE=4;<br />net.ContentLoader=function(url,onload,onerror){<br />this.url=url;<br />this.req=null;<br />this.onload=onload;<br />this.onerror=(onerror) ? onerror : this.defaultError;<br />this.loadXMLDoc(url);<br />net.ContentLoader.prototype={<br />&nbsp; loadXMLDoc:function(url){<br />&nbsp;&nbsp;&nbsp; if (window.XMLHttpRequest){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.req=new XMLHttpRequest();<br />&nbsp;&nbsp;&nbsp; } else if (window.ActiveXObject){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.req=new ActiveXObject(&quot;Microsoft.XMLHTTP&quot;);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; if (this.req){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var loader=this;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.req.onreadystatechange=function(){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; loader.onReadyState.call(loader);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.req.open('GET',url,true);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.req.send(null);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }catch (err){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.onerror.call(this);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp; },<br />&nbsp; onReadyState:function(){<br />&nbsp;&nbsp;&nbsp; var req=this.req;<br />&nbsp;&nbsp;&nbsp; var ready=req.readyState;<br />&nbsp;&nbsp;&nbsp; if (ready==net.READY_STATE_COMPLETE){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var httpStatus=req.status;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (httpStatus==200 || httpStatus==0){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.onload.call(this);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.onerror.call(this);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp; },<br />&nbsp; defaultError:function(){<br />&nbsp;&nbsp;&nbsp; alert(&quot;error fetching data!&quot;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +&quot;\n\nreadyState:&quot;+this.req.readyState<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +&quot;\nstatus: &quot;+this.req.status<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +&quot;\nheaders: &quot;+this.req.getAllResponseHeaders());<br />&nbsp; }<br />}</p>
<p>//Adapter模式实例<br />var xhr = new XMLHttpRequest();<br />xhr.open(&quot;GET&quot;, &quot;myData.xml&quot;);<br />xhr.onreadystatechange = function(){<br />&nbsp; if(xhr.readyState == 4){<br />&nbsp;&nbsp;&nbsp; alert(xhr.responseXML);<br />&nbsp; }<br />}<br />xhr.send(null);</p>
<p><br />//Observer模式实例<br />window.onloadListeners=new Array();<br />&nbsp; window.addOnLoadListener(listener){<br />&nbsp; window.onloadListeners[window.onloadListeners.length]=listener;<br />}</p>
<p>window.onload=function(){<br />&nbsp; for(var i=0;i&lt;window.onloadListeners.length;i++){<br />&nbsp;&nbsp;&nbsp; var func=window.onlloadListeners[i];<br />&nbsp;&nbsp;&nbsp; func.call();<br />&nbsp; }<br />}</p>
<p>//Singleton模式实例<br />var SingletonObj = {<br />&nbsp; property1: value1,<br />&nbsp; property2: value2,<br />&nbsp; ...<br />&nbsp; method1:function(){<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp; }<br />&nbsp; method2:function(){<br />&nbsp;&nbsp;&nbsp; ...<br />&nbsp; }<br />&nbsp; ...<br />}</p>
<p>function getSingletonObj() {<br />&nbsp; if(!top.SingletonObj) {<br />&nbsp;&nbsp;&nbsp; var top.SingletonObj = {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; top.SingletonObj.init(...);<br />&nbsp; }<br />&nbsp; return top.SingletonObj;<br />}</p>
<p>//Command模式实例<br />function buttonOnclickHandler(event){<br />&nbsp; var data=calculate();<br />&nbsp; showData(dataTable,data);<br />}<br />function ajaxOnloadHandler(){<br />&nbsp; var data=calculate();<br />&nbsp; showData(otherDataTable,data);<br />}<br />function calculate(){<br />&nbsp; var data=new Array();<br />&nbsp; data[0]=6;<br />&nbsp; data[1]=data[0]/3;<br />&nbsp; data[2]=data[0]*data[1]+7;<br />&nbsp; return data;<br />}<br />function showData(table,data){<br />&nbsp; var newRow=createTableRow(table);<br />&nbsp; for (var i=0;i&lt;data.length;i++){<br />&nbsp;&nbsp;&nbsp; createTableCell(newRow,data[i]);<br />&nbsp; }<br />}<br />buttonDiv.onclick=buttonOnclickHandler;<br />poller.onload=ajaxOnloadHandler;</p>
<p>//MVC应用实例<br />function Button(value,domEl){<br />&nbsp; this.domEl=domEl;<br />&nbsp; this.value=value;<br />&nbsp; this.domEl.buttonObj=this;<br />&nbsp; this.domEl.onclick=this.clickHandler;<br />}</p>
<p>Button.prototype.clickHandler=function(){<br />&nbsp; var buttonObj=this.buttonObj;<br />&nbsp; var value=(buttonObj &amp;&amp; buttonObj.value) ?<br />&nbsp;&nbsp;&nbsp; buttonObj.value : &quot;unknown value&quot;;<br />&nbsp; alert(value);<br />}</p><img src ="http://www.blogjava.net/BaSaRa/aggbug/51605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-09 09:20 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/09/51605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>这几天没空更新BLOG，今天就放个很简单的解析JSON程序吧</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/08/51383.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 08 Jun 2006 08:09:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/08/51383.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/51383.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/08/51383.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/51383.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/51383.html</trackback:ping><description><![CDATA[<p>一个JSON：<br />var infos = {<br />&nbsp;&quot;user&quot;&nbsp;:&nbsp;{<br />&nbsp;&nbsp;&quot;id&quot;&nbsp;&nbsp;:&nbsp;&quot;001&quot;,<br />&nbsp;&nbsp;&quot;data&quot;&nbsp;:&nbsp;[<br />&nbsp;&nbsp;&nbsp;{&quot;id&quot;:&quot;loginName&quot;, &quot;value&quot;:&quot;yiyi&quot;},<br />&nbsp;&nbsp;&nbsp;{&quot;id&quot;:&quot;name&quot;, &quot;value&quot;:&quot;翼翼&quot;},<br />&nbsp;&nbsp;&nbsp;{&quot;id&quot;:&quot;sex&quot;, &quot;value&quot;:&quot;女&quot;},&nbsp;<br />&nbsp;&nbsp;&nbsp;{&quot;id&quot;:&quot;age&quot;, &quot;value&quot;:&quot;22&quot;},<br />&nbsp;&nbsp;]<br />&nbsp;}<br />}<br /><br />function parse(v, partion) {<br />&nbsp;var splits = partion.split(&quot;.&quot;);<br />&nbsp;var tmp = v;<br />&nbsp;for(var i=0;i&lt;splits.length;i++){<br />&nbsp;&nbsp;tmp = tmp[splits[i]];<br />&nbsp;}<br />&nbsp;alert(tmp);<br />}</p>
<p>parse(infos, &quot;user.data&quot;);<br /><br />只是很简单的深度解析，开始没这样做，是我们的老大写的 - - 俺太笨了<img src="http://www.blogjava.net/Emoticons/msn/sad_smile.gif" alt="" /></p><img src ="http://www.blogjava.net/BaSaRa/aggbug/51383.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-08 16:09 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/08/51383.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>今天整理了一下dojo事件机制，包括一些例子</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/02/49952.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Fri, 02 Jun 2006 07:59:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/02/49952.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49952.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/02/49952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49952.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49952.html</trackback:ping><description><![CDATA[<p>1.普通绑定<br />dojo.event.connect(DOMNode, 'onclick', 'func');</p>
<p>2.绑定多个事件<br />dojo.event.connect(DOMNode, 'onclick', 'func1');<br />dojo.event.connect(DOMNode, 'onclick', 'func2');</p>
<p>3.绑定一个obj的两个方法<br />dojo.event.connect(DOMNode, 'onclick', evtObj, 'func1');<br />dojo.event.connect(DOMNode, 'onclick', evtObj, 'func2');</p>
<p>4.让绑定的事件顺序执行<br />var exampleObj = {<br />&nbsp;&nbsp;counter: 0,<br />&nbsp;&nbsp;foo: function(){ <br />&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;foo&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;this.counter++;<br />&nbsp;&nbsp;},<br />&nbsp;&nbsp;bar: function(){<br />&nbsp;&nbsp;&nbsp;&nbsp;alert(&quot;bar&quot;);<br />&nbsp;&nbsp;&nbsp;&nbsp;this.counter++;<br />&nbsp;&nbsp;}<br />};<br />dojo.event.connect(exampleObj, &quot;foo&quot;, exampleObj, &quot;bar&quot;);&nbsp;// 调用foo的话bar也会执行<br />这样也可以<br />dojo.event.kwConnect({<br />&nbsp;type&nbsp;:&nbsp;'before'&nbsp;// 让bar在foo之前执行<br />&nbsp;srcObj&nbsp;:&nbsp;exampleObj,<br />&nbsp;srcFunc&nbsp;:&nbsp;'foo',<br />&nbsp;targetObj&nbsp;:&nbsp;exampleObj,<br />&nbsp;targetFunc&nbsp;:&nbsp;'bar',<br />&nbsp;delay&nbsp;:&nbsp;2000&nbsp;// bar延迟执行2秒<br />&nbsp;once&nbsp;:&nbsp;true&nbsp;// 绑定一次<br />});<br />exampleObj.foo();</p>
<p>5.先后执行<br />dojo.event.connect(&quot;after&quot;, exampleObj, &quot;foo&quot;, exampleObj, &quot;bar&quot;);&nbsp;// bar在foo之后执行<br />dojo.event.connect(&quot;before&quot;, exampleObj, &quot;foo&quot;, exampleObj, &quot;bar&quot;);&nbsp;// bar在foo之前执行</p>
<p>6.传递参数<br />var evtObj = function() {<br />&nbsp;this.func1 = function(a) {<br />&nbsp;&nbsp;return(function(e) {<br />&nbsp;&nbsp;&nbsp;alert((e||window.event).type);<br />&nbsp;&nbsp;})<br />&nbsp;};<br />&nbsp;this.func2 = function(b) {<br />&nbsp;&nbsp;alert(b);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;};<br />}</p>
<p>var o = new evtObj();<br />var btn = dojo.byId(&quot;testBtn&quot;);<br />dojo.event.connect(btn, 'onclick', o.func1('hello'));</p>
<p>以前一般这样写：<br />function init() {<br />var evtObj = function() {<br />&nbsp;this.func1 = function(a) {<br />&nbsp;&nbsp;alert(a.type);<br />&nbsp;};<br />&nbsp;this.func2 = function(b) {<br />&nbsp;&nbsp;alert(b);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;};<br />}</p>
<p>var o = new evtObj();<br />var btn = dojo.byId(&quot;testBtn&quot;);<br />dojo.event.connect(btn, 'onclick', function(event){o.func1(event)});<br />这样的话你在第三个参数就要传递event，很麻烦</p><img src ="http://www.blogjava.net/BaSaRa/aggbug/49952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-02 15:59 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/02/49952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的定时器，不知道会不会存在内存泄露。。。</title><link>http://www.blogjava.net/BaSaRa/archive/2006/06/01/49565.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Thu, 01 Jun 2006 06:18:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/06/01/49565.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49565.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/06/01/49565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49565.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49565.html</trackback:ping><description><![CDATA[<p>&lt;input type=&quot;button&quot; id=&quot;btn&quot; value=&quot;btn&quot;/&gt;<br />&lt;div id=&quot;div1&quot; style=&quot;display:none;&quot;&gt;I am tooltip&lt;/div&gt;</p>
<p>&lt;script language=&quot;JavaScript&quot;&gt;<br />&lt;!--<br />// 方法A<br />var obj = {<br />&nbsp;flag&nbsp;:&nbsp;null,<br />&nbsp;setTime&nbsp;:&nbsp;function(n) {<br />&nbsp;&nbsp;this.flag = setTimeout(function(){<br />&nbsp;&nbsp;&nbsp;document.getElementById(&quot;div1&quot;).style.display = &quot;&quot;;<br />&nbsp;&nbsp;}, n);<br />&nbsp;},<br />&nbsp;clear&nbsp;&nbsp;:&nbsp;function() {<br />&nbsp;&nbsp;clearTimeout(this.flag);<br />&nbsp;&nbsp;document.getElementById(&quot;div1&quot;).style.display = &quot;none&quot;;<br />&nbsp;}<br />}</p>
<p>document.getElementById(&quot;btn&quot;).onmouseover = function() {obj.setTime(1000);};<br />document.getElementById(&quot;btn&quot;).onmouseout = function() {obj.clear();};<br />//--&gt;<br />&lt;/script&gt;</p>
<p>&lt;script language=&quot;JavaScript&quot;&gt;<br />&lt;!--<br />//方法B<br />//var flag;<br />//function setTime(time) {<br />//&nbsp;return(function(e){<br />//&nbsp;&nbsp;flag=setTimeout(function() {<br />//&nbsp;&nbsp;&nbsp;document.getElementById(&quot;div1&quot;).style.display = &quot;&quot;;<br />//&nbsp;&nbsp;}, time);<br />//&nbsp;});<br />//}<br />//function clear() {<br />//&nbsp;clearTimeout(flag);<br />//&nbsp;document.getElementById(&quot;div1&quot;).style.display = &quot;none&quot;;<br />//}<br />//<br />//document.getElementById(&quot;btn&quot;).onmouseover = setTime(1000);<br />//document.getElementById(&quot;btn&quot;).onmouseout = clear;<br />//--&gt;<br />&lt;/script&gt;<br /><br />总觉得方法A和方法B都存在泄露隐患。。。</p><img src ="http://www.blogjava.net/BaSaRa/aggbug/49565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-06-01 14:18 <a href="http://www.blogjava.net/BaSaRa/archive/2006/06/01/49565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>怎样在不使用function(){ ... }情况下绑定事件</title><link>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49310.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 31 May 2006 09:35:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49310.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49310.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49310.html</trackback:ping><description><![CDATA[<p>一般写事件绑定都是这样写的：<br /><br />document.getElementById('btn').onclick = function() { func...&nbsp;}<br /><br />现在这样写：<br /><br />&lt;input type=&quot;button&quot; id=&quot;btn&quot; value=&quot;hello&quot;/&gt;</p>
<p>&lt;script language=&quot;JavaScript&quot;&gt;<br />&lt;!--<br />function associate(str){<br />&nbsp;&nbsp;&nbsp; return (function(e){&nbsp; // event会默认传进去，所以不用在associate的参数里传递event （ associate(event) ）<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var _e = e||window.event;&nbsp;&nbsp;// 在这里加入判断，兼容ff和ie<br />&nbsp;&nbsp;&nbsp;&nbsp;doClick(_e, this, str);<br />&nbsp;&nbsp;&nbsp; });<br />}</p>
<p>function doClick(a, b, c) {<br />&nbsp;alert(a.type);<br />&nbsp;alert(b.type);<br />&nbsp;alert(c);<br />}</p>
<p>document.getElementById('btn').onclick = associate('hello');<br />//--&gt;<br />&lt;/script&gt;</p><img src ="http://www.blogjava.net/BaSaRa/aggbug/49310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-05-31 17:35 <a href="http://www.blogjava.net/BaSaRa/archive/2006/05/31/49310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>msdn一篇关于内存泄漏的文章</title><link>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49213.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 31 May 2006 03:53:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49213.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49213.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49213.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49213.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49213.html</trackback:ping><description><![CDATA[
		<table height="24" cellspacing="0" cellpadding="4" width="100%" bgcolor="#ffffff" border="0">
				<tbody>
						<tr>
								<td class="eyebrow" valign="center" align="left" width="100%">   <a class="small" href="http://msdn.microsoft.com/default.asp" target="_top">MSDN Home</a> &gt;  <a class="small" href="http://msdn.microsoft.com/library/default.asp" target="_top">MSDN Library</a> &gt;  <a class="small" href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnanchor/html/anch_webdev.asp" target="_top">Web Development</a> &gt; <a href=""></a></td>
						</tr>
				</tbody>
		</table>
		<table class="clsContainer" style="TABLE-LAYOUT: fixed" cellspacing="0" cellpadding="15" width="100%" border="0" float="left">
				<tbody>
						<tr>
								<td valign="top">
										<!--TOOLBAR_START-->
										<!--TOOLBAR_EXEMPT-->
										<!--TOOLBAR_END-->
										<!-- Begin Content -->
										<table class="buttonbarshade" id="Table1" cellspacing="0">
												<tbody>
														<tr>
																<td> </td>
														</tr>
												</tbody>
										</table>
										<table class="buttonbartable" id="Table2" cellspacing="0">
												<tbody>
														<tr id="hdr">
																<td class="runninghead" nowrap="">Internet Explorer Development Technical Articles</td>
														</tr>
												</tbody>
										</table>
										<h1>
												<a name="ie_leakpattern">
												</a>Understanding and Solving Internet Explorer Leak Patterns</h1>
										<p>Justin Rogers<br />Microsoft Corporation</p>
										<p>June 2005</p>
										<h2>The Evolution of the Web Developer</h2>
										<p>In the past, memory leaks haven't posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.</p>
										<p>New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.</p>
										<p>The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed.</p>
										<h2>Leak Patterns</h2>
										<p>The following sections will discuss patterns of memory leaks and point out some common examples of each pattern. One great example of a pattern is the closure feature of JScript, while another example is the use of closures in hooking events. If you're familiar with the event hooking example, you might be able to find and fix many of your memory leaks, but other closure-related issues might go unnoticed.</p>
										<p>Now, let's look at the following patterns:</p>
										<ol>
												<li>
														<p>Circular References—When mutual references are counted between Internet Explorer's COM infrastructure and any scripting engine, objects can leak memory. This is the broadest pattern. </p>
												</li>
												<li>
														<p>Closures—Closures are a specific form of circular reference that pose the largest pattern to existing Web application architectures. Closures are easy to spot because they rely on a specific language keyword and can be searched for generically. </p>
												</li>
												<li>
														<p>Cross-Page Leaks—Cross-page leaks are often very small leaks of internal book-keeping objects as you move from site to site. We'll examine the DOM Insertion Order issue, along with a workaround that shows how small changes to your code can prevent the creation of these book-keeping objects. </p>
												</li>
												<li>
														<p>Pseudo-Leaks—These aren't really leaks, but can be extremely annoying if you don't understand where your memory is going. We'll examine the script element rewriting and how it appears to leak quite a bit of memory, when it is really performing as required. </p>
												</li>
										</ol>
										<h2>Circular References</h2>
										<p>Circular references are the root of nearly every leak. Normally, script engines handle circular references through their garbage collectors, but certain unknowns can prevent their heuristics from working properly. The unknown in the case of IE would be the status of any DOM elements that a portion of script has access to. The basic principle would be as follows:</p>
										<p>
												<img height="568" alt="Figure 1 Basic Circular Reference Pattern" src="http://msdn.microsoft.com/library/en-us/ietechcol/dnwebgen/ie_leak_patterns_fig01.gif" width="413" border="0" />
										</p>
										<p>
												<b>Figure 1. Basic Circular Reference Pattern</b>
										</p>
										<p>The cause of the leak in this pattern is based on COM reference counting. The script engine objects will hold a reference to the DOM element and will be waiting for any outstanding references to be removed before cleaning up and releasing the DOM element pointer. In our case we have two references on the script engine object: the script engine scope, and the DOM element expando property. While terminating the script engine will release the first reference, the DOM element reference will never be released because it is waiting on the script engine object to release it! You might think it would be easy to detect this scenario and fix the problem, but in practice the basic case presented is only the tip of the iceberg. You could have circular references at the end of a 30 object chain and those would be much harder to detect.</p>
										<p>If you are wondering what this pattern looks like in HTML, you can cause a leak by using a global script engine variable and a DOM element as shown.</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        var myGlobalObject;

        function SetupLeak()
        {
            // First set up the script scope to element reference
            myGlobalObject =
                document.getElementById("LeakedDiv");

            // Next set up the element to script scope reference
            document.getElementById("LeakedDiv").expandoProperty =
                myGlobalObject;
        }


        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
										</pre>
										<p>To break the leak pattern you can make use of explicit null assignments. By assigning null before the document unloads you are telling the script engine there is no longer an association between the element and the object inside the engine. It can now properly clean up references and will release the DOM element. In this case, you as the Web developer know more about the relationships between your objects than the script engine does.</p>
										<p>While that is the basic pattern, it can be difficult to spot more complex scenarios. A common usage of object-oriented JScript is to extend DOM elements by encapsulating them inside of a JScript object. During the construction process, you generally pass in the DOM element you want to attach to and then store a reference to the DOM element on the newly constructed object while at the same time storing an instance of the newly constructed object on the DOM element. That way your application model always has access to everything it needs. The problem is this is a very explicit circular reference, but because it uses different language aspects it might go unnoticed. Breaking up this kind of pattern can become more complex, and you can use the same simple methods discussed earlier.</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function Encapsulator(element)
        {
            // Set up our element
            this.elementReference = element;

            // Make our circular reference
            element.expandoProperty = this;
        }

        function SetupLeak()
        {
            // The leak happens all at once
            new Encapsulator(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code>
										</pre>
										<p>More complex solutions to this problem involve registration schemes to note which elements/properties need to be unhooked, having the peer element hook events so that it can clean up before the document unloads, but often you can run into additional leak patterns without actually fixing the problem.</p>
										<h2>Closures</h2>
										<p>Closures are very often responsible for leaks because they create circular references without the programmer being fully aware. It isn't immediately obvious that parent function parameters and local variables will be frozen in time, referenced, and held until the closure itself is released. In fact this has become such a common programming tactic, and users have run into issues so often, there are quite a few resources already available. Because they detail some of the history behind closures as well as some of the specific instances of closure leaks we'll check those out after applying the closure model to our circular reference diagram and figuring out where these extra references are coming from.</p>
										<p>
												<img height="525" alt="Figure 2 Circular References with Closures" src="http://msdn.microsoft.com/library/en-us/ietechcol/dnwebgen/ie_leak_patterns_fig02.gif" width="413" border="0" />
										</p>
										<p>
												<b>Figure 2. Circular References with Closures</b>
										</p>
										<p>With normal circular references there were two solid objects holding references to each other, but closures are different. Rather than make the references directly, they are made instead by importing information from their parent function's scope. Normally, a function's local variables and the parameters used when calling a function only exist for the lifetime of the function itself. With closures, these variables and parameters continue to have an outstanding reference as long as the closure is alive, and since closures can live beyond the lifetime of their parent function so can any of the locals and parameters in that function. In the example, Parameter 1 would normally be released as soon as the function call was over. Because we've added a closure, a second reference is made, and that second reference won't be released until the closure is also released. If you happened to attach the closure to an event, then you would have to detach it from that event. If you happened to attach the closure to an expando then you would need to null that expando.</p>
										<p>Closures are also created per call, so calling this function twice will create two individual closures, each holding references to the parameters passed in each time. Because of this transparent nature it is really easy to leak closures. The following example provides the most basic of leaks using closures:</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function AttachEvents(element)
        {
            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", ClickEventHandler);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
        }
        &lt;/script&gt;
    &lt;/head\&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
										</pre>
										<p>If you are wondering how to break this leak, it won't be as easy as a normal circular reference. The "closure" can be viewed as a temporary object that exists in the function scope. Once the function exits, you lose reference to the closure itself, so what would you end up calling <b>detachEvent</b> with? One of the most interesting approaches to this problem was demonstrated on <a href="http://spaces.msn.com/members/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry">MSN spaces thanks to Scott Isaacs</a>. The approach uses a second closure to additionally hook the window's <b>onUnload</b> event, and because this closure has the same "scoped" objects it is able to detach the event, detach itself, and finish the clean up process. To make everything easily fit with our model we can also store the closure on an expando, detach it, and then null the expando, as in the following example.</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function AttachEvents(element)
        {
            // In order to remove this we need to put
            // it somewhere. Creates another ref
            element.expandoClick = ClickEventHandler;

            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", element.expandoClick);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").detachEvent("onclick",
                document.getElementById("LeakedDiv").expandoClick);
            document.getElementById("LeakedDiv").expandoClick = null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
										</pre>
										<p>In a <a href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;830555">Knowledge Base article</a>, we actually recommend that you try not to use closures unless they are necessary. In the example, I've given we don't need to use a closure as the event handler, instead we can move the closure to a global scope. When the closure becomes a function, it no longer inherits the parameters or local variables from its parent function so we don't have to worry about closure-based circular references at all. Most code can be fixed by creating an architecture that doesn't rely on closures where they aren't necessary.</p>
										<p>Finally, Eric Lippert, one of the developers of the scripting engines, has a <a href="http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx">great post on closures in general</a>. His final recommendations are also along the lines of only using closures when truly necessary. While his article doesn't mention any of the workarounds for the closure pattern, hopefully we've covered enough examples here to get you started.</p>
										<h2>Cross-Page Leaks</h2>
										<p>Leaks that are based on order of insertion are almost always caused by the creation of intermediate objects that don't get cleaned up properly. That is exactly the case when creating dynamic elements and then attaching them to the DOM. The basic pattern is attaching two dynamically created objects together temporarily which creates a scope from the child to the parent element. Later, when you attach this two-element tree to the primary tree, they both inherit the scope of the document and a temporary object is leaked. The following diagram shows two methods for attaching dynamically created elements to the tree. In the first model, attach each child element to its parent, and finally attach the entire subtree to the primary tree. This method can cause leaks through temporary objects if other conditions are met. In the second model, we attach elements into the primary tree working our way from top-level dynamically created element down through all of the children. Because each attachment inherits the scope of the primary document we never generate temporary scopes. This method is much better at avoiding potential memory leaks.</p>
										<p>
												<img height="379" alt="Figure 3 DOM Insertion Order Leak Model" src="http://msdn.microsoft.com/library/en-us/ietechcol/dnwebgen/ie_leak_patterns_fig03.gif" width="417" border="0" />
										</p>
										<p>
												<b>Figure 3. DOM Insertion Order Leak Model</b>
										</p>
										<p>Next, we are going to cover an example of a leak that is transparent to most leak-detection algorithms. Because we don't leak any publicly visible elements and the objects we leak are very small you might never notice this problem. For our example to work, the dynamically created elements will have to contain a script pointer in the form of an inline function. This will allow us to leak an internal script object that is created temporarily as we attach elements together. Because the leak is small, we'll have to run thousands of samples. In fact, the objects leaked are only a few bytes. By running the sample and navigating to an empty page, you can see the difference in memory consumption between the two versions. When we use the first DOM model of attaching child to parent, then parent to the primary tree, our memory usage goes up a bit. This is a cross-navigation leak and the memory isn't reclaimed until you restart the IE process. If you run the sample a few more times, using the second DOM model of attaching the parent to the primary tree and then the child to the parent, your memory won't continue to climb and you'll find that you've fixed the cross-page navigation leak.</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function LeakMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                var parentDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");
                var childDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");

                // This will leak a temporary object
                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }


        function CleanMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                var parentDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");
                var childDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");

                // Changing the order is important, this won't leak
                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;button onclick="LeakMemory()"&gt;Memory Leaking Insert&lt;/button&gt;
        &lt;button onclick="CleanMemory()"&gt;Clean Insert&lt;/button&gt;
        &lt;div id="hostElement"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
										</pre>
										<p>This leak deserves clarification, because our workaround goes against some best practices in IE. The key points to understand about the leak are that DOM elements are being created with scripts already attached. This is actually crucial to the leak, because if we create DOM elements that don't contain any script and attach them together in the same manner we don't have a leak problem. This gives rise to a second workaround that might be even better for larger subtrees (in the example we only have two elements, so building the tree off the primary DOM isn't a performance hit). The second workaround would be to create your elements with no scripts attached initially so that you can safely build your subtree. After you've attached your subtree to the primary DOM, go back and wire up any script events at that point. Remember to follow the principles for circular references and closures so you don't cause a different leak in your code as you hook up your events.</p>
										<p>I really wanted to point out this issue because it shows that not all memory leaks are easy to find. It could take thousands of iterations of a smaller pattern to become visible, and it might be something slight, like the order of insertion of DOM elements that causes the problem to arise. If you tend to program using only best practices, then you think you are safe, but this leak shows that even best practices can exhibit leaks. Our solution here was to improve upon the best practice or even introduce a new best practice in order to remove the leaking condition.</p>
										<h2>Pseudo-Leaks</h2>
										<p>Often times the actual behavior and expected behavior of some APIs can lead you to misdiagnose memory leaks. Pseudo-leaks almost always appear on the same page during dynamic scripting operations and should rarely be visible after navigation away from the page to a blank page. That is how you can eliminate the issue as a cross-page leak and then start to work on whether the memory consumption is expected. We'll use script text rewriting as our example of a pseudo-leak.</p>
										<p>Like the DOM Insertion Order issue, this issue also relies on the creation of temporary objects in order to "leak" memory. By rewriting the script text inside of a script element over and over again, slowly you'll begin to leak various script engine objects that were attached to the previous contents. In particular, objects related to debugging script are left behind as are fully formed code elements.</p>
										<pre>
												<code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function LeakMemory()
        {
            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                hostElement.text = "function foo() { }";
            }
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;button onclick="LeakMemory()"&gt;Memory Leaking Insert&lt;/button&gt;
        &lt;script id="hostElement"&gt;function foo() { }&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;</code>
										</pre>
										<p>If you run the above code and use the Task Manager trick again, while navigating between the "leaking" page and a blank page, you won't notice a script leak. This script leak is entirely within a page and when you navigate away then you get your memory back. The reason this one is bad is due to expected behavior. You expect that after rewriting some script that the original script won't stay around. But it really has to, because it might have been used already for event attachments and there might be outstanding reference counts. As you can see, this is a pseudo-leak. On the surface the amount of memory consumption looks really bad, but there is a completely valid reason.</p>
										<h2>Conclusion</h2>
										<p>Every Web developer builds a personal list of code examples that they know leak and learns to work around those leaks when they see them in code. This is extremely handy and is the reason the Web is relatively leak-free today. Thinking about the leaks in terms of patterns instead of individual code examples, you can start to develop even better strategies for dealing with them. The idea is to take them into account during the design phase and make sure you have plans for any potential leaks. Use defensive coding practices and assume that you'll need to clean up all your own memory. While this is an overstatement of the problem, you very rarely need to clean up your own memory; it becomes obvious which variables and expando properties have the potential for leaking.</p>
										<p>In the interest of patterns and design I highly recommend <a href="http://spaces.msn.com/members/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry">Scott's short blog entry</a> because it demonstrates a general purpose example of removing all closure-based leaks. It does require a bit more code, but the practice is sound and the improved pattern is easy to spot in code and to debug. Similar registration schemes can be used for expando-based circular references as long as care is taken that the registration method itself isn't riddled with leaks (especially where closures are used)!</p>
										<p>
										</p>
										<p>
										</p>
										<hr noshade="" size="1" />
										<b>About the author</b>
										<p>
												<b>Justin Rogers</b> recently joined the Internet Explorer team as an Object Model developer working on extensibility and previously worked on such notable projects as the .NET QuickStart Tutorials, .NET Terrarium, and SQL Reporting Services Management Studio in SQL Server 2005.</p>
										<div>
										</div>
										<hr size="1" />
										<br />   
<p><!-- End Content --></p></td>
						</tr>
				</tbody>
		</table>
		<br style="OVERFLOW: hidden; LINE-HEIGHT: 1px" clear="all" />
		<table id="msviFooter" cellspacing="0" cellpadding="0" width="100%">
				<tbody>
						<tr valign="bottom">
								<td id="msviFooter2" style="FILTER: ">
										<div id="msviLocalFooter">
												<nobr>
														<a href="http://go.microsoft.com/?linkid=317027">Manage Your Profile</a> |</nobr>
												<wbr>
														<nobr>
																<a href="http://msdn.microsoft.com/isapi/gomscom.asp?target=/legal/" target="_parent">Legal</a> |</nobr>
														<wbr>
																<nobr>
																		<a href="http://go.microsoft.com/?linkid=2028439" target="_parent">Contact Us</a> |</nobr>
																<wbr>
																		<nobr>
																				<a href="http://msdn.microsoft.com/flash/" target="_parent">MSDN Flash Newsletter</a>
																		</nobr>
																</wbr>
														</wbr>
												</wbr>
										</div>
										<div id="msviGlobalFooter">
												<span dir="ltr">© 2006 Microsoft Corporation. All rights reserved. </span>
												<nobr>
														<a href="http://www.microsoft.com/info/cpyright.mspx">Terms of Use</a> |</nobr>
												<wbr>
														<nobr>
																<a href="http://msdn.microsoft.com/library/toolbar/3.0/trademarks/en-us.mspx">Trademarks</a> |</nobr>
														<wbr>
																<nobr>
																		<a href="http://www.microsoft.com/info/privacy.mspx">Privacy Statement</a>
																</nobr>
														</wbr>
												</wbr>
										</div>
								</td>
								<td width="105" bgcolor="#669aff">
										<img title="" height="29" alt="Microsoft" src="http://msdn.microsoft.com/library/toolbar/3.0/text.aspx?t=TQ%3d%3d&amp;f=FFFFFF&amp;b=669AFF&amp;font=Microsoft+Logo+95%2c+13pt&amp;w=105&amp;h=29&amp;a=0&amp;l=0&amp;v=0&amp;c=eAdQAhJgwJihw2DKZGDGx4FnKIM%3d" width="105" border="0" />
								</td>
						</tr>
				</tbody>
		</table>
		<script language="javascript"><![CDATA[ar msviFooter2;if (document.getElementById){msviFooter2 = document.getElementById("msviFooter2");msviFooter2.style.filter = "";}]]&gt;</script>
		<table style="WIDTH: 677px; ; WIDTH: expression(msviFooter2.offsetWidth); HEIGHT: 58px; ; HEIGHT: expression(msviFooter2.offsetHeight+1)" height="58" cellspacing="0" cellpadding="0" width="100%">
				<tbody>
						<tr valign="top">
								<td>
										<div style="WIDTH: 200px">
										</div>
								</td>
								<td style="FILTER: progid:DXImageTransform.Microsoft.Gradient(startColorStr='#FFFFFF', endColorStr='#669AFF', gradientType='1')" width="100%">
								</td>
						</tr>
				</tbody>
		</table>
		<script language="javascript"><![CDATA[ooterjs(document);]]&gt;</script>
		<layer visibility="hide">
				<div style="DISPLAY: none">
						<img height="0" hspace="0" src="http://c.microsoft.com/trans_pixel.asp?source=msdn&amp;TYPE=PV&amp;p=library_en-us_ietechcol_dnwebgen_ie_leak&amp;URI=%2flibrary%2ftoolbar%2f3.0%2fasp.aspx%3fmode%3dhead%26c%3d%2fnonlibraryshell.config%26h%3dmsdn%252Emicrosoft%252Ecom%26u%3d%252Flibrary%252Fen%252Dus%252Fietechcol%252Fdnwebgen%252Fie%255Fleak%255Fpatterns%252Easp%26r%3dhttp%253A%252F%252Fmsdn%252Emicrosoft%252Ecom%252Flibrary%252Fshared%252Fdeeptree%252Fasp%252Frightframe%252Easp%253Fdtcfg%253D%252Flibrary%252Fdeeptreeconfig%252Exml%2526url%253D%252Flibrary%252Fen%252Dus%252Fietechcol%252Fdnwebgen%252Fie%255Fleak%255Fpatterns%252Easp%253Fframe%253Dtrue%2526hidetoc%253Dfalse&amp;GUID=1F4FC18C-F71E-47FB-8FC9-612F8EE59C61&amp;r=http%3a%2f%2fmsdn.microsoft.com%2flibrary%2fshared%2fdeeptree%2fasp%2frightframe.asp%3fdtcfg%3d%2flibrary%2fdeeptreeconfig.xml%26url%3d%2flibrary%2fen-us%2fietechcol%2fdnwebgen%2fie_leak_patterns.asp%3fframe%3dtrue%26hidetoc%3dfalse" width="0" border="0" />
				</div>
		</layer>
<img src ="http://www.blogjava.net/BaSaRa/aggbug/49213.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-05-31 11:53 <a href="http://www.blogjava.net/BaSaRa/archive/2006/05/31/49213.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java里面的迭代器模式(Iterator)解释</title><link>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49173.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Wed, 31 May 2006 01:56:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49173.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49173.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/05/31/49173.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49173.html</trackback:ping><description><![CDATA[很多ajax框架都用到了Iterator，类似地实现java的 java.util.Collections 类。一直不理解Iterator的意思，大概看了一下帮助文档：<br /><br /><strong>用Iterator模式实现遍历集合<br /></strong>　<br />　　Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来，从而避免向客户端暴露集合的内部结构。<br /><br />　　例如，如果没有使用Iterator，遍历一个数组的方法是使用索引：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0; i&lt;array.size(); i++) { ... get(i) ... }<br /><br />　　而访问一个链表（LinkedList）又必须使用while循环：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while((e=e.next())!=null) { ... e.data() ... }<br /><br />　　以上两种方法客户端都必须事先知道集合的内部结构，访问代码和集合本身是紧耦合，无法将访问逻辑从集合类和客户端代码中分离出来，每一种集合对应一种遍历方法，客户端代码无法复用。<br /><br />　　更恐怖的是，如果以后需要把ArrayList更换为LinkedList，则原来的客户端代码必须全部重写。<br /><br />　　为解决以上问题，Iterator模式总是用同一种逻辑来遍历集合：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(Iterator it = c.iterater(); it.hasNext(); ) { ... }<br /><br />　　奥秘在于客户端自身不维护遍历集合的&quot;指针&quot;，所有的内部状态（如当前元素位置，是否有下一个元素）都由Iterator来维护，而这个Iterator由集合类通过工厂方法生成，因此，它知道如何遍历整个集合。<br /><br />　　客户端从不直接和集合类打交道，它总是控制Iterator，向它发送&quot;向前&quot;，&quot;向后&quot;，&quot;取当前元素&quot;的命令，就可以间接遍历整个集合。<br /><br /><br />这样看来实现Iterator的目的是降低耦合以及实现统一的遍历模式吧。<br />在JS里面，遍历数组和遍历Object是不一样的，一般数组是 for(i=0; i&lt;length; i++) 这样，Object就要 for in 了，用了Iterator后可以达到写法的一致，就不用管需要遍历的是什么类型对象了。<img src ="http://www.blogjava.net/BaSaRa/aggbug/49173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-05-31 09:56 <a href="http://www.blogjava.net/BaSaRa/archive/2006/05/31/49173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于javascript中的this...</title><link>http://www.blogjava.net/BaSaRa/archive/2006/05/30/49049.html</link><dc:creator>BaSaRa </dc:creator><author>BaSaRa </author><pubDate>Tue, 30 May 2006 08:37:00 GMT</pubDate><guid>http://www.blogjava.net/BaSaRa/archive/2006/05/30/49049.html</guid><wfw:comment>http://www.blogjava.net/BaSaRa/comments/49049.html</wfw:comment><comments>http://www.blogjava.net/BaSaRa/archive/2006/05/30/49049.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/BaSaRa/comments/commentRss/49049.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/BaSaRa/services/trackbacks/49049.html</trackback:ping><description><![CDATA[看了zkybeyond的BLOG里的一篇留言，有这么一段代码：<br /><br />var myObj=new Object(); <br />myObj.message="hello world"; <br />myObj.fun=function(){ <br />alert (this.message); <br /><br />} <br /><br />window.onload=myObj.fun; <br /><br />页面打开时显示什么？hello world? <br /><br />不对，是undefined！！<br /> <br />晕不晕？反正当我真正开始在js中运用OO概念进行编程的时候发现，this所指代的对象竟然和直觉不一致。后来查资料知道，在html事件响应函数中的this都会被替换成触发事件的那个Element！！（这种说法不太严谨，不过意思可以理解，，嘻嘻）所以window.onload的时候调用的fun已经不是myObj的fun了。 <br /><br /> 改一下代码：<br />&lt;script language="JavaScript"&gt;<br />&lt;!--<br />var myObj= {};<br />myObj.message="hello world"; <br />myObj.fun=function(){ <br /> alert (this.fun); <br />} <br />window.fun = "test";<br />window.onload=myObj.fun; <br />//--&gt;<br />&lt;/script&gt;<br /><br />。。。有点晕吧<br /><img src ="http://www.blogjava.net/BaSaRa/aggbug/49049.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/BaSaRa/" target="_blank">BaSaRa </a> 2006-05-30 16:37 <a href="http://www.blogjava.net/BaSaRa/archive/2006/05/30/49049.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>