<?xml version="1.0" encoding="gb2312"?>
<rss version="2.0">
<channel>
<title><![CDATA[漂亮的疯子]]></title>
        <image>
        <title>http://hi.baidu.com</title>
        <link>http://hi.baidu.com</link>
        <url>http://img.baidu.com/img/logo-hi.gif</url>
        </image>
<description><![CDATA[没有永远，只有更远！]]></description>
<link>http://hi.baidu.com/shulin2008cn</link>
<language>zh-cn</language>
<generator>www.baidu.com</generator>
<ttl>5</ttl>


<item>
        <title><![CDATA[发布一个基于jQ的图片无缝滚动的plugin]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/31d58a23c0b9674ead34de15.html]]></link>
        <description><![CDATA[
		
		<font color="#666666"><font color="#20124d">目前还有个小小个bug，仍有待优化，但基本可以在项目中使用，有时间在完善！<br>
此插件支持多个滚动元素，可配置项如下：<br>
</font>/**************************************************************************<br>
***************************************************************************<br>
*anthor&#160; zhaoyuanxu 'at' vip.qq.com<br>
* @example<br>
* $('#example').jMarquee({<br>
*&#160;&#160;&#160;&#160;&#160;&#160;&#160; next : &quot;next&quot;,<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;prev : &quot;prev&quot;&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
*&#160; })<br>
*<br>
*jMarquee options参数可配置项：<br>
*&#160;&#160; next : 字符串&#160; 下翻页的className ；<br>
*&#160;&#160; prev : 字符串&#160; 上翻页的className ；<br>
*&#160;&#160; auto : 布尔值&#160; true为自动滚动，false为手动滚动， 默认true ；<br>
*&#160; pause : 布尔值&#160; true支持暂停功能，false为不支持， 默认false (暂时不可用)；<br>
* scroll : 数字&#160;&#160;&#160; 设置每次滚动元素的个数(默认滚动所有可见部分)<br>
*&#160; speed : 数字&#160;&#160;&#160; 设置每次滚动动画执行时间(单位毫秒， 默认为200)；<br>
*&#160;&#160; time : 数字&#160;&#160;&#160; 设置每次动画执行间隔时间(单位毫秒， 默认为2000)；<br>
***************************************************************************<br>
*完整的html代码结构：<br>
*&lt;div id='example'&gt;<br>
*&#160;&#160;&#160; &lt;div class='scroll'&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&lt;ul&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160; &lt;li&gt;&lt;/li&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160; &lt;li&gt;&lt;/li&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160; &lt;li&gt;&lt;/li&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160; &lt;li&gt;&lt;/li&gt;<br>
*&#160;&#160;&#160; &#160;&#160;&#160; &#160;&lt;/ul&gt;<br>
*&#160;&#160;&#160; &lt;/div&gt;<br>
*&#160; &lt;span class=&quot;prev&quot;&gt;前一个&lt;/span&gt; <br>
*&#160; &lt;span class=&quot;next&quot;&gt;下一个&lt;/span&gt;<br>
*&#160; &lt;span class=&quot;pause&quot;&gt;&lt;img src=&quot;#&quot;&gt;&lt;/span&gt;<br>
*&lt;/div&gt;<br>
***************************************************************************<br>
***************************************************************************/</font><br>
;(function($){<br>
$.fn.extend({<br>
jMarquee : function (options){<br>
var settings = {<br>
next : 'prev',<br>
prev : 'next',<br>
auto : true,<br>
pause : false,<br>
scroll : null,<br>
speed : 200,<br>
time : 3000<br>
};<br>
var options = $.extend(settings, options);<br>
$(this).each(function(){<br>
var timer;<br>
var status = true;<br>
var $this = $(this);<br>
var $wrap = $('div.scroll', $this);<br>
var $parent = $('li', $wrap).parent();<br>
var number = Math.floor($wrap.width() / $('li', $wrap).outerWidth());&#160;&#160;&#160; <br>
if(options.scroll){<br>
number = options.scroll;&#160;&#160;&#160; &#160; <br>
}&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
var movelang = $('li', $wrap).outerWidth() * number;&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
$wrap.css('overflow', 'hidden');<br>
$parent.css('width', $wrap.width()*2 + 'px');&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
function startScrollLeft() {<br>
if(status){<br>
status = false;<br>
$parent.animate({marginLeft:-movelang}, options.speed, function() {<br>
var $tempwrap = $('li', $wrap).slice(0, number);<br>
$parent.append($tempwrap);&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160; <br>
$parent.css('marginLeft', 0);<br>
status = true;<br>
});&#160;&#160;&#160; &#160;&#160;&#160; <br>
}&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
}<br>
function startScrollRight() {<br>
if(status){<br>
var $tempwrap = $('li', $wrap).slice(-number);<br>
status = false;<br>
$parent.prepend($tempwrap);<br>
$parent.css('marginLeft', -movelang);&#160;&#160;&#160; &#160;&#160;&#160; <br>
$parent.animate({marginLeft:0}, options.speed, function() {<br>
status = true;<br>
});&#160;&#160;&#160; <br>
}&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; <br>
}<br>
<br>
function stopScroll() {&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
clearInterval(timer);<br>
}<br>
<br>
function autoPlay() {&#160;&#160;&#160; <br>
timer = setInterval(startScrollLeft,options.time);<br>
}<br>
if(options.auto){&#160;&#160;&#160; <br>
$wrap.hover(function() {<br>
stopScroll(); <br>
},function() {<br>
autoPlay(); <br>
});<br>
$('.' + options.prev, $this).hover(function() {&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
stopScroll();<br>
$(this).css('opacity', .8);<br>
},function() {<br>
autoPlay();<br>
$(this).css('opacity', 1);<br>
});<br>
$('.' + options.next, $this).hover(function() {<br>
stopScroll();<br>
$(this).css('opacity', .8);<br>
},function() {<br>
autoPlay();<br>
$(this).css('opacity', 1);<br>
});<br>
<br>
autoPlay();<br>
}<br>
if(options.pause){<br>
$('.' + options.pause, $this).toggle(function() {<br>
clearInterval(timer);<br>
$(this).find('img').replaceWith('&lt;img src=&quot;#&quot; alt=&quot;play&quot;/&gt;');<br>
}),function() {<br>
timer = setInterval(startScrollLeft,options.time);&#160; <br>
$(this).find('img').replaceWith('&lt;img src=&quot;#&quot; alt=&quot;pause&quot;/&gt;');<br>
}<br>
}<br>
$('.' + options.prev, $this).click(startScrollRight);<br>
$('.' + options.next, $this).click(startScrollLeft);&#160;&#160;&#160; <br>
});<br>
}//end scroll&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;<br>
<br>
});&#160;&#160; <br>
<br>
})(jQuery); 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/31d58a23c0b9674ead34de15.html#comment">查看评论</a>]]></description>
        <pubDate>2009年11月23日 星期一  10:40</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/31d58a23c0b9674ead34de15.html</guid>
</item>

<item>
        <title><![CDATA[reflow]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/ba96bfc2537a84110ef47714.html]]></link>
        <description><![CDATA[
		
		<div>Yahoo!性能工程师Nicole Sullivan写了一篇非常值得一读的<a href="http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-%20-slow/" title="分析Reflow和Repaint的文章">分析Reflow和Repaint的文章</a>。</div>
<br>
<div>repaint(重绘)是在一个元素的外观被改变，但没有改变布局的情况下发生，如改变visibility、outline、前景色。</div>
<div>&quot;According to<span> </span><a href="http://dev.opera.com/articles/view/efficient-%20/?page=3#reflow" title="Opera">Opera</a><span> </span>, repaint is expensive because the browser must verify the visibility of all other nodes in the DOM tree.&quot;</div>
<div>当repaint发生时，浏览器会验证DOM树上的所有其它结点的visibility属性。</div>
<div> </div>
<div>reflow(回流)是导致DOM脚本执行低效的关键因素之一。页面上任何一个结点触发reflow，都会导致它的子结点及祖先结点重新渲染。Nicole举了个例子：</div>
<div>&lt;body&gt;</div>
<div>&lt;div class=”error”&gt;</div>
<div>&lt;h4&gt;My Module&lt;/h4&gt;</div>
<div>&lt;p&gt;&lt;strong&gt;Error:&lt;/strong&gt;Description of the error…&lt;/p&gt;</div>
<div>&lt;h5&gt;Corrective action required:&lt;/h5&gt;</div>
<div>&lt;ol&gt;</div>
<div>&lt;li&gt;Step one&lt;/li&gt;</div>
<div>&lt;li&gt;Step two&lt;/li&gt;</div>
<div>&lt;/ol&gt;</div>
<div>&lt;/div&gt;</div>
<div>&lt;/body&gt;</div>
<div>当p结点上发生reflow，div.error和body也会重新渲染，甚至h5和ol也会受到影响。</div>
<div> </div>
<div>Nicole总结了在哪些情况下会导致reflow发生：</div>
<div>
<ul>
    <li>改变窗囗大小</li>
    <li>改变文字大小</li>
    <li>添加/删除样式表</li>
    <li>内容的改变，如用户在输入框中敲字(这样也会-_-||)</li>
    <li>激活伪类，如:hover (IE里是一个兄弟结点的伪类被激活)</li>
    <li>操作class属性</li>
    <li>脚本操作DOM</li>
    <li>计算offsetWidth和offsetHeight</li>
    <li>设置style属性</li>
</ul>
</div>
<div> </div>
<div>reflow是不可避免的，只能将reflow对性能的影响减到最小。Nicole提出6点建议：</div>
<ol>
    <li>Change classes on the element you wish to style (as low in the dom tree as possible)<br>
    尽可能限制reflow的影响范围。以上面的代码为例，要改变p的样式，class不要加在div上，通过父级元素影响子元素不好。最好直接加在p上。</li>
    <li>Avoid setting multiple inline styles <br>
    通过设置style属性改变结点样式的话，每设置一次都会导致一次reflow。所以最好通过设置class的方式。</li>
    <li>Apply animations to elements that are position fixed or absolute <br>
    实现元素的动画，它的position属性应当设为fixed或absolute，这样不会影响其它元素的布局。</li>
    <li>Trade smoothness for speed <br>
    权衡速度的平滑。比如实现一个动画，以1个像素为单位移动这样最平滑，但reflow就会过于频繁，CPU很快就会被完全占用。如果以3个像素为单位移动就会好很多。</li>
    <li>Avoid tables for layout <br>
    不要用tables布局的另一个原因就是tables中某个元素一旦触发reflow就会导致table里所有的其它元素reflow。在适合用 table的场合，可以设置table-layout为auto或fixed，这样可以让table一行一行的渲染，这种做法也是为了限制reflow的 影响范围。</li>
    <li>Avoid JavaScript expressions in the CSS (IE only)<br>
    很多情况下都会触发reflow，如果css里有expression，每次都会重新计算一遍。</li>
</ol>
<h3> </h3>
<h3><font size="3" face="宋体">从渲染过程上来讲，mozilla有过CSS的书写建议：</font></h3>
<dl><dt>1.显示样式  </dt><dd>display/position/float/clear  </dd><dt>2.自身样式  </dt><dd>width/height/margin/padding/border/background  </dd><dt>3.内容样式  </dt><dd>line-height/text-align/font系列（font-size/font-weight）/color/text-decoration/vitical-align </dd></dl> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/xhtml%2Bcss">xhtml+css</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/ba96bfc2537a84110ef47714.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月14日 星期三  18:08</pubDate>
        <category><![CDATA[xhtml+css]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/ba96bfc2537a84110ef47714.html</guid>
</item>

<item>
        <title><![CDATA[ie下背景图片定位底部对齐的bug！]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/91ad35dd74002fd38d1029bd.html]]></link>
        <description><![CDATA[
		
		问题：在做圆角的时候，也许会用到一个独立的空标签来放置圆角的背景图片background-position: left bottom;<br>
如果这个图片或者放置图片的标签的高度很小，那么在IE6下你可能会看不到这个图片。<br>
<br>
答案：font-size:0<br>
<br>
注解：体会吧 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/xhtml%2Bcss">xhtml+css</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/91ad35dd74002fd38d1029bd.html#comment">查看评论</a>]]></description>
        <pubDate>2009年10月13日 星期二  17:27</pubDate>
        <category><![CDATA[xhtml+css]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/91ad35dd74002fd38d1029bd.html</guid>
</item>

<item>
        <title><![CDATA[免费使用google的javascript CDN]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/10f7fbfeeb4265385c600817.html]]></link>
        <description><![CDATA[
		
		<div class="content">
<p>转：<a href="http://www.koyoz.com/blog/?action=show&amp;id=212" target="_blank">http://www.koyoz.com/blog/?action=show&amp;id=212</a></p>
<p>说javascript的CDN,概念是有点大.</p>
<p>但是google给我们提供了热门Javascript Framework 的Host, 由于使用<a href="http://baike.baidu.com/view/21895.htm" target="_blank">CDN</a>(Content Delivery Network), 世界任何一个地方都能很快的访问到,并且默认是gzip输出,各种优化细节google都帮你做好了.</p>
<p>目前支持的库有:</p>
<ul>
    <li>
    <div><font color="#339966">jQuery</font></div>
    </li>
    <li>
    <div><font color="#339966">jQuery UI</font></div>
    </li>
    <li>
    <div><font color="#339966">Prototype</font></div>
    </li>
    <li>
    <div><font color="#339966">script_aculo_us</font></div>
    </li>
    <li>
    <div><font color="#339966">MooTools</font></div>
    </li>
    <li>
    <div><font color="#339966">Dojo</font></div>
    </li>
    <li>
    <div><font color="#339966">SWFObjectNew!</font></div>
    </li>
    <li>
    <div><font color="#339966">Yahoo! User Interface Library (YUI)New!</font>&#160;</div>
    </li>
</ul>
<p>载入方式:</p>
<p>jQuery:&#160;</p>
<div class="codeText">
<div class="codeHead">XML/HTML代码</div>
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">script</span><span>&#160;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;text/javascript&quot;</span><span>&#160;</span><span class="attribute">src</span><span>=</span><span class="attribute-value">&quot;http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js&quot;</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">script</span><span class="tag">&gt;</span><span>&#160;&#160;</span></span></li>
</ol>
</div>
<p>Prototype:</p>
<div class="codeText">
<div class="codeHead">XML/HTML代码</div>
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">script</span><span>&#160;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;text/javascript&quot;</span><span>&#160;</span><span class="attribute">src</span><span>=</span><span class="attribute-value">&quot;http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.3/prototype.js&quot;</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">script</span><span class="tag">&gt;</span><span>&#160;&#160;</span></span></li>
</ol>
</div>
<p>也可以使用google.load的方式来载入:</p>
<div class="codeText">
<div class="codeHead">XML/HTML代码</div>
<ol class="dp-xml">
    <li class="alt"><span><span class="tag">&lt;</span><span class="tag-name">script</span><span>&#160;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;text/javascript&quot;</span><span>&#160;</span><span class="attribute">src</span><span>=</span><span class="attribute-value">&quot;http://www.google.com/jsapi&quot;</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">script</span><span class="tag">&gt;</span><span>&#160;&#160;&#160;&#160;&#160; &#160;&#160;</span></span></li>
    <li><span class="tag">&lt;</span><span class="tag-name">script</span><span>&#160;</span><span class="attribute">type</span><span>=</span><span class="attribute-value">&quot;text/javascript&quot;</span><span class="tag">&gt;</span><span>&#160;&#160;&#160;&#160;&#160; &#160;&#160;</span></li>
    <li class="alt"><span>google.load(&quot;jquery&quot;,&#160;&quot;1.3.0&quot;);&#160;&#160;&#160;&#160;&#160; &#160;&#160;</span></li>
    <li><span class="tag">&lt;/</span><span class="tag-name">script</span><span class="tag">&gt;</span><span>&#160;&#160;&#160;</span></li>
</ol>
</div>
<p>嘿嘿,如此高效方便,以后网站的JS库就用google的了</p>
<p>google官方网站:<a href="http://code.google.com/intl/zh-CN/apis/ajaxlibs/" target="_blank">http://code.google.com/intl/zh-CN/apis/ajaxlibs/</a></p>
</div> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/10f7fbfeeb4265385c600817.html#comment">查看评论</a>]]></description>
        <pubDate>2009年08月27日 星期四  11:32</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/10f7fbfeeb4265385c600817.html</guid>
</item>

<item>
        <title><![CDATA[JavaScript--正则表达式]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/c6f0a911ea622e77ca80c419.html]]></link>
        <description><![CDATA[
		
		JavaScript--正则表达式<br>
正则表达式(regular expression)对象包含一个正则表达式模式(pattern)。它具有用正则表达式模式去匹&#160; 配或代替一个串(string)中特定字符(或字符集合)的属性(properties)和方法(methods)。<br>
正则表达式构造函数： new RegExp(&quot;pattern&quot;[,&quot;flags&quot;]); <br>
参数说明： <br>
pattern -- 一个正则表达式文本 <br>
flags -- 如果存在，将是以下值：<br>
g: 全局匹配<br>
i: 忽略大小写 <br>
gi: 以上组合<br>
在构造函数中，一些特殊字符需要进行转意(在特殊字符前加&quot;\&quot;)。正则表达式中的特殊字符： 字符&#160; 含意<br>
\ 转意，即通常在&quot;\&quot;后面的字符不按原来意义解释，如/b/匹配字符&quot;b&quot;，当b前面加了反斜杆后/\b/，转意为&#160; 匹配一个单词的边界。<br>
-或-<br>
对正则表达式功能字符的还原，如&quot;*&quot;匹配它前面元字符0次或多次，/a*/将匹配a,aa,aaa，加了&quot;\&quot;后，/a\*/&#160; 将只匹配&quot;a*&quot;。 <br>
^&#160; 匹配一个输入或一行的开头，<br>
/^a/匹配&quot;an A&quot;，而不匹配&quot;An a&quot;&#160; <br>
$&#160; 匹配一个输入或一行的结尾，<br>
/a$/匹配&quot;An a&quot;，而不匹配&quot;an A&quot;&#160; <br>
*&#160; 匹配前面元字符0次或多次，<br>
/ba*/将匹配b,ba,baa,baaa&#160; <br>
+&#160; 匹配前面元字符1次或多次，<br>
/ba*/将匹配ba,baa,baaa&#160; <br>
?&#160; 匹配前面元字符0次或1次，<br>
/ba*/将匹配b,ba&#160; <br>
(x)&#160; 匹配x保存x在名为$1...$9的变量中&#160; <br>
x|y&#160; 匹配x或y&#160; <br>
{n}&#160; 精确匹配n次&#160; <br>
{n,}&#160; 匹配n次以上&#160; <br>
{n,m}&#160; 匹配n-m次&#160; <br>
[xyz]&#160; 字符集(character set)，匹配这个集合中的任一一个字符(或元字符)&#160; <br>
[^xyz]&#160; 不匹配这个集合中的任何一个字符&#160; <br>
[\b]&#160; 匹配一个退格符 <br>
\b&#160; 匹配一个单词的边界&#160; <br>
\B&#160; 匹配一个单词的非边界<br>
\cX&#160; 这儿，X是一个控制符，<br>
/\cM/匹配Ctrl-M&#160; <br>
\d&#160; 匹配一个字数字符，<br>
/\d/ = /[0-9]/&#160; \D&#160; 匹配一个非字数字符，<br>
/\D/ = /[^0-9]/&#160; \n&#160; 匹配一个换行符 <br>
\r&#160; 匹配一个回车符&#160; <br>
\s&#160; 匹配一个空白字符，包括\n,\r,\f,\t,\v等&#160; <br>
\S&#160; 匹配一个非空白字符，等于/[^\n\f\r\t\v]/&#160; <br>
\t&#160; 匹配一个制表符&#160; \v&#160; 匹配一个重直制表符&#160; <br>
\w&#160; 匹配一个可以组成单词的字符(alphanumeric，这是我的意译，含数字)，包括下划线，如[\w]匹配&quot;$5.98&quot;&#160; 中的5，等于[a-zA-Z0-9]&#160; <br>
\W&#160; 匹配一个不可以组成单词的字符，如[\W]匹配&quot;$5.98&quot;中的$，等于[^a-zA-Z0-9]。<br>
说了这么多了，我们来看一些正则表达式的实际应用的例子： HTML代码的屏蔽&#160; function mask_HTMLCode(strInput) {&#160;&#160;&#160; var myReg = /&lt;(\w+)&gt;/;&#160;&#160;&#160; return strInput.replace(myReg, &quot;&amp;lt;$1&amp;gt;&quot;);&#160; } E-mail地址验证:&#160; function test_email(strEmail) {&#160;&#160; var myReg = /^[_a-z0-9]+@([_a-z0-9]+\.)+[a-z0-9]{2,3}$/;&#160;&#160; if(myReg.test(strEmail)) return true;&#160;&#160; return false;&#160; }&#160; 正则表达式对象的属性及方法：<br>
预定义的正则表达式拥有有以下静态属性：input, multiline, lastMatch, lastParen, leftContext,&#160; rightContext和$1到$9。其中input和multiline可以预设置。其他属性的值在执行过exec或test方法后被根据&#160; 不同条件赋以不同的值。许多属性同时拥有长和短(perl风格)的两个名字，并且，这两个名字指向同一个值。(&#160; JavaScript模拟perl的正则表达式)&#160; 正则表达式对象的属性： 属性 含义 <br>
$1...$9 如果它(们)存在，是匹配到的子串 <br>
$_&#160;&#160; 参见input&#160; <br>
$* 参见multiline&#160; <br>
$&amp; 参见lastMatch&#160; <br>
$+ 参见lastParen&#160; <br>
$` 参见leftContext&#160; <br>
$''　参见rightContext <br>
constructor:创建一个对象的一个特殊的函数原型<br>
global:是否在整个串中匹配(bool型)<br>
ignoreCase:匹配时是否忽略大小写(bool型) <br>
input:被匹配的串 <br>
lastIndex:最后一次匹配的索引<br>
lastParen:最后一个括号括起来的子串<br>
leftContext:最近一次匹配以左的子串<br>
multiline:是否进行多行匹配(bool型) <br>
prototype:允许附加属性给对象<br>
rightContext:最近一次匹配以右的子串 <br>
source:正则表达式模式<br>
lastIndex:最后一次匹配的索引<br>
<br>
正则表达式对象的方法： 方法 含义<br>
compile&#160;&#160;&#160;&#160; 正则表达式比较<br>
exec&#160;&#160;&#160;&#160;&#160;&#160; 执行查找<br>
test &#160; &#160; &#160;&#160; 进行匹配<br>
toSource&#160;&#160; 返回特定对象的定义(literal&#160; representing)，其值可用来创建一个新的对象。重载Object.toSource方法得到的。<br>
toString　　　　　 返回特定对象的串。重载Object.toString方法得到的。<br>
valueOf　　　　　&#160; 返回特定对象的原始值。重载Object.valueOf方法得到 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/c6f0a911ea622e77ca80c419.html#comment">查看评论</a>]]></description>
        <pubDate>2009年08月07日 星期五  16:10</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/c6f0a911ea622e77ca80c419.html</guid>
</item>

<item>
        <title><![CDATA[CSS.JS文件发布机制的思考（转）]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/a35314b3f1e0d9aed9335ab4.html]]></link>
        <description><![CDATA[
		
		<p style="margin: 0in;  font-size: 10pt;"><strong>CSS.JS文件发布机制的思考</strong></p>
<p style="margin: 0in;  font-size: 10pt;"> </p>
<p style="margin: 0in;  font-size: 10pt;">转自：<a href="http://www.cnblogs.com/nebel/archive/2009/08/03/f2engine_css_js.html" target="_blank">路口</a></p>
<p style="margin: 0in;  font-size: 10pt;"> </p>
<p style="margin: 0in;  font-size: 10pt;">在开发过程中，有时遇到由于缓存问题导致页面不能及时更新，有时页面引入了不必需的样式脚本文件，有时由于文件太多，字节过大导致页面的性能缓慢，为了解决这些问题，个人设想了一个初步的解决方案。</p>
<p style="margin: 0in;  font-size: 10pt;">&#160;</p>
<p style="margin: 0in;  font-size: 10pt;">&#160;</p>
<p style="margin: 0in;  font-size: 10pt;">解决方案如下：</p>
<p style="margin: 0in;  font-size: 10pt;">&#160;</p>
<p style="margin: 0in;  font-size: 10pt;">&#160;</p>
<table height="1055" cellspacing="0" cellpadding="0" border="1" width="904" valign="top" style="border: 1pt solid rgb(163, 163, 163); border-collapse: collapse; direction: ltr;">
    <tbody>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">描述</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">备注</p>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">资源级别</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <p style="margin: 0in;  font-size: 10pt;"><span style=" font-size: 10pt;">页面的资源级别：</span></p>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">全局级（</span><span style=" font-size: 10pt;">Common</span><span style=" font-size: 10pt;">）</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">模块级（</span><span style=" font-size: 10pt;">Module</span><span style=" font-size: 10pt;">）</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">页面级（</span><span style=" font-size: 10pt;">Page</span><span style=" font-size: 10pt;">）</span></li>
            </ol>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">优化方案</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <p style="margin: 0in;  font-size: 10pt;"><span style=" font-size: 10pt;">优化主要从以下几个方面：</span></p>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">减少单个文件的字节大小</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">减少文件的个数（即减少</span><span style=" font-size: 10pt;">http</span><span style=" font-size: 10pt;">请求数）</span>
                <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
                </li>
            </ol>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">其他的优化是从开发技巧上进行的，取决于专业水平</p>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <p style="margin: 0in;  font-size: 10pt;"><span style=" font-size: 10pt;">文件输出方案</span></p>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">合并</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">压缩</span></li>
            </ol>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.286in; font-size: 10pt;">
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">基于资源级别及优化方案，制定以下</span><span style=" font-size: 10pt;">4</span><span style=" font-size: 10pt;">种方案：</span><span style=" font-size: 10pt;"><br>
                </span></p>
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">1、直接引用单个文件依次引入（</span><span style=" font-size: 10pt;">&lt;link/&gt;</span><span style=" font-size: 10pt;">、</span><span style=" font-size: 10pt;">&lt;script/&gt;</span><span style=" font-size: 10pt;">）</span><span style=" font-size: 10pt;"><br>
                </span></p>
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">2、基于</span><span style=" font-size: 10pt;">1</span><span style=" font-size: 10pt;">，进行单个文件压缩</span><span style=" font-size: 10pt;"><br>
                </span></p>
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">3、按照资源级别合并成新的单个文件</span><span style=" font-size: 10pt;"><br>
                </span></p>
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">4、基于</span><span style=" font-size: 10pt;">3</span><span style=" font-size: 10pt;">，进行合并后的文件压缩</span></p>
                <p style="margin: 0in;  font-size: 10pt;"><br>
                <br>
                </p>
            </ol>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">思考点</p>
            <p style="margin: 0in; font-size: 10pt;"><span>方案</span><span>3</span><span>：</span><span> </span><span>如何确定合并的文件个数？</span></p>
            <p style="margin: 0in; font-size: 10pt;"><span><br>
            </span></p>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">缓存问题</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">采用时间戳后缀</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">f2econfig_json</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">配置文件：</p>
            <p style="margin: 0in; font-size: 10pt;"><span>var f2eJson={<br>
            <span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span></span><span>&quot;Version&quot;:&quot;v3&quot;,</span><span>//</span><span>版本</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span>&quot;Update&quot;:&quot;20091015&quot;,</span><span>//</span><span>根据时间戳更新缓存</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span>&quot;Compress&quot;:&quot;</span><span>1</span><span>&quot;,</span><span>//</span><span>文件输出方案（</span><span>1</span><span>，</span><span>2</span><span>，</span><span>3</span><span>，</span><span>4</span><span>）</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span>&quot;</span><span>Common</span><span>&quot;:[</span><span>//</span><span>全站公共样式</span></p>
            <p style="margin: 0in 0in 0in 0.375in;  font-size: 10pt;"><span>&#160; </span>&quot;common/global.css&quot;</p>
            <p style="margin: 0in 0in 0in 0.375in;  font-size: 10pt;">],</p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span>&quot;M</span><span>odule</span><span>&quot;:{ //</span><span>模块及样式</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span><span>&#160;&#160;&#160;&#160;&#160;&#160; </span>&quot;</span><span>模块</span><span>1&quot;:[&quot;product,.css&quot;]</span></p>
            <p style="margin: 0in 0in 0in 0.375in;  font-size: 10pt;">},</p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span>&quot;Page&quot;:{</span><span>//</span><span>每个页面所拥有的样式</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span><span>&#160;&#160;&#160;&#160;&#160;&#160; </span></span><span>&quot;index.php&quot;:[&quot;&quot;</span><span>,</span><span>&quot;sys/index.css&quot;],</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span><span>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; </span>//</span><span>第一个元素存储模块引用名称，无则留空</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span><span>&#160;&#160;&#160;&#160;&#160;&#160; </span></span><span>&quot;search.php&quot;:[&quot;模块</span><span>1</span><span>&quot;,&quot;product/search.css&quot;]</span></p>
            <p style="margin: 0in 0in 0in 0.375in; font-size: 10pt;"><span><span>&#160;&#160;&#160;&#160;&#160;&#160; </span>//</span><span>引用多个模块，用</span><span> </span><span>“，”隔开，比如：</span><span><span>&#160;&#160; </span></span><span>模块</span><span>1</span><span>，模块</span><span>2</span></p>
            <p style="margin: 0in 0in 0in 0.375in;  font-size: 10pt;"><span>&#160;</span>}</p>
            <p style="margin: 0in;  font-size: 10pt;">}</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">php</span><span style=" font-size: 10pt;">有专门的</span><span style=" font-size: 10pt;">json</span><span style=" font-size: 10pt;">转换库</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">js</span><span style=" font-size: 10pt;">的配置结构同</span><span style=" font-size: 10pt;">css</span><span style=" font-size: 10pt;">的配置</span><span style=" font-size: 10pt;">json</span></li>
            </ol>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">f2engine.php</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">&#160;&#160; 1、读取json配置文件，转化成php数组<br>
            2、根据每个页面的资源参数，查找该页面拥有的样式资源<br>
            3、根据文件输出方案，进行处理<br>
            4、在页面上输出</td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">配置文件没有更新的情况下，只解析一次</span><span style=" font-size: 10pt;">json</span><span style=" font-size: 10pt;">为数组</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">只解析一次资源，并将结果保存，供下次直接使用</span>
                <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
                </li>
            </ol>
            </td>
        </tr>
        <tr>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 1.136in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">例子</p>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 5.718in; vertical-align: top;">
            <ol style="margin-top: 0in; unicode-bidi: embed;  direction: ltr; margin-bottom: 0in; margin-left: 0.193in; font-size: 10pt;">
                <p style="margin: 0in; font-size: 10pt;"><span style=" font-size: 10pt;">比如</span><span style=" font-size: 10pt;">search.php</span><span style=" font-size: 10pt;">这个页面的样式引用</span></p>
                <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">根据页面找到页面级资源：</span><span style=" font-size: 10pt;"> </span><span style=" font-size: 10pt;">Page[&quot;search.php&quot;]</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">根据该数组的第一个值查找所引用的模块样式</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">根据配置文件中的“Compress”值确定文件输出方案，并进行处理</span></li>
                <li style="list-style-type: disc; margin-top: 0pt; margin-bottom: 0pt; vertical-align: middle;"><span style=" font-size: 10pt;">在页面上进行输出</span>
                <p style="margin: 0in; font-size: 10pt;"><span>//</span><span>全站样式</span><span> common</span></p>
                <p style="margin: 0in; font-size: 10pt;"><span>&lt;link type=&quot;text/css&quot; href=&quot;</span><span>common/global.pack.css?20091015</span><span>&quot; rel=&quot;stylesheet&quot; /&gt;</span></p>
                <p style="margin: 0in; font-size: 10pt;"><span>//</span><span>模块样式</span><span> module</span></p>
                <p style="margin: 0in; font-size: 10pt;"><span>&lt;link type=&quot;text/css&quot; href=&quot;</span><span>product.pack.css?20091015</span><span>&quot; rel=&quot;stylesheet&quot; /&gt;</span></p>
                <p style="margin: 0in; font-size: 10pt;"><span>//</span><span>页面样式</span><span> page</span></p>
                <p style="margin: 0in; font-size: 10pt;"><span>&lt;link type=&quot;text/css&quot; href=&quot;</span><span>product/serach.pack.css?20091015</span><span>&quot; rel=&quot;stylesheet&quot; /&gt;</span></p>
                <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
                <p style="margin: 0in; font-size: 10pt;"><span>注</span><span>:</span><span>压缩后文件名称变为</span><span><span>&#160;&#160; </span>search.pack.css</span></p>
                <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
                </li>
            </ol>
            </td>
            <td style="border: 1pt solid rgb(163, 163, 163); padding: 4pt; width: 2.945in; vertical-align: top;">
            <p style="margin: 0in;  font-size: 10pt;">&#160;</p>
            </td>
        </tr>
    </tbody>
</table> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/a35314b3f1e0d9aed9335ab4.html#comment">查看评论</a>]]></description>
        <pubDate>2009年08月06日 星期四  18:44</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/a35314b3f1e0d9aed9335ab4.html</guid>
</item>

<item>
        <title><![CDATA[styleFloat的firefox兼容写法]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/64ec266ddfebeff34316947f.html]]></link>
        <description><![CDATA[
		
		styleFloat为IE方法<br>
cssFloat为标准方法<br>
function getFloat(obj){<br>
  if(document.all)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  {obj.style.styleFloat;}<br>
  else<br>
      &nbsp;&nbsp;  { obj.style.cssFloat;}<br>
<br>
<br>
} 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/64ec266ddfebeff34316947f.html#comment">查看评论</a>]]></description>
        <pubDate>2009年04月07日 星期二  23:10</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/64ec266ddfebeff34316947f.html</guid>
</item>

<item>
        <title><![CDATA[IE下奇怪的空格]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/66b7d2ead7387edbd439c965.html]]></link>
        <description><![CDATA[
		
		<br>
var p=' 飞机 ';<br>
var c=' 飞机 ';<br>
alert(p==c);<br>
有时候IE会对这样的ms相等的两个字符串返回为false，尤其是调用外部数据的时候;这些ms没有空格的数据处理时总是给你返回一个意外的结果，不是编码问题，文档声明都一致，罪魁祸首就这些个看不见的&ldquo;空格空格空格呀&rdquo;<br>
假如你不想为它再去写个trim的方法，那么一下会对你有用：<br>
var  reg=/ /g;<br>
var d=c.replace(reg,&quot;&quot;);<br>
var e=p.replace(reg,&quot;&quot;); 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/66b7d2ead7387edbd439c965.html#comment">查看评论</a>]]></description>
        <pubDate>2009年03月30日 星期一  14:29</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/66b7d2ead7387edbd439c965.html</guid>
</item>

<item>
        <title><![CDATA[“e.target || e.srcElement”事件的目标节点的的先后顺序~]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/24daa73ea9de7bf2828b1391.html]]></link>
        <description><![CDATA[
		
		一个奇怪的问题：<br>
var target=e.target || e.srcElement;如果前后颠倒防止 FF下的loader会显示为reload！ 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/24daa73ea9de7bf2828b1391.html#comment">查看评论</a>]]></description>
        <pubDate>2009年03月30日 星期一  14:07</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/24daa73ea9de7bf2828b1391.html</guid>
</item>

<item>
        <title><![CDATA[微软产品因何而败？（译言）]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/8410d3fca2b6d8f5fc037fe6.html]]></link>
        <description><![CDATA[
		
		相比Windows Vista操作系统，为什么有些人更青睐Windows XP和Mac OSX？毕竟，Vista相比XP视觉上更美观圆润，性能上更先进，并且在很多方面也远胜于Mac OSX。为什么那么多人喜欢Xbox，而Windows Mobile则无人问津？<br>
<br>
为什么黑莓用户如此钟爱他们黑莓品牌，但大众却对Palm掌上电脑漠然置之？<br>
<br>
为什么外观朴素、色调沉闷、设计乏善可陈的电子书阅读器Amazon Kindle会如此流行？<br>
<br>
为什么人们喜欢页面简单、外观丑陋的Gmail？<br>
<br>
关于这些问题的答案，大多数制造个人电脑、电玩、消费性电子装置的公司和软件制造商都很困惑。厂家花费数十亿美元用于产品的可用性评测和用户界面设计。但很不幸地是，这些巨资基本都付之东流。<br>
<br>
问题的关键在于产品技术支持方面的专家过于繁多。技术支持只占产品整体设计因素的一半。另一半则是人的因素：缺乏理性，易于冲动，没有耐心，权力饥渴的贪欲机器。<br>
<br>
当你进行调查询问他们真正想要什么时，他们是不会告诉你真相的，因为他们根本就不知道真相。<br>
<br>
  <br>
<br>
用户和产品设计师同样都会谈及用户界面的连贯性、可用性和简易性，以及诸如性能和稳定性之类的系统属性。但他们都没有谈及实现这些属性的方法。问题的关键是用户掌握控制权的生理感受。实现控制这一目的有多种途径：<br>
<br>
连贯性：设计师关注用户界面的&ldquo;连贯性&rdquo;，但为什么呢？连贯性给人以可预测性，这使得用户有这样一种感觉：当他们操作时，他们知道下一步即将出现什么&mdash;&mdash;即使是在第一次操作。这是一种掌握的感觉，是一种控制的感觉。<br>
<br>
可用性：用户是需要自我保护白痴，基于这一假设来设计产品用户界面，这是软件和硬件设计师常犯的一个错误。如果给这些白痴太多的条条框框，按前面的假设，他们就会被束缚起来无法摆脱。但是，如果不采用微软的设计路线&mdash;&mdash;掩埋隐藏这些控制和特征，这虽然可以避免新手造茧自缚，但这同时也严重挫伤了行家里手的积极性&mdash;&mdash; 最好的办法是提供一个防弹性的&ldquo;复原&rdquo;功能。给用户以控制，允许他们犯错，当搞得一团糟的时候，用户可以将混乱局面&ldquo;复原&rdquo;。<br>
<br>
简易性：简易性实现起来是很复杂的。实现这一性能有好多种方法。一种方法是强调自上而下、由内及外的简易性。极端的例子包括最初的Palm Pilot organizer，Gmail和RSS feeds。再一个是简易性的假象，说的正是微软的设计路线。为了努力成为所有人和所有任务操作系统的提供商，微软Windows和Windows Mobile可谓是极其复杂的软件工程作品。为了实现&ldquo;简易化&rdquo;，微软把产品的各个特征隐藏起来，掩盖了控制因素，并把各个特征分门别类，以求创造产品选项较少的表象，但实际上选项并没有减少。（以Windows 7为例，从其所有菜单上来看，它将会提供更多的类似的&ldquo;简易化&rdquo;选项。）这两种极端做法都实现了所谓的&ldquo;简易性&rdquo;这一目标。但一种做法通过赋予控制令用户陶醉不已。另一种做法则通过取消控制令用户苦不堪言。<br>
<br>
性能：每个人都讨厌反应迟钝的电脑。究其根源倒不是人们苦于等待。事实上是因在时钟摇摆的时间内，电脑剥夺了用户的控制权。盯着时钟焦急等待的三秒实际上是你感觉完全无能为力的三秒。反应灵敏的电脑之所以好，是因为它保留了使用者的控制权。<br>
<br>
稳定性：设计师们关注系统&ldquo;稳定性&rdquo;，但这也不是因为他们担心浪费时间，尽管那是使用者对系统缺乏稳定性的托词。如同性能的问题一样，不稳定性是对用户行使系统控制权的窃取。人们在各种事务上都能浪费大量的时间，但人们似乎对此并不介意。但当被别人强行浪费时间时，人们就会恼羞成怒。蓝屏死机就如同开车时不期而遇交通堵塞或有人强行拿走了你的电视遥控器。你被迫等待，留给你的只有无能为力的情绪。<br>
<br>
令人不满的各色产品在全国整个行业流行的原因之一是，整个可用性测评文化不重视用户的控制欲望。例如，微软公司也做产品可用性测评，但其测评是有缺陷的。具有代表性的一例是，微软公司让随机抽查人员坐在可用性测评实验室的一台电脑前，&ldquo;受害人&rdquo;被指导完成各项任务，在努力完成那些任务的同时，还要回答他们正在做什么、正在想什么。所有这些行为都是被监控的，每一项也都要记录在案。<br>
<br>
微软公司的可用性测评倾向于注重能使用户&ldquo;完成目标&rdquo;。微软利用他们经验性的先入之见，根据工作和用户类别，如学生、中层管理者、设计师等，对人们要完成的目标进行分门别类。所以说，微软公司注重结果。而我则认为用户在完成任务过程中的感受才是重中之重。<br>
<br>
  <br>
<br>
此处有个问题。上述微软公司测评情景中，使用者操作的是别人的电脑。他们认为电脑中的软件是受控制的。他们对于这些设备、软件、任务或任何一切都没有心理上的归属感。于是，最重要的元素&mdash;&mdash;人们，在自己的家里、用自己的电脑、做自己的工作时的控制感&mdash;&mdash;在这些测评中消失殆尽。<br>
<br>
在可用性测评过程中，用户不断地被问及关于软件的问题。问那些问题是不对的。在现实中生活中，人们做真实的工作时，他们关注的是自己的期望和目标，他们失落或开心取决于他们所得的满意度。<br>
<br>
我对微软公司的建议是再附加一个测试：谁是控制者？每测试完一项任务，就让用户对他们在此任务中对&ldquo;我是控制者&rdquo;还是&ldquo;软件是控制者&rdquo;两种体验进行打分排名。用尽所有的办法完成各项测评任务后，并从任务中选出&ldquo;我是控制者&rdquo;最高分的那一项。他们还需要家庭版的现实生活中的测评结果。<br>
<br>
当使用电玩、个人电脑、电话和软件时，我们都已经历过各种酸甜苦辣、喜怒哀乐。在这一系列情感中，一端是心醉神迷，因为一些东西发挥了作用；另一端则是怒不可遏。你沉浸在心醉神迷这一端的时间量是你多么喜欢这个产品的决定因素，而且是唯一的决定因素。<br>
<br>
连贯性、可用性、简易性、稳定性、性能，以及成功的完成各项任务，总之，一切和使用电脑有关的因素都要归结为&mdash;&mdash;控制。<br>
<br>
总之，赋予我控制权，我就会喜欢你的产品。就这么简单。 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/%B2%FA%C6%B7">产品</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/8410d3fca2b6d8f5fc037fe6.html#comment">查看评论</a>]]></description>
        <pubDate>2009年03月11日 星期三  14:43</pubDate>
        <category><![CDATA[产品]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/8410d3fca2b6d8f5fc037fe6.html</guid>
</item>

<item>
        <title><![CDATA[仅firefox识别的hack]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/7e1476229d1539ac4623e80e.html]]></link>
        <description><![CDATA[
		
		#box, x:-moz-any-link, x:default { position:relative; padding-left:200px}/*only for ff*/<br>
IE7也能识别=.=! 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/xhtml%2Bcss">xhtml+css</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/7e1476229d1539ac4623e80e.html#comment">查看评论</a>]]></description>
        <pubDate>2009年03月10日 星期二  15:44</pubDate>
        <category><![CDATA[xhtml+css]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/7e1476229d1539ac4623e80e.html</guid>
</item>

<item>
        <title><![CDATA[js拖拽]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/cf1da50974b42f236b60fb85.html]]></link>
        <description><![CDATA[
		
		<pre>&lt;script type=&quot;text/javascript&quot;&gt;<br>//记录当前的拖拽元素<br>var dragElement = null;<br>//4个全局变量，用来记录当前拖拽元素以及鼠标的坐标<br>//由于不可能同时拖拽多个元素，所以不会冲突<br>var mouseY,mouseX,objY,objX;<br>//用于动态更新z-index，确保不会造成不该移动的元素瞎动。<br>var max = 1;<br>//初始化网页，遍历所有的元素，如果元素的class属性为&quot;drag&quot;<br>//则对其进行适当地设置<br>function dragInit(node){<br> if(node.className == &quot;drag&quot;){ <br>  node.onmousedown = down;<br>  document.onmousemove = move;<br>  node.onmouseover = over;<br>  node.style.position = &quot;relative&quot;;<br>  node.dragging = false;<br> }<br> var children = node.childNodes;<br> for(var i = 0;i &lt; children.length; i++){<br>  dragInit(children[i]);<br> }<br>}<br>window.onload = function(){<br> //从document开始遍历<br> dragInit(document);<br> //确保在文档的任何位置将鼠标松开都将导致拖拽停止<br> document.onmouseup = docUp;<br> window.onblur = docUp;<br>}<br>//鼠标按下响应事件<br>function down(event)<br>{ <br> event = event || window.event;<br> //按谁拽谁 <br> dragElement = this;<br> //记录鼠标的当前坐标<br> mouseX = parseInt(event.clientX)<br>+(document.documentElement.scrollLeft || document.body.scrollLeft);<br> mouseY = parseInt(event.clientY)<br>+(document.documentElement.scrollTop || document.body.scrollTop);<br> //记录元素的当前坐标<br> objY = parseInt(getNodeStyle(dragElement,&quot;top&quot;));<br> objX = parseInt(getNodeStyle(dragElement,&quot;left&quot;));<br> //IE不返回未设置的CSS属性<br> if(!objY)objY=0;<br> if(!objX)objX=0;<br> this.style.zIndex = max++;<br>}<br>function move(event){<br> event = event || window.event;<br> if(dragElement){<br>  var x,y;<br>  //y等于鼠标当前y - 记录的鼠标y + 元素y     ，后面的x一样<br>  y = parseInt(event.clientY) <br>+(document.documentElement.scrollTop || document.body.scrollTop) <br>- mouseY + objY;<br>  x = parseInt(event.clientX) <br>+(document.documentElement.scrollLeft || document.body.scrollLeft)<br> - mouseX + objX;<br>  //更新元素的实际显示<br>  dragElement.style.top = y + &quot;px&quot;;<br>  dragElement.style.left = x + &quot;px&quot;;<br>  //更新鼠标坐标和元素坐标的记录<br>  objY=y;<br>  objX=x;<br>  mouseX = parseInt(event.clientX)<br>+(document.documentElement.scrollLeft || document.body.scrollLeft);<br>  mouseY = parseInt(event.clientY)+(<br>document.documentElement.scrollTop || document.body.scrollTop);<br> }<br>}<br>function docUp(){<br> //停止拖拽<br> dragElement = null;<br>}<br>function over(){<br> this.style.cursor = &quot;move&quot;;<br>}<br>//获得元素的坐标<br>function getNodeStyle(node,styleName){<br> var realStyle = null;<br> if(node.currentStyle){<br>  realStyle = node.currentStyle[styleName];<br> }else if(window.getComputedStyle){<br>  realStyle = window.getComputedStyle(node,null)[styleName];<br> }<br> return realStyle;<br>}<br>&lt;/script&gt;</pre> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/cf1da50974b42f236b60fb85.html#comment">查看评论</a>]]></description>
        <pubDate>2009年02月10日 星期二  22:40</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/cf1da50974b42f236b60fb85.html</guid>
</item>

<item>
        <title><![CDATA[js图片轮播效果【原创教程】]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/b0b3d013fb9ea924dd5401b0.html]]></link>
        <description><![CDATA[
		
		以前都是直接改别人的，近日闲来无事就自个写了个，旨在普及下Js教育。<br>
为了方便展示实现的逻辑，我把没个功能都单独写成了一个函数。<br>
<br>
<strong>代码如下：<br>
<br>
</strong><font color="#003366">function $(id){return document.getElementById(id)}//获取ID节点的简介方法<br>
var tags=$(&quot;fd&quot;).getElementsByTagName(&quot;li&quot;);//获取切换按钮节点<br>
var cats=$(&quot;fd&quot;).getElementsByTagName(&quot;p&quot;);//获取切换内容节点<br>
var current;//设置当前帧的变量容器<br>
var timer=3000;//&nbsp;&nbsp;&nbsp;    <br>
function disAll(){//初始所有标签样式<br>
for(var i=0; i&lt;tags.length; i++){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[i].className=&quot;&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[i].className=&quot;&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[i].style.display=&quot;none&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
}<br>
function setNow(){//获取当前帧的索引值<br>
for(var i=0; i&lt;tags.length; i++){<br>
&nbsp;&nbsp;&nbsp;   if(tags[i].className==&quot;now&quot;){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   current=i;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;     } <br>
}<br>
for(var j=0; j&lt;tags.length; j++){//设置手动切换<br>
&nbsp;&nbsp;&nbsp;&nbsp;     tags[j].onmouseover=function(){<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   clearInterval(h);&nbsp;&nbsp;&nbsp;    <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   disAll();&nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   this.className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;     setNow();<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[current].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[current].className=&quot;now&quot;;&nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;     tags[j].onmouseout=function(){<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   setNow();&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   h=setInterval(&quot;goNext()&quot;,3000);<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;   }<br>
function goNext(){//自动切换<br>
&nbsp;&nbsp;   setNow();//获取当前帧索引<br>
&nbsp;&nbsp;   current+=1;//帧自增1<br>
if(current&gt;=parseInt(tags.length)){//判断：如果当前帧索引值是否大于切换按钮总数，如果大于按钮总数则回到初始状态<br>
&nbsp;&nbsp;&nbsp;   current=0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   disAll();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[0].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[0].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[0].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;   else{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   disAll();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[current].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[current].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[current].className=&quot;now&quot;;<br>
&nbsp;&nbsp;   }<br>
}<br>
var h=setInterval(&quot;goNext()&quot;,timer)//开始自动切换</font><br>
<br>
<strong>全部代码：</strong><br>
[html]<br>
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&gt;<br>
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;<br>
&lt;head&gt;<br>
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;<br>
&lt;title&gt;无标题文档&lt;/title&gt;<br>
&lt;style&gt;<br>
p.now{ display:block; border:1px solid #ccc}<br>
li.now{ color:red}<br>
li{ list-style:none;float:left; padding:0 10px; border:1px solid #ccc}<br>
#fd{position:absolute; left:100px; top:100px;height:20px; width:600px; background:#ccc}<br>
&lt;/style&gt;<br>
&lt;/head&gt;<br>
<br>
&lt;body&gt;<br>
&lt;div id=&quot;fd&quot;&gt;<br>
&lt;p class=&quot;now&quot;&gt;1&lt;/p&gt;<br>
&lt;p style=&quot;display:none&quot;&gt;2&lt;/p&gt;<br>
&lt;p style=&quot;display:none&quot;&gt;3&lt;/p&gt;<br>
&lt;p style=&quot;display:none&quot;&gt;4&lt;/p&gt;<br>
&lt;ul&gt;<br>
&lt;li class=&quot;now&quot;&gt;1&lt;/li&gt;<br>
&lt;li&gt;2&lt;/li&gt;<br>
&lt;li&gt;3&lt;/li&gt;<br>
&lt;li&gt;4&lt;/li&gt;<br>
&lt;/ul&gt;<br>
&lt;/div&gt;<br>
&lt;script&gt;<br>
function $(id){return document.getElementById(id)}//获取ID节点的简介方法<br>
var tags=$(&quot;fd&quot;).getElementsByTagName(&quot;li&quot;);//获取切换按钮节点<br>
var cats=$(&quot;fd&quot;).getElementsByTagName(&quot;p&quot;);//获取切换内容节点<br>
var current;//设置当前帧的变量容器<br>
var timer=3000;//&nbsp;&nbsp;&nbsp;    <br>
function disAll(){//初始所有标签样式<br>
for(var i=0; i&lt;tags.length; i++){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[i].className=&quot;&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[i].className=&quot;&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[i].style.display=&quot;none&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
}<br>
function setNow(){//获取当前帧的索引值<br>
for(var i=0; i&lt;tags.length; i++){<br>
&nbsp;&nbsp;&nbsp;   if(tags[i].className==&quot;now&quot;){<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   current=i;&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;     } <br>
}<br>
for(var j=0; j&lt;tags.length; j++){//设置手动切换<br>
&nbsp;&nbsp;&nbsp;&nbsp;     tags[j].onmouseover=function(){<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   clearInterval(h);&nbsp;&nbsp;&nbsp;    <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   disAll();&nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   this.className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;     setNow();<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[current].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   cats[current].className=&quot;now&quot;;&nbsp;&nbsp;&nbsp;     <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;     tags[j].onmouseout=function(){<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   setNow();&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;   <br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   h=setInterval(&quot;goNext()&quot;,3000);<br>
&nbsp;&nbsp;&nbsp;   &nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;   }<br>
function goNext(){//自动切换<br>
&nbsp;&nbsp;   setNow();//获取当前帧索引<br>
&nbsp;&nbsp;   current+=1;//帧自增1<br>
if(current&gt;=parseInt(tags.length)){//判断：如果当前帧索引值是否大于切换按钮总数，如果大于按钮总数则回到初始状态<br>
&nbsp;&nbsp;&nbsp;   current=0;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   disAll();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[0].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[0].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[0].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   }<br>
&nbsp;&nbsp;&nbsp;   else{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   disAll();<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[current].style.display=&quot;block&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   cats[current].className=&quot;now&quot;;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   tags[current].className=&quot;now&quot;;<br>
&nbsp;&nbsp;   }<br>
}<br>
var h=setInterval(&quot;goNext()&quot;,timer)//开始自动切换<br>
&lt;/script&gt;<br>
<br>
&lt;/body&gt;<br>
&lt;/html&gt;<br>
<br>
[/html] 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/b0b3d013fb9ea924dd5401b0.html#comment">查看评论</a>]]></description>
        <pubDate>2009年01月13日 星期二  19:43</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/b0b3d013fb9ea924dd5401b0.html</guid>
</item>

<item>
        <title><![CDATA[Json,prototype,闭包,构造函数]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/0d4c3e1f40de44cfa786697a.html]]></link>
        <description><![CDATA[
		
		<div class="cnt" >
<p>JSON&nbsp;&nbsp;&nbsp;<br>
&nbsp;&nbsp;   已经说了许多了许多话题了，但有一个很基本的问题我们忘了讨论，那就是：怎样建立对象？ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   在前面的示例中，我们已经涉及到了对象的建立了。我们使用了一种被称为JavaScript Object Notation(缩写JSON)的形式，翻译为中文就是&ldquo;JavaScript对象表示法&rdquo;。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   JSON为创建对象提供了非常简单的方法。例如， <br>
&nbsp;&nbsp;   创建一个没有任何属性的对象： <br>
&nbsp;&nbsp;   var o = {}; <br>
&nbsp;&nbsp;   创建一个对象并设置属性及初始值： <br>
&nbsp;&nbsp;   var person = {name: &quot;Angel&quot;, age: 18, married: false}; <br>
&nbsp;&nbsp;   创建一个对象并设置属性和方法： <br>
&nbsp;&nbsp;   var speaker = {text: &quot;Hello World&quot;, say: function(){alert(this.text)}}; <br>
&nbsp;&nbsp;   创建一个更复杂的对象，嵌套其他对象和对象数组等： <br>
&nbsp;&nbsp;   var company = <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   name: &quot;Microsoft&quot;, <br>
&nbsp;&nbsp;   product: &quot;softwares&quot;, <br>
&nbsp;&nbsp;   chairman: {name: &quot;Bill Gates&quot;, age: 53, Married: true}, <br>
&nbsp;&nbsp;   employees: [{name: &quot;Angel&quot;, age: 26, Married: false}, {name: &quot;Hanson&quot;, age: 32, Marred: true}], <br>
&nbsp;&nbsp;   readme: function() {document.write(this.name + &quot; product &quot; + this.product);} <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;  JSON的形式就是用大括&ldquo;{}&rdquo;号包括起来的项目列表，每一个项目间并用逗号&ldquo;,&rdquo;分隔，而项目就是用冒号&ldquo;:&rdquo;分隔的属性名和属性值。这是典型的字典 表示形式，也再次表明了 JavaScript里的对象就是字典结构。不管多么复杂的对象，都可以被一句JSON代码来创建并赋值。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  其实，JSON就是JavaScript对象最好的序列化形式，它比XML更简洁也更省空间。对象可以作为一个JSON形式的字符串，在网络间自由传递和 交换信息。而当需要将这个JSON字符串变成一个JavaScript对象时，只需要使用eval函数这个强大的数码转换引擎，就立即能得到一个 JavaScript内存对象。正是由于JSON的这种简单朴素的天生丽质，才使得她在AJAX舞台上成为璀璨夺目的明星。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   JavaScript就是这样，把面向对象那些看似复杂的东西，用及其简洁的形式表达出来。卸下对象浮华的浓妆，还对象一个眉目清晰！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   构造对象 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   好了，接下我们来讨论一下对象的另一种创建方法。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   除JSON外，在JavaScript中我们可以使用new操作符结合一个函数的形式来创建对象。例如： <br>
&nbsp;&nbsp;   function MyFunc() {}; //定义一个空函数 <br>
&nbsp;&nbsp;   var anObj = new MyFunc(); //使用new操作符，借助MyFun函数，就创建了一个对象 <br>
&nbsp;&nbsp;   JavaScript的这种创建对象的方式可真有意思，如何去理解这种写法呢？ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   其实，可以把上面的代码改写成这种等价形式： <br>
&nbsp;&nbsp;   function MyFunc(){}; <br>
&nbsp;&nbsp;   var anObj = {}; //创建一个对象 <br>
&nbsp;&nbsp;   MyFunc.call(anObj); //将anObj对象作为this指针调用MyFunc函数 <br>
&nbsp;&nbsp;  我们就可以这样理解，JavaScript先用new操作符创建了一个对象，紧接着就将这个对象作为this参数调用了后面的函数。其实， JavaScript内部就是这么做的，而且任何函数都可以被这样调用！但从 &ldquo;anObj = new MyFunc()&rdquo; 这种形式，我们又看到一个熟悉的身影，C++和C#不就是这样创建对象的吗？原来，条条大路通灵山，殊途同归啊！</p>
<p>请看下面的代码：
<table cellspacing="0" cellpadding="6" border="0" align="center" width="95%" style="border: 1px dotted rgb(204, 204, 204); table-layout: fixed;" class="FCK__ShowTableBorders">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">1 function Person(name) //带参数的构造函数 <br>
            &nbsp;&nbsp;   2 { <br>
            &nbsp;&nbsp;   3 this.name = name; //将参数值赋给给this对象的属性 <br>
            &nbsp;&nbsp;   4 this.SayHello = function() {alert( &quot;Hello, I'm &quot; + this.name);}; //给this对象定义一个SayHello方法。 <br>
            &nbsp;&nbsp;   5 }; <br>
            &nbsp;&nbsp;   6 <br>
            &nbsp;&nbsp;   7 function Employee(name, salary) //子构造函数 <br>
            &nbsp;&nbsp;   8 { <br>
            &nbsp;&nbsp;   9 Person.call(this, name); //将this传给父构造函数 <br>
            &nbsp;&nbsp;   10 this.salary = salary; //设置一个this的salary属性 <br>
            &nbsp;&nbsp;   11 this.ShowMeTheMoney = function() {alert(this.name + &quot; $&quot; + this.salary);}; //添加ShowMeTheMoney方法。 <br>
            &nbsp;&nbsp;   12 }; <br>
            &nbsp;&nbsp;   13 <br>
            &nbsp;&nbsp;   14 var BillGates = new Person( &quot;Bill Gates&quot;); //用Person构造函数创建BillGates对象 <br>
            &nbsp;&nbsp;   15 var SteveJobs = new Employee( &quot;Steve Jobs&quot;, 1234); //用Empolyee构造函数创建SteveJobs对象 <br>
            &nbsp;&nbsp;   16 <br>
            &nbsp;&nbsp;   17 BillGates.SayHello(); //显示：I'm Bill Gates <br>
            &nbsp;&nbsp;   18 SteveJobs.SayHello(); //显示：I'm Steve Jobs <br>
            &nbsp;&nbsp;   19 SteveJobs.ShowMeTheMoney(); //显示：Steve Jobs $1234 <br>
            &nbsp;&nbsp;   20 <br>
            &nbsp;&nbsp;   21 alert(BillGates.constructor == Person); //显示：true <br>
            &nbsp;&nbsp;   22 alert(SteveJobs.constructor == Employee); //显示：true <br>
            &nbsp;&nbsp;   23 <br>
            &nbsp;&nbsp;   24 alert(BillGates.SayHello == SteveJobs.SayHello); //显示：false</td>
        </tr>
    </tbody>
</table>
这段代码表明，函数不但可以当作构造函数，而且还可以带参数，还可以为对象添加成员和方法。其中的第9行，Employee构造函数又将自己接收的 this作为参数调用Person构造函数，这就是相当于调用基类的构造函数。第21、22行还表明这样一个意思：BillGates是由Person构 造的，而SteveJobs是由Employee构造的。对象内置的constructor属性还指明了构造对象所用的具体函数！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   其实，如果你愿意把函数当作&ldquo;类&rdquo;的话，她就是&ldquo;类&rdquo;，因为她本来就有&ldquo;类&rdquo;的那些特征。难道不是吗？她生出的儿子各个都有相同的特征，而且构造函数也与类同名嘛！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  但要注意的是，用构造函数操作this对象创建出来的每一个对象，不但具有各自的成员数据，而且还具有各自的方法数据。换句话说，方法的代码体(体现函数 逻辑的数据)在每一个对象中都存在一个副本。尽管每一个代码副本的逻辑是相同的，但对象们确实是各自保存了一份代码体。上例中的最后一句说明了这一实事， 这也解释了JavaScript中的函数就是对象的概念。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   同一类的对象各自有一份方法代码显然是一种浪费。在传统的对象语言中，方法函数并不象JavaScript那样是个对象概念。即使也有象函数指针、方法指针或委托那样的变化形式，但其实质也是对同一份代码的引用。一般的对象语言很难遇到这种情况。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   不过，JavaScript语言有大的灵活性。我们可以先定义一份唯一的方法函数体，并在构造this对象时使用这唯一的函数对象作为其方法，就能共享方法逻辑。例如： <br>
&nbsp;&nbsp;   function SayHello() //先定义一份SayHello函数代码 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(&quot;Hello, I'm &quot; + this.name); <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   function Person(name) //带参数的构造函数 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   this.name = name; //将参数值赋给给this对象的属性 <br>
&nbsp;&nbsp;   this.SayHello = SayHello; //给this对象SayHello方法赋值为前面那份SayHello代码。 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var BillGates = new Person(&quot;Bill Gates&quot;); //创建BillGates对象 <br>
&nbsp;&nbsp;   var SteveJobs = new Person(&quot;Steve Jobs&quot;); //创建SteveJobs对象 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   alert(BillGates.SayHello == SteveJobs.SayHello); //显示：true <br>
&nbsp;&nbsp;  其中，最后一行的输出结果表明两个对象确实共享了一个函数对象。虽然，这段程序达到了共享了一份方法代码的目的，但却不怎么优雅。因为，定义 SayHello方法时反映不出其与Person类的关系。&ldquo;优雅&rdquo;这个词用来形容代码，也不知道是谁先提出来的。不过，这个词反映了程序员已经从追求代 码的正确、高效、可靠和易读等基础上，向着追求代码的美观感觉和艺术境界的层次发展，程序人生又多了些浪漫色彩。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   显然，JavaScript早想到了这一问题，她的设计者们为此提供了一个有趣的prototype概念。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   初看原型 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   prototype源自法语，软件界的标准翻译为&ldquo;原型&rdquo;，代表事物的初始形态，也含有模型和样板的意义。JavaScript中的prototype概念恰如其分地反映了这个词的内含，我们不能将其理解为C++的prototype那种预先声明的概念。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  JavaScript的所有function类型的对象都有一个prototype属性。这个prototype属性本身又是一个object类型的对 象，因此我们也可以给这个prototype对象添加任意的属性和方法。既然prototype是对象的&ldquo;原型&rdquo;，那么由该函数构造出来的对象应该都会具 有这个&ldquo;原型&rdquo;的特性。事实上，在构造函数的prototype上定义的所有属性和方法，都是可以通过其构造的对象直接访问和调用的。也可以这么说， prototype提供了一群同类对象共享属性和方法的机制。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   我们先来看看下面的代码： <br>
&nbsp;&nbsp;   function Person(name) <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   this.name = name; //设置对象属性，每个对象各自一份属性数据 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   Person.prototype.SayHello = function() //给Person函数的prototype添加SayHello方法。 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(&quot;Hello, I'm &quot; + this.name); <br>
&nbsp;&nbsp;   } <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var BillGates = new Person(&quot;Bill Gates&quot;); //创建BillGates对象 <br>
&nbsp;&nbsp;   var SteveJobs = new Person(&quot;Steve Jobs&quot;); //创建SteveJobs对象 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   BillGates.SayHello(); //通过BillGates对象直接调用到SayHello方法 <br>
&nbsp;&nbsp;   SteveJobs.SayHello(); //通过SteveJobs对象直接调用到SayHello方法 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   alert(BillGates.SayHello == SteveJobs.SayHello); //因为两个对象是共享prototype的SayHello，所以显示：true <br>
&nbsp;&nbsp;  程序运行的结果表明，构造函数的prototype上定义的方法确实可以通过对象直接调用到，而且代码是共享的。显然，把方法设置到prototype的 写法显得优雅多了，尽管调用形式没有变，但逻辑上却体现了方法与类的关系，相对前面的写法，更容易理解和组织代码。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   那么，对于多层次类型的构造函数情况又如何呢？</p>
<p>然而，比静态对象语言更神奇的是，我们可以随时给原型对象动态添加新的属性和方法，从而动态地扩展基类的功能特性。这在静态对象语言中是很难想象的。我们来看下面的代码：
<table cellspacing="0" cellpadding="6" border="0" align="center" width="95%" style="border: 1px dotted rgb(204, 204, 204); table-layout: fixed;" class="FCK__ShowTableBorders">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">以下是引用片段：<br>
            function Person(name) <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   this.name = name; <br>
            &nbsp;&nbsp;   }; <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   Person.prototype.SayHello = function() //建立对象前定义的方法 <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   alert( &quot;Hello, I'm &quot; + this.name); <br>
            &nbsp;&nbsp;   }; <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   var BillGates = new Person( &quot;Bill Gates&quot;); //建立对象 <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   BillGates.SayHello(); <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   Person.prototype.Retire = function() //建立对象后再动态扩展原型的方法 <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   alert( &quot;Poor &quot; + this.name + &quot;, bye bye!&quot;); <br>
            &nbsp;&nbsp;   };</td>
        </tr>
    </tbody>
</table>
BillGates.Retire(); //动态扩展的方法即可被先前建立的对象立即调用 <br>
&nbsp;&nbsp;   阿弥佗佛，原型继承竟然可以玩出有这样的法术！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   原型扩展 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   想必君的悟性极高，可能你会这样想：如果在JavaScript内置的那些如Object和Function等函数的prototype上添加些新的方法和属性，是不是就能扩展JavaScript的功能呢？ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   那么，恭喜你，你得到了！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  在AJAX技术迅猛发展的今天，许多成功的AJAX项目的JavaScript运行库都大量扩展了内置函数的prototype功能。比如微软的 ASP.NET AJAX，就给这些内置函数及其prototype添加了大量的新特性，从而增强了JavaScript的功能。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   我们来看一段摘自MicrosoftAjax.debug.js中的代码： <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   String.prototype.trim = function String$trim() { <br>
&nbsp;&nbsp;   if (arguments.length !== 0) throw Error.parameterCount(); <br>
&nbsp;&nbsp;   return this.replace(/^\s+|\s+$/g, ''); <br>
&nbsp;&nbsp;   } <br>
&nbsp;&nbsp;  这段代码就是给内置String函数的prototype扩展了一个trim方法，于是所有的String类对象都有了trim方法了。有了这个扩展，今 后要去除字符串两段的空白，就不用再分别处理了，因为任何字符串都有了这个扩展功能，只要调用即可，真的很方便。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   当然，几乎很少有人去给Object的prototype添加方法，因为那会影响到所有的对象，除非在你的架构中这种方法的确是所有对象都需要的。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   前两年，微软在设计AJAX类库的初期，用了一种被称为&ldquo;闭包&rdquo;(closure)的技术来模拟&ldquo;类&rdquo;。其大致模型如下：
<table cellspacing="0" cellpadding="6" border="0" align="center" width="95%" style="border: 1px dotted rgb(204, 204, 204); table-layout: fixed;" class="FCK__ShowTableBorders">
    <tbody>
        <tr>
            <td bgcolor="#f3f3f3">以下是引用片段：<br>
            function Person(firstName, lastName, age) <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   //私有变量： <br>
            &nbsp;&nbsp;   var _firstName = firstName; <br>
            &nbsp;&nbsp;   var _lastName = lastName; <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   //公共变量: <br>
            &nbsp;&nbsp;   this.age = age; <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   //方法： <br>
            &nbsp;&nbsp;   this.getName = function() <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   return(firstName + &quot; &quot; + lastName); <br>
            &nbsp;&nbsp;   }; <br>
            &nbsp;&nbsp;   this.SayHello = function() <br>
            &nbsp;&nbsp;   { <br>
            &nbsp;&nbsp;   alert( &quot;Hello, I'm &quot; + firstName + &quot; &quot; + lastName); <br>
            &nbsp;&nbsp;   }; <br>
            &nbsp;&nbsp;   }; <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   var BillGates = new Person( &quot;Bill&quot;, &quot;Gates&quot;, 53); <br>
            &nbsp;&nbsp;   var SteveJobs = new Person( &quot;Steve&quot;, &quot;Jobs&quot;, 53); <br>
            &nbsp;&nbsp;   <br>
            &nbsp;&nbsp;   BillGates.SayHello(); <br>
            &nbsp;&nbsp;   SteveJobs.SayHello(); <br>
            &nbsp;&nbsp;   alert(BillGates.getName() + &quot; &quot; + BillGates.age); <br>
            &nbsp;&nbsp;   alert(BillGates.firstName); //这里不能访问到私有变量</td>
        </tr>
    </tbody>
</table>
很显然，这种模型的类描述特别象C#语言的描述形式，在一个构造函数里依次定义了私有成员、公共属性和可用的方法，显得非常优雅嘛。特别是&ldquo;闭包&rdquo;机制可以模拟对私有成员的保护机制，做得非常漂亮。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  所谓的&ldquo;闭包&rdquo;，就是在构造函数体内定义另外的函数作为目标对象的方法函数，而这个对象的方法函数反过来引用外层外层函数体中的临时变量。这使得只要目标 对象在生存期内始终能保持其方法，就能间接保持原构造函数体当时用到的临时变量值。尽管最开始的构造函数调用已经结束，临时变量的名称也都消失了，但在目 标对象的方法内却始终能引用到该变量的值，而且该值只能通这种方法来访问。即使再次调用相同的构造函数，但只会生成新对象和方法，新的临时变量只是对应新 的值，和上次那次调用的是各自独立的。的确很巧妙！</p>
<p>&nbsp;&nbsp;  但是前面我们说过，给每一个对象设置一份方法是一种很大的浪费。还有，&ldquo;闭包&rdquo;这种间接保持变量值的机制，往往会给JavaSript的垃圾回收器制造难 题。特别是遇到对象间复杂的循环引用时，垃圾回收的判断逻辑非常复杂。无独有偶，IE浏览器早期版本确实存在JavaSript垃圾回收方面的内存泄漏问 题。再加上&ldquo;闭包&rdquo;模型在性能测试方面的表现不佳，微软最终放弃了&ldquo;闭包&rdquo;模型，而改用&ldquo;原型&rdquo;模型。正所谓&ldquo;有得必有失&rdquo;嘛。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   原型模型需要一个构造函数来定义对象的成员，而方法却依附在该构造函数的原型上。大致写法如下： <br>
&nbsp;&nbsp;   //定义构造函数 <br>
&nbsp;&nbsp;   function Person(name) <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   this.name = name; //在构造函数中定义成员 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   //方法定义到构造函数的prototype上 <br>
&nbsp;&nbsp;   Person.prototype.SayHello = function() <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(&quot;Hello, I'm &quot; + this.name); <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   //子类构造函数 <br>
&nbsp;&nbsp;   function Employee(name, salary) <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   Person.call(this, name); //调用上层构造函数 <br>
&nbsp;&nbsp;   this.salary = salary; //扩展的成员 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   //子类构造函数首先需要用上层构造函数来建立prototype对象，实现继承的概念 <br>
&nbsp;&nbsp;   Employee.prototype = new Person() //只需要其prototype的方法，此对象的成员没有任何意义！ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   //子类方法也定义到构造函数之上 <br>
&nbsp;&nbsp;   Employee.prototype.ShowMeTheMoney = function() <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(this.name + &quot; $&quot; + this.salary); <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var BillGates = new Person(&quot;Bill Gates&quot;); <br>
&nbsp;&nbsp;   BillGates.SayHello(); <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var SteveJobs = new Employee(&quot;Steve Jobs&quot;, 1234); <br>
&nbsp;&nbsp;   SteveJobs.SayHello(); <br>
&nbsp;&nbsp;   SteveJobs.ShowMeTheMoney(); <br>
&nbsp;&nbsp;   原型类模型虽然不能模拟真正的私有变量，而且也要分两部分来定义类，显得不怎么&ldquo;优雅&rdquo;。不过，对象间的方法是共享的，不会遇到垃圾回收问题，而且性能优于&ldquo;闭包&rdquo;模型。正所谓&ldquo;有失必有得&rdquo;嘛。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  在原型模型中，为了实现类继承，必须首先将子类构造函数的prototype设置为一个父类的对象实例。创建这个父类对象实例的目的就是为了构成原型链， 以起到共享上层原型方法作用。但创建这个实例对象时，上层构造函数也会给它设置对象成员，这些对象成员对于继承来说是没有意义的。虽然，我们也没有给构造 函数传递参数，但确实创建了若干没有用的成员，尽管其值是undefined，这也是一种浪费啊。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   唉！世界上没有完美的事情啊！</p>
<p>那么，我们能否自己定义一个对象来当作原型，并在这个原型上描述类，然后将这个原型设置给新创建的对象，将其当作对象的类呢？我们又能否将这个原型中的一个方法当作构造函数，去初始化新建的对象呢？例如，我们定义这样一个原型对象： <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var Person = //定义一个对象来作为原型类 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   Create: function(name, age) //这个当构造函数 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   this.name = name; <br>
&nbsp;&nbsp;   this.age = age; <br>
&nbsp;&nbsp;   }, <br>
&nbsp;&nbsp;   SayHello: function() //定义方法 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(&quot;Hello, I'm &quot; + this.name); <br>
&nbsp;&nbsp;   }, <br>
&nbsp;&nbsp;   HowOld: function() //定义方法 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(this.name + &quot; is &quot; + this.age + &quot; years old.&quot;); <br>
&nbsp;&nbsp;   } <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   这个JSON形式的写法多么象一个C#的类啊！既有构造函数，又有各种方法。如果可以用某种形式来创建对象，并将对象的内置的原型设置为上面这个&ldquo;类&rdquo;对象，不就相当于创建该类的对象了吗？ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   但遗憾的是，我们几乎不能访问到对象内置的原型属性！尽管有些浏览器可以访问到对象的内置原型，但这样做的话就只能限定了用户必须使用那种浏览器。这也几乎不可行。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   那么，我们可不可以通过一个函数对象来做媒介，利用该函数对象的prototype属性来中转这个原型，并用new操作符传递给新建的对象呢？ <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   其实，象这样的代码就可以实现这一目标： <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   function anyfunc(){}; //定义一个函数躯壳 <br>
&nbsp;&nbsp;   anyfunc.prototype = Person; //将原型对象放到中转站prototype <br>
&nbsp;&nbsp;   var BillGates = new anyfunc(); //新建对象的内置原型将是我们期望的原型对象 <br>
&nbsp;&nbsp;   不过，这个anyfunc函数只是一个躯壳，在使用过这个躯壳之后它就成了多余的东西了，而且这和直接使用构造函数来创建对象也没啥不同，有点不爽。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   可是，如果我们将这些代码写成一个通用函数，而那个函数躯壳也就成了函数内的函数，这个内部函数不就可以在外层函数退出作用域后自动消亡吗？而且，我们可以将原型对象作为通用函数的参数，让通用函数返回创建的对象。我们需要的就是下面这个形式： <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   function New(aClass, aParams) //通用创建函数 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   function new_() //定义临时的中转函数壳 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   aClass.Create.apply(this, aParams); //调用原型中定义的的构造函数，中转构造逻辑及构造参数 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   new_.prototype = aClass; //准备中转原型对象 <br>
&nbsp;&nbsp;   return new new_(); //返回建立最终建立的对象 <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var Person = //定义的类 <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   Create: function(name, age) <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   this.name = name; <br>
&nbsp;&nbsp;   this.age = age; <br>
&nbsp;&nbsp;   }, <br>
&nbsp;&nbsp;   SayHello: function() <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(&quot;Hello, I'm &quot; + this.name); <br>
&nbsp;&nbsp;   }, <br>
&nbsp;&nbsp;   HowOld: function() <br>
&nbsp;&nbsp;   { <br>
&nbsp;&nbsp;   alert(this.name + &quot; is &quot; + this.age + &quot; years old.&quot;); <br>
&nbsp;&nbsp;   } <br>
&nbsp;&nbsp;   }; <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   var BillGates = New(Person, [&quot;Bill Gates&quot;, 53]); //调用通用函数创建对象，并以数组形式传递构造参数 <br>
&nbsp;&nbsp;   BillGates.SayHello(); <br>
&nbsp;&nbsp;   BillGates.HowOld(); <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;   alert(BillGates.constructor == Object); //输出：true <br>
&nbsp;&nbsp;   这里的通用函数New()就是一个&ldquo;语法甘露&rdquo;！这个语法甘露不但中转了原型对象，还中转了构造函数逻辑及构造参数。 <br>
&nbsp;&nbsp;   <br>
&nbsp;&nbsp;  有趣的是，每次创建完对象退出New函数作用域时，临时的new_函数对象会被自动释放。由于new_的prototype属性被设置为新的原型对象，其 原来的原型对象和new_之间就已解开了引用链，临时函数及其原来的原型对象都会被正确回收了。上面代码的最后一句证明，新创建的对象的 constructor属性返回的是Object函数。其实新建的对象自己及其原型里没有constructor属性，那返回的只是最顶层原型对象的构造 函数，即Object</p>
</div> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/0d4c3e1f40de44cfa786697a.html#comment">查看评论</a>]]></description>
        <pubDate>2009年01月07日 星期三  22:01</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/0d4c3e1f40de44cfa786697a.html</guid>
</item>

<item>
        <title><![CDATA[JavaScript的函数]]></title>
        <link><![CDATA[http://hi.baidu.com/shulin2008cn/blog/item/04d9adfda95f431109244d27.html]]></link>
        <description><![CDATA[
		
		<font size="5"><strong><u>javascript的函数</u></strong></font><br>
<br>
作者：F. Permadi<br>
译者：Sheneyan(子乌)<br>
时间：2006.01.03<br>
英文原文： <a target="_blank" href="http://www.permadi.com/tutorial/jsFunc/">INTRODUCTION TO JavaScript Functions</a><br>
中文译文(包括示例)：<a target="_blank" href="http://sheneyan.com/g.php/tech/article/js/jsfunc.html">javascript的函数</a><br>
<strong>子乌注：一篇相当不错的function入门文章，个人感觉相当经典。</strong><br>
<br>
<strong>词语翻译列表</strong><br>
function:函数（Function未翻译）<br>
declare:定义<br>
assign:指派，分配<br>
functionbody:函数体（就是函数的内容）<br>
object:对象<br>
property:属性<br>
unnamed:匿名（在这里没翻译成未命名）<br>
object oriented programming:面向对象编程<br>
class:类（比如后面的class data type我翻译成类数据类型）<br>
pointer:指针<br>
reassign:重新分配<br>
nest:嵌套<br>
feature:功能，特性<br>
local/global:局部/全局<br>
blueprint:蓝图（？）<br>
user defined:用户自定义<br>
instance:实例<br>
prototype:原型（除了标题都不翻译）<br>
internal:内部<br>
constructor:构造器<br>
duplication:<br>
<br>
<font size="4"><strong><u>函数：定义</u></strong></font><br>
<br>
有以下这些方法可以定义一个函数。所有这些都是有效的，但是它们在后台如何实现的则有一些差别。<br>
<br>
一般大家都用这个写法来定义一个函数：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >functionName([parameters]){functionBody};</code></div>
<font size="3"><strong>Example D1：</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function add(a, b) <br>
{  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
&nbsp;&nbsp; return a+b;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
alert(add(1,2));  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果 3</code></div>
当我们这么定义函数的时候，函数内容会被编译（但不会立即执行，除非我们去调用它）。而且，也许你不知道，当这个函数创建的时候有一个同名的对象也被创建。就我们的例子来说，我们现在有一个对象叫做&ldquo;add&rdquo;（要更深入了解，看底下<strong>函数：对象</strong>节。）<br>
我们也可以通过指派一个变量名给<strong>匿名</strong>函数的方式来定义它。<br>
<br>
<font size="3"><strong>Example D2 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var add=function(a, b) <br>
{  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
&nbsp;&nbsp; return a+b;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
alert(add(1,2));  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果 3</code></div>
这个代码和前一个例子做了同样的事情。也许语法看起来比较奇怪，但它应该更能让你感觉到函数是一个对象，而且我们只是为这个对指派了一个名称。可以把它看做和<strong> var myVar=[1,2,3]</strong>一样的语句。以这种方式声明的函数内容也一样会被编译。<br>
当我们指派一个这样的函数的时候，我们并不一定要求必须是<strong>匿名</strong>函数。在这里，我作了和<strong>ExampleD2</strong>一样的事情，但我加了函数名&ldquo;<strong>theAdd</strong>&rdquo;，而且我可以通过调用函数名或者是那个变量来引用函数。<br>
<br>
<font size="3"><strong>Example D2A</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var add=function theAdd(a, b) <br>
{  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
&nbsp;&nbsp; return a+b;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
alert(add(1,2));  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果 3<br>
alert(theAdd(1,2));  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果也是 3</code></div>
使用这种方式来定义函数在面向对象编程中是很有用的，因为我们能像底下这样使一个函数成为一个<strong>对象</strong>的<strong>属性</strong>。
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var myObject=new Object();<br>
myObject.add=function(a,b){return a+b};&nbsp;&nbsp;<br>
// myObject 现在有一个叫做&ldquo;add&rdquo;的属性（或方法）<br>
// 而且我能够象下面这样使用它<br>
myObject.add(1, 2);</code></div>
我们也能够通过使用运算符<strong>new</strong>来定义一个函数。这是一个最少见的定义函数的方式并且并不推荐使用这种方式除非有特殊的理由（可能的理由见下）。语法如下：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >varName=new Function([param1Name, param2Name,...paramNName], functionBody);</code></div>
<font size="3"><strong>Example D3: </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var add=new Function(&quot;a&quot;, &quot;b&quot;, &quot;return a+b;&quot;);<br>
alert(add(3,4));  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果 7</code></div>
我在这里有两个参数叫做<strong>a</strong>和<strong>b</strong>，而<strong>函数体</strong>返回<strong>a</strong>和<strong>b</strong>的和。请注意<strong>new Function(...)</strong>使用了大写<strong>F</strong>， 而不是小写f。 这就告诉javascript，我们将要创建一个类型是Function的对象。 还要注意到，参数名和函数体都是作为字符串而被传递。我们可以随心所欲的增加参数，javascript知道函数体会是右括号前的最后一个字符串（如果没 有参数，你能够只写函数体）。你没必要将所有东西都写在一行里（使用<strong>\</strong>或者使用字符串连接符<strong>+</strong>来分隔长代码）。<strong>\</strong>标记告诉JavaScript在下一行查找字符串的其余部分。例子如下：<br>
<br>
<font size="3"><strong>Example D4 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >// 注意 &quot;+&quot;<br>
// 和 &quot;\&quot;的不同用法<br>
var add=new Function(&quot;a&quot;, &quot;b&quot;, <br>
&nbsp;&nbsp; &quot;alert&quot; +  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; &quot;('adding '+a+' and ' +b);\<br>
   return a+b;&quot;);<br>
alert(add(3,4));  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 结果 7</code></div>
采用这种方式定义函数会导致函数并没被编译，而且它有可能会比用其它方式定义的函数要慢。至于为什么，看一下这个代码：<br>
<br>
<font size="3"><strong>Example D5</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function createMyFunction(myOperator)<br>
{<br>
&nbsp;&nbsp; return new Function(&quot;a&quot;, &quot;b&quot;, &quot;return a&quot; + myOperator + &quot;b;&quot;);<br>
}<br>
var add=createMyFunction(&quot;+&quot;);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 创建函数 &quot;add&quot; <br>
var subtract=createMyFunction(&quot;-&quot;);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 创建函数 &quot;subtract&quot; <br>
var multiply=createMyFunction(&quot;*&quot;);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 创建函数 &quot;multiply&quot; <br>
// test the functions<br>
alert(&quot;加的结果=&quot;+add(10,2));  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 结果是 12<br>
alert(&quot;减的结果=&quot;+subtract(10,2));  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 结果是 8<br>
alert(&quot;乘的结果=&quot;+multiply(10,2));  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 结果是 20<br>
alert(add);</code></div>
这个有趣的例子创建了三个不同的<strong>function</strong>，通过实时传递不同的参数来创建一个新<strong>Function</strong>。因为编译器没法知道最终代码会是什么样子的，所以<strong>new Function(...)</strong>的 内容不会被编译。那这有什么好处呢？嗯，举个例子，如果你需要用户能够创建他们自己的函数的时候这个功能也许很有用，比如在游戏里。我们也许需要允许用户 添加&ldquo;行为&rdquo;给一个&ldquo;player&rdquo;。但是，再说一次，一般情况下，我们应该避免使用这种形式，除非有一个特殊的目的。<br>
<br>
<br>
<font size="4"><strong><u>函数：对象</u></strong></font><br>
函数是javascript中的一种特殊形式的对象。它是第一个<strong>类数据类型（class data type）</strong>。这意味着我们可以给它增加属性。这里有一些需要注意的有趣观点： <br>
<br>
就像刚才提及的，当我们定义一个函数时，javascript实际上在后台为你创建了一个对象。这个对象的名称就是函数名本身。这个对象的类型是function。在下面的例子，我们也许不会意识到这一点，但我们实际上已经创建了一个对象：它叫做<strong>Ball</strong>。<br>
<br>
<font size="3"><strong>Example 1 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball()  &nbsp;&nbsp;    // 也许看起来有点奇怪，但是这个声明<br>
{  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 创建了一个叫做Ball的对象<br>
&nbsp;&nbsp; i=1;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
alert(typeof Ball);  &nbsp;&nbsp;&nbsp; // 结果 &quot;function&quot;</code></div>
我们甚至能将这个对象的内容打印出来而且它会输出这个函数的实际代码，Example 2: 点击 <strong>alert(Ball);</strong>来看看<strong>Ball</strong>的内容。<br>
我们可以给<strong>Object</strong>添加属性，包括对象<strong>function</strong>。因为定义一个函数的实质是创建一个对象。我们可以&ldquo;暗地里&rdquo;给函数添加属性。比如，我们这里定义了函数<strong>Ball</strong>，并添加属性<strong>callsign</strong>。
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball()  &nbsp;&nbsp;    // 也许看起来有点奇怪，但是这个声明<br>
{  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 创建了一个叫做Ball的对象，而且你能够<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 引用它或者象下面那样给它增加属性<br>
Ball.callsign=&quot;The Ball&quot;; // 给Ball增加属性<br>
alert(Ball.callsign); // 输出 &quot;The Ball&quot;</code></div>
因为<strong>function</strong>是一个对象，我们可以为一个<strong>function</strong>分配一个指针。如下例，变量<strong>ptr</strong>指向了对象<strong>myFunction</strong>。
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function myFunction(message) <br>
{ <br>
&nbsp;&nbsp; alert(message);<br>
}<br>
var ptr=myFunction;&nbsp;&nbsp; // ptr指向了myFunction<br>
ptr(&quot;hello&quot;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 这句会执行myFunction：输出&quot;hello&quot;</code></div>
我们可以运行这个函数，就好像这个函数名已经被指针名代替了一样。所以在上面，这行<strong>ptr(&quot;hello&quot;); </strong>和<strong>myFunction(&quot;hello&quot;);</strong>的意义是一样的。<br>
指向函数的指针在面向对象编程中相当有用。例如：当我们有多个对象指向同一个函数的时候（如下）：<br>
<br>
<font size="3"><strong>Example 4A </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function sayName(name) <br>
{ <br>
&nbsp;&nbsp; alert(name);<br>
}<br>
var object1=new Object();  &nbsp;&nbsp;   // 创建三个对象<br>
var object2=new Object();<br>
var object3=new Object();<br>
object1.sayMyName=sayName;  &nbsp;&nbsp;    // 将这个函数指派给所有对象<br>
object2.sayMyName=sayName;<br>
object3.sayMyName=sayName;<br>
&nbsp;&nbsp;<br>
object1.sayMyName(&quot;object1&quot;);    // 输出 &quot;object1&quot;<br>
object2.sayMyName(&quot;object2&quot;);    // 输出 &quot;object2&quot;<br>
object3.sayMyName(&quot;object3&quot;);    // 输出 &quot;object3&quot;</code></div>
<img border="0" src="http://sheneyan.com/image/article/jsfunc/sayName.gif"><br>
<br>
因为只有指针被保存（而不是函数本身），当我们改变函数对象自身的时候，所有指向那个函数的指针都会发生变化。我们可以在底下看到：<br>
<br>
<font size="3"><strong>Example 5: </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function myFunction() <br>
{ <br>
&nbsp;&nbsp; alert(myFunction.message);<br>
}<br>
myFunction.message=&quot;old&quot;;<br>
var ptr1=myFunction;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // ptr1 指向 myFunction<br>
var ptr2=myFunction;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // ptr2 也指向 myFunction<br>
ptr1();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 输出 &quot;old&quot;<br>
ptr2();  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;old&quot;<br>
myFunction.message=&quot;new&quot;;<br>
ptr1();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // 输出 &quot;new&quot;<br>
ptr2();  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;new&quot;</code></div>
我们可以在一个函数创建之后重新分配它，但是我们需要指向函数对象本身，而不是指向它的指针。在下例中，我将改变<strong>myfunction()</strong>的内容。<br>
<br>
<font size="3"><strong>Example 6: </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function myFunction() <br>
{ <br>
&nbsp;&nbsp; alert(&quot;Old&quot;);<br>
}<br>
myFunction(); // 输出 &quot;Old&quot;<br>
myFunction=function()<br>
{<br>
&nbsp;&nbsp; alert(&quot;New&quot;);<br>
};<br>
myFunction(); // 输出 &quot;New&quot;</code></div>
旧函数哪里去了？？被抛弃了。<br>
<img border="0" src="http://sheneyan.com/image/article/jsfunc/lostCode.gif"><br>
<br>
如果我们需要保留它，我们可以在改变它之前给它分配一个指针。<br>
<br>
<font size="3"><strong>Example 6A: </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function myFunction() <br>
{ <br>
&nbsp;&nbsp; alert(&quot;Old&quot;);<br>
}<br>
var savedFuncion=myFunction;<br>
myFunction=function()<br>
{<br>
&nbsp;&nbsp; alert(&quot;New&quot;);<br>
};<br>
myFunction();    // 输出 &quot;New&quot;<br>
savedFuncion();&nbsp;&nbsp; // 输出 &quot;Old&quot;</code></div>
<img border="0" src="http://sheneyan.com/image/article/jsfunc/notlostCode.gif"><br>
<br>
不过要小心，象下面这样的例子并不会有作用，因为是创建了另一个叫做<strong>myFunctionPtr</strong>的函数而不是修改它。<br>
<br>
<font size="3"><strong>Example 6B: </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function myFunction() <br>
{ <br>
&nbsp;&nbsp; alert(&quot;Old&quot;);<br>
}<br>
var savedFunc=myFunction;<br>
savedFunc=function()<br>
{<br>
&nbsp;&nbsp; alert(&quot;New&quot;);<br>
};<br>
myFunction();  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;Old&quot;<br>
savedFunc();  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 输出 &quot;New&quot;</code></div>
我们还能够在一个<strong>函数</strong>中嵌套一个<strong>函数</strong>。下例，我有一个叫做<strong>getHalfOf</strong>的函数,而在它里面，我有另一个叫做<strong>calculate</strong>的函数。<br>
<br>
<font size="3"><strong>Example 7 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function getHalfOf(num1, num2, num3)  &nbsp;&nbsp;&nbsp;<br>
{ <br>
&nbsp;&nbsp; function calculate(number)<br>
&nbsp;&nbsp; {<br>
    return number/2;<br>
&nbsp;&nbsp; }<br>
&nbsp;&nbsp; var result=&quot;&quot;;<br>
&nbsp;&nbsp; result+=calculate(num1)+&quot; &quot;;<br>
&nbsp;&nbsp; result+=calculate(num2)+&quot; &quot;;<br>
&nbsp;&nbsp; result+=calculate(num3);<br>
&nbsp;&nbsp; return result;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
var resultString=getHalfOf(10,20,30);<br>
alert(resultString);  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;5 10 15&quot;</code></div>
你只能在内部调用嵌套的函数。就是说，你不能这么调用：<strong>getHalfOf.calculate(10)</strong>，因为<strong>calculate</strong>只有当外部函数(<strong>getHalfOf()</strong>)在运行的时候才会存在。这和我们前面的讨论一致（函数会被编译，但只有当你去调用它的时候才会执行）。<br>
你也许正在想命名冲突的问题。比如，下面哪一个叫做<strong>calculate</strong>的函数会被调用？<br>
<br>
<font size="3"><strong>Example 8 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function calculate(number)<br>
{<br>
&nbsp;&nbsp; return number/3;<br>
}<br>
function getHalfOf(num1, num2, num3)  &nbsp;&nbsp;&nbsp;<br>
{ <br>
&nbsp;&nbsp; function calculate(number)<br>
&nbsp;&nbsp; {<br>
    return number/2;<br>
&nbsp;&nbsp; }<br>
&nbsp;&nbsp; var result=&quot;&quot;;<br>
&nbsp;&nbsp; result+=calculate(num1)+&quot; &quot;;<br>
&nbsp;&nbsp; result+=calculate(num2)+&quot; &quot;;<br>
&nbsp;&nbsp; result+=calculate(num3);<br>
&nbsp;&nbsp; return result;<br>
}  &nbsp;&nbsp;  &nbsp;&nbsp;   <br>
var resultString=getHalfOf(10,20,30);<br>
alert(resultString);  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;5 10 15&quot;</code></div>
在这个例子中，编译器会首先搜索局部内存地址，所以它会使用内嵌的<strong>calculate</strong>函数。如果我们删除了这个内嵌（局部）的<strong>calculate</strong>函数,这个代码会使用全局的<strong>calculate</strong>函数。<br>
<br>
<font size="4"><strong><u>函数：数据类型及构造函数</u></strong></font><br>
<br>
让我们来看看<strong>函数</strong>的另一个特殊功能－－这让它和其它对象类型截然不同。一个函数能够用来作为一个数据类型的蓝图。这个特性通常被用在面向对象编程中来模拟<strong>用户自定义数据类型(user defined data type)</strong>。使用用户自定义数据类型创建的对象通常被成为<strong>用户自定义对象(user defined object)</strong>。<br>
<br>
在定义了一个函数之后，我们也同时创建了一个新的数据类型。这个数据类型能够用来创建一个新对象。下例，我创建了一个叫做<strong>Ball</strong>的新数据类型。<br>
<br>
<font size="3"><strong>Example DT1 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball()<br>
{<br>
}<br>
var ball0=new Ball(); // ball0 现在指向一个新对象<br>
alert(ball0);  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;Object&quot;，因为 ball0 现在是一个对象</code></div>
这样看来，<strong>ball0=new Ball()</strong>作了什么？<strong>new</strong>关键字创建了一个类型是<strong>Object</strong>的新对象（叫做<strong>ball0</strong>）。然后它会执行<strong>Ball()</strong>，并将这个引用传给<strong>ball0</strong>（用于调用对象）。下面，你会看到这条消息：&ldquo;creating new Ball&rdquo;，如果<strong>Ball()</strong>实际上被运行的话。<br>
<br>
<font size="3"><strong>Example DT2 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball(message)<br>
{<br>
&nbsp;&nbsp; alert(message);<br>
}<br>
var ball0=new Ball(&quot;creating new Ball&quot;);&nbsp;&nbsp; // 创建对象并输出消息<br>
ball0.name=&quot;ball-0&quot;;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // ball0现在有一个属性：name<br>
alert(ball0.name);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;ball-0&quot;</code></div>
我们可以把上面这段代码的第6行看做是底下的代码6-8行的一个简写：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball(message)<br>
{<br>
&nbsp;&nbsp; alert(message);<br>
}<br>
var ball0=new Object();<br>
ball0.construct=Ball;<br>
ball0.construct(&quot;creating new ball&quot;);&nbsp;&nbsp; // 执行 ball0.Ball(&quot;creating..&quot;);<br>
ball0.name=&quot;ball-0&quot;;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
alert(ball0.name);  &nbsp;&nbsp;  &nbsp;&nbsp;   </code></div>
这行代码<strong>ball0.construct=Ball</strong>和<strong>Example 4</strong>中的<strong>ptr=myFunction</strong>语法一致。<br>
如果你还是不明白这行的含义那就回过头再复习一下<strong>Example 4</strong>。注意：你也许考虑直接运行<strong>ball0.Ball(&quot;...&quot;)</strong>，但是它不会起作用的，因为<strong>ball0</strong>并没有一个叫做<strong>Ball(&quot;...&quot;)</strong>的属性，并且它也不知道你究竟想作些什么。<br>
当我们象上面那样使用关键字<strong>new</strong>创建一个对象的时候，一个新的<strong>Object</strong>被创建了。我们可以在创建之后给这个对象添加属性（就好像我在上面那样添加属性<strong>name</strong>。而接下来的问题就是如果我们创建了这个对象的另外一个实例，我们得象下面那样再次给这个新对象添加这个属性。）<br>
<br>
<font size="3"><strong>Example DT3 (creates 3 ball objects) </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball()<br>
{<br>
}<br>
var ball0=new Ball(); // ball0 现在指向了类型Ball的一个新实例<br>
ball0.name=&quot;ball-0&quot;;&nbsp;&nbsp; // ball0 现在有一个属性&quot;name&quot;<br>
var ball1=new Ball();<br>
ball1.name=&quot;ball-1&quot;;<br>
var ball2=new Ball();<br>
alert(ball0.name);    // 输出 &quot;ball-0&quot;<br>
alert(ball1.name);    // 输出 &quot;ball-1&quot;<br>
alert(ball2.name);    // 哦，我忘记给ball2添加&ldquo;name&rdquo;了！</code></div>
我忘记给<strong>ball2</strong>添加属性<strong>name</strong>了，如果在正式的程序中这也许会引发问题。有什么好办法可以自动增加属性呢？嗯，有一个：使用<strong>this</strong>关键字。<strong>this</strong>这个词在<strong>function</strong>中有特别的意义。它指向了调用函数的那个对象。让我们看看下面的另一个示例，这时候我们在构造函数中添加上这些属性：<br>
<br>
<font size="3"><strong>Example DT4 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball(message, specifiedName)<br>
{<br>
&nbsp;&nbsp; alert(message);<br>
&nbsp;&nbsp; this.name=specifiedName;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
}<br>
var ball0=new Ball(&quot;creating new Ball&quot;, &quot;Soccer Ball&quot;);&nbsp;&nbsp;<br>
alert(ball0.name);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // prints &quot;Soccer Ball&quot;</code></div>
请记住：是<strong>new</strong>关键字最终使得构造函数被执行。在这个例子中，它将会运行<strong>Ball(&quot;creating new Ball&quot;, &quot;Soccer Ball&quot;);</strong>而关键字<strong>this</strong>将指向<strong>ball0</strong>。<br>
因此，这行：<strong>this.name=specifiedName</strong>变成了<strong>ball0.name=&quot;Soccer Ball&quot;</strong>。<br>
它主要是说：给<strong>ball0</strong>添加属性<strong>name</strong>，属性值是<strong>Soccer Ball</strong>。 <br>
我们现在只是添加了一个<strong>name</strong>属性给<strong>ball0</strong>，看起来和上一个例子中所做的很象，但却是一个更好更具扩展性的方法。现在，我们可以随心所欲的创建许多带有属性的<strong>ball</strong>而无需我们手动添加它们。而且，人们也希望创建的<strong>Ball</strong>对象能够清晰的看懂它的<strong>构造函数</strong>并且能够轻松找出<strong>Ball</strong>的所有属性。让我们添加更多属性到<strong>Ball</strong>里。<br>
<br>
<font size="3"><strong>Example DT5</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Ball(color, specifiedName, owner, weight)<br>
{<br>
&nbsp;&nbsp; this.name=specifiedName;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.color=color;<br>
&nbsp;&nbsp; this.owner=owner;<br>
&nbsp;&nbsp; this.weight=weight;<br>
}<br>
var ball0=new Ball(&quot;black/white&quot;, &quot;Soccer Ball&quot;, &quot;John&quot;, 20);&nbsp;&nbsp;<br>
var ball1=new Ball(&quot;gray&quot;, &quot;Bowling Ball&quot;, &quot;John&quot;, 30);&nbsp;&nbsp;<br>
var ball2=new Ball(&quot;yellow&quot;, &quot;Golf Ball&quot;, &quot;John&quot;, 55);&nbsp;&nbsp;<br>
var balloon=new Ball(&quot;red&quot;, &quot;Balloon&quot;, &quot;Pete&quot;, 10);&nbsp;&nbsp;<br>
alert(ball0.name);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 &quot;Soccer Ball&quot;<br>
alert(balloon.name);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 输出 &quot;Balloon&quot;<br>
alert(ball2.weight);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    // 输出 &quot;55&quot;</code></div>
嘿！使用面向对象术语，你能够说<strong>Ball</strong>是一个拥有如下属性的对象类型：name, color, owner, weight。 <br>
我们并没被限制只能添加形如字符串或者数字之类的简单数据类型作为属性。我们也能够将对象赋给属性。下面，<strong>supervisor</strong>是<strong>Employee</strong>的一个属性.<br>
<br>
<font size="3"><strong>Example DT6 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary, mySupervisor)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
&nbsp;&nbsp; this.supervisor=mySupervisor;<br>
}<br>
var boss=new Employee(&quot;John&quot;, 200);<br>
var manager=new Employee(&quot;Joan&quot;, 50, boss);&nbsp;&nbsp;<br>
var teamLeader=new Employee(&quot;Rose&quot;, 50, boss);&nbsp;&nbsp;<br>
alert(manager.supervisor.name+&quot; is the supervisor of &quot;+manager.name);<br>
alert(manager.name+&quot;\'s supervisor is &quot;+manager.supervisor.name);&nbsp;&nbsp;</code></div>
会输出什么呢？<br>
就像你在上面这个例子中看到的那样，<strong>manager</strong>和<strong>teamLeader</strong>都有一个<strong>supervisor</strong>属性，而这个属性是类型<strong>Employee</strong>的一个对象。<br>
任何类型的对象都可以作为一个属性，回忆一下前面的<strong>Example 4</strong>(不是Example DT4)，函数也是一个对象。所以你可以让一个<strong>函数</strong>作为一个对象的一个属性。下面，我将添加两个函数<strong>getSalary</strong>和<strong>addSalary</strong>。<br>
<br>
<font size="3"><strong>Example DT7 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
&nbsp;&nbsp; this.addSalary=addSalaryFunction;<br>
&nbsp;&nbsp; this.getSalary=function()<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; {<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    return this.salary;<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; };<br>
}<br>
function addSalaryFunction(addition)<br>
{<br>
&nbsp;&nbsp; this.salary=this.salary+addition;<br>
}<br>
var boss=new Employee(&quot;John&quot;, 200000);<br>
boss.addSalary(10000);  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; // boss 长了 10K 工资……为什么老板工资可以长这么多:'(<br>
alert(boss.getSalary());  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;   // 输出 210K……为什么默认工资也那么高……:'(</code></div>
<strong>addSalary</strong>和<strong>getSalary</strong>演示了几种将函数赋给属性的不同方法。如果你记得我们最开始的讨论；我讨论了三种声明函数的不同方式。所有那些在这里都是适用的，但是上面展示的两个最常用。<br>
让我们看看有什么不同。下面，注意一下9-12行的代码。当这部分代码执行的时候，函数<strong>getSalary</strong>被声明。如前面数次提到的，一个函数声明的结果是一个对象被创建。所以这时候<strong>boss</strong>被创建（接下来的第19行），而boss里有一个<strong>getSalary</strong>属性。
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
&nbsp;&nbsp; this.addSalary=addSalaryFunction;<br>
&nbsp;&nbsp; this.getSalary=function()<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; {<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    return this.salary;<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; };<br>
}<br>
function addSalaryFunction(addition)<br>
{<br>
&nbsp;&nbsp; this.salary=this.salary+addition;<br>
}<br>
var boss=new Employee(&quot;John&quot;, 200000);<br>
var boss2=new Employee(&quot;Joan&quot;, 200000);<br>
var boss3=new Employee(&quot;Kim&quot;, 200000);<br>
</code></div>
当你创建这个对象的更多实例时(<strong>boss2</strong>和<strong>boss3</strong>),每一个实例都有一份<strong>getSalary</strong>代码的单独拷贝；而与此相反，<strong>addSalary</strong>则指向了同一个地方(即<strong>addSalaryFunction</strong>)。&nbsp;&nbsp;<br>
<img border="0" src="http://sheneyan.com/image/article/jsfunc/boss.gif"><br>
看看下面的代码来理解一下上面所描述的内容。<br>
<br>
<font size="3"><strong>Example DT8</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
&nbsp;&nbsp; this.addSalary=addSalaryFunction;<br>
&nbsp;&nbsp; this.getSalary=function()<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; {<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    return this.salary;<br>
  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;&nbsp; };<br>
}<br>
function addSalaryFunction(addition)<br>
{<br>
&nbsp;&nbsp; this.salary=this.salary+addition;<br>
}<br>
var boss1=new Employee(&quot;John&quot;, 200000);<br>
var boss2=new Employee(&quot;Joan&quot;, 200000);<br>
// 给getSalary函数对象添加属性<br>
boss1.getSalary.owner=&quot;boss1&quot;;<br>
boss2.getSalary.owner=&quot;boss2&quot;;<br>
alert(boss1.getSalary.owner);   // 输出 &quot;boss1&quot;<br>
alert(boss2.getSalary.owner);   // 输出 &quot;boss2&quot;<br>
// 如果两个对象指向同一个函数对象，那么<br>
// 上面两个输出都应该是&ldquo;boss2&rdquo;。<br>
// 给addSalary函数对象添加属性<br>
boss1.addSalary.owner=&quot;boss1&quot;;<br>
boss1.addSalary.owner=&quot;boss2&quot;;<br>
alert(boss1.addSalary.owner);   // 输出 &quot;boss2&quot;<br>
alert(boss2.addSalary.owner);   // 输出 &quot;boss2&quot;<br>
// 因为两个对象都指向同一个函数，（子乌注：原文写are not pointing to the same function，疑为笔误）<br>
// 当修改其中一个的时候，会影响所有的实例（所以两个都输出&ldquo;boss2&rdquo;）.<br>
</code></div>
也许不是重要的事情，但这里有一些关于运行类似上面的<strong>getSalary</strong>的内嵌函数的结论： 1) 需要更多的存储空间来存储对象（因为每一个对象实例都会有它自己的<strong>getSalary</strong>代码拷贝）；2) javascript需要更多时间来构造这个对象。<br>
让我们重新写这个示例来让它更有效率些。<br>
<br>
<font size="3"><strong>Example DT9</strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
&nbsp;&nbsp; this.addSalary=addSalaryFunction;<br>
&nbsp;&nbsp; this.getSalary=getSalaryFunction;<br>
}<br>
function getSalaryFunction()<br>
{<br>
&nbsp;&nbsp; return this.salary;<br>
}<br>
function addSalaryFunction(addition)<br>
{<br>
&nbsp;&nbsp; this.salary=this.salary+addition;<br>
}</code></div>
看这儿，两个函数都指向同一个地方，这将会节约空间和缩短构造时间（特别是当你有一大堆内嵌函数在一个构造函数的时候）。这里有另外一个函数的功能能够来提升这个设计，它叫做<strong>prototype</strong>，而我们将在下一节讨论它。<br>
<br>
<font size="4"><strong><u>函数：原型</u></strong></font><br>
每一个构造函数都有一个属性叫做原型(<strong>prototype</strong>,下面都不再翻译，使用其原文)。这个属性非常有用：为一个特定类声明通用的变量或者函数。<br>
<br>
你不需要显式地声明一个<strong>prototype</strong>属性，因为在每一个构造函数中都有它的存在。你可以看看下面的例子：<br>
<br>
<font size="3"><strong>Example PT1 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Test()<br>
{<br>
}<br>
alert(Test.prototype);&nbsp;&nbsp; // 输出 &quot;Object&quot;</code></div>
就如你在上面所看到的，<strong>prototype</strong>是一个对象，因此，你能够给它添加属性。你添加给<strong>prototype</strong>的属性将会成为使用这个<strong>构造函数</strong>创建的对象的通用属性。<br>
例如，我下面有一个数据类型<strong>Fish</strong>，我想让<strong>所有</strong>的鱼都有这些属性：<strong>livesIn=&quot;water&quot;</strong>和<strong>price=20</strong>；为了实现这个，我可以给构造函数<strong>Fish</strong>的<strong>prototype</strong>添加那些属性。<br>
<br>
<font size="3"><strong>Example PT2 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Fish(name, color)<br>
{<br>
&nbsp;&nbsp; this.name=name;<br>
&nbsp;&nbsp; this.color=color;<br>
}<br>
Fish.prototype.livesIn=&quot;water&quot;;<br>
Fish.prototype.price=20;</code></div>
接下来让我们作几条鱼：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var fish1=new Fish(&quot;mackarel&quot;, &quot;gray&quot;);<br>
var fish2=new Fish(&quot;goldfish&quot;, &quot;orange&quot;);<br>
var fish3=new Fish(&quot;salmon&quot;, &quot;white&quot;);</code></div>
再来看看鱼都有哪些属性：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >for (var i=1; i&lt;=3; i++)<br>
{<br>
&nbsp;&nbsp; var fish=eval(&quot;fish&quot;+i);   // 我只是取得指向这条鱼的指针<br>
&nbsp;&nbsp; alert(fish.name+&quot;,&quot;+fish.color+&quot;,&quot;+fish.livesIn+&quot;,&quot;+fish.price);<br>
}</code></div>
输出应该是：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >&quot;mackarel, gray, water, 20&quot;<br>
&quot;goldfish, orange, water, 20&quot;<br>
&quot;salmon, white&nbsp;&nbsp; water, 20&quot; </code></div>
你看到所有的鱼都有属性<strong>livesIn</strong>和<strong>price</strong>,我们甚至都没有为每一条不同的鱼特别声明这些属性。这时因为当一个对象被创建时，这个构造函数将会把它的属性<strong>prototype</strong>赋给新对象的内部属性<strong>__proto__</strong>。这个<strong>__proto__</strong>被这个对象用来查找它的属性。<br>
你也可以通过<strong>prototype</strong>来给所有对象添加共用的函数。这有一个好处：你不需要每次在构造一个对象的时候创建并初始化这个函数。为了解释这一点，让我们重新来看<strong>Example DT9</strong>并使用<strong>prototype</strong>来重写它：<br>
<br>
<font size="3"><strong>Example PT3 </strong></font>
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >function Employee(name, salary)<br>
{<br>
&nbsp;&nbsp; this.name=name;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;  &nbsp;&nbsp;    <br>
&nbsp;&nbsp; this.salary=salary;<br>
}<br>
Employee.prototype.getSalary=function getSalaryFunction()<br>
{<br>
&nbsp;&nbsp; return this.salary;<br>
}<br>
Employee.prototype.addSalary=function addSalaryFunction(addition)<br>
{<br>
&nbsp;&nbsp; this.salary=this.salary+addition;<br>
}</code></div>
我们可以象通常那样创建对象：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >var boss1=new Employee(&quot;Joan&quot;, 200000);<br>
var boss2=new Employee(&quot;Kim&quot;, 100000);<br>
var boss3=new Employee(&quot;Sam&quot;, 150000);</code></div>
并验证它：
<div class="blockcode"><em >复制内容到剪贴板</em>
<h5>代码:</h5>
<code >alert(boss1.getSalary());   // 输出 200000<br>
alert(boss2.getSalary());   // 输出 100000<br>
alert(boss3.getSalary());   // 输出 150000</code></div>
这里有一个图示来说明<strong>prototype</strong>是如何工作的。这个对象的每一个实例(boss1, boss2, boss3)都有一个内部属性叫做<strong>__proto__</strong>，这个属性指向了它的构造器(<strong>Employee</strong>)的属性<strong>prototype</strong>。当你执行<strong>getSalary</strong>或者<strong>addSalary</strong>的时候，这个对象会在它的<strong>__proto__</strong>找到并执行这个代码。注意这点：这里并没有代码的复制(和<strong>Example DT8</strong>的图表作一下对比)。<br>
<img border="0" src="http://sheneyan.com/image/article/jsfunc/prototype.gif"> 
		
		<br/><b>类别：</b><a href="http://hi.baidu.com/shulin2008cn/blog/category/Javascript">Javascript</a>&nbsp;<a href="http://hi.baidu.com/shulin2008cn/blog/item/04d9adfda95f431109244d27.html#comment">查看评论</a>]]></description>
        <pubDate>2009年01月06日 星期二  22:55</pubDate>
        <category><![CDATA[Javascript]]></category>
        <author><![CDATA[shulin2008cn]]></author>
		<guid>http://hi.baidu.com/shulin2008cn/blog/item/04d9adfda95f431109244d27.html</guid>
</item>


</channel>
</rss>