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

<channel>
	<title>肉包子的摇滚生活 &#187; JavaScript</title>
	<atom:link href="http://www.fangyuqiang.com/archives/category/js/feed" rel="self" type="application/rss+xml" />
	<link>http://www.fangyuqiang.com</link>
	<description>前端开发，交互设计，用户体验</description>
	<lastBuildDate>Wed, 01 Sep 2010 09:06:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Open Flash Chart 在IE下显示错误的bug</title>
		<link>http://www.fangyuqiang.com/archives/891</link>
		<comments>http://www.fangyuqiang.com/archives/891#comments</comments>
		<pubDate>Wed, 26 May 2010 02:04:10 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=891</guid>
		<description><![CDATA[图表在首次打开IE6进去后可以正常看到，但是这个时候再点击其他的图表，就出错了，IE8，firefox等浏览器不会有此问题，想来想去不清楚问题所在。后来用httpwatch抓包分析了下，发现IE6第二次不会重新加载图表。shit，又是 IE6缓存问题造成的。要解决IE6的缓存问题，当然就是每次请求的时候请求地址后面附带一个随机数。]]></description>
			<content:encoded><![CDATA[<p>之前就已经碰到过这个问题，open flash chart在IE6，7下会显示不出来，参见：<a href="http://www.fangyuqiang.com/archives/531">http://www.fangyuqiang.com/archives/531</a></p>
<blockquote><p>算是被这个bug吓出一身冷汗，还以为open flash chart在IE下不能用了。状况是：图表在首次打开IE6进去后可以正常看到，但是这个时候再点击其他的图表，就出错了，IE8，firefox等浏览器不会有此问题，想来想去不清楚问题所在。后来用httpwatch抓包分析了下，发现IE6第二次不会重新加载图表。shit，又是 IE6缓存问题造成的。要解决IE6的缓存问题，当然就是每次请求的时候请求地址后面附带一个随机数。这里我们就要对flash的加载地址后面附带随机数了。</p></blockquote>
<p>这次我是用swfobject加载的flash，所以直接在加载的flash地址后面加上时间随机数：<br />
swfobject.embedSWF(&#8220;{S_URL}/flash/hxchart.swf?t=&#8221;+new Date(), &#8220;totaldata&#8221;, &#8220;100%&#8221;, &#8220;100%&#8221;, &#8220;7.0.0&#8243;,&#8221;expressInstall.swf&#8221;,{&#8220;get-data&#8221;:&#8221;get_total_data&#8221;});</p>
<p>问题解决。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/891/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>见识到chrome惊人的Javascript执行能力</title>
		<link>http://www.fangyuqiang.com/archives/876</link>
		<comments>http://www.fangyuqiang.com/archives/876#comments</comments>
		<pubDate>Wed, 12 May 2010 17:29:53 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=876</guid>
		<description><![CDATA[说实话，每次新版本浏览器推出的时候很快就会有一系列的评测报告，但是我一向对这些评测报告不怎么感兴趣。因为无论新版本的浏览器有多牛x，至少在5年内，我还是总是要为IE6做兼容。因为我现在做的网址面向不是高端用户，就算出现一条推荐您使用更高版本的浏览器，都是对用户体验的伤害。之前一直知道chrome的Javascript评测成绩惊人，不过从来没体会到。今天结结实实的体会到，chrome的Javascript能力的惊人之处。 我一向用firefox，今天在挖淘宝一段js代码研究的时候，因为代码都被压缩过，要把它格式化回来，我把那js文件拷下来，放到apatana中格式化。。apatana卡住，然后装死，格式化格不动。 然后我又转向一个网络上的js格式化工具，地址：http://www.div-css.com/f/tool/js-format-color.html 然后把压缩过的js扔进去，格式化，格式到13%左右，firefox提示，脚本执行缓慢，是否终止。继续格式化，终于开始越来越卡。受不了。想起来chrome好像js效率一向不错，打开chrome，执行，我操，15秒！firefox执行到卡死的脚步格式，chrome 15秒内飞快的帮我格式化好了，我一看，格式化后的代码有3000多行。 这次真的见识到了。]]></description>
			<content:encoded><![CDATA[<p>说实话，每次新版本浏览器推出的时候很快就会有一系列的评测报告，但是我一向对这些评测报告不怎么感兴趣。因为无论新版本的浏览器有多牛x，至少在5年内，我还是总是要为IE6做兼容。因为我现在做的网址面向不是高端用户，就算出现一条推荐您使用更高版本的浏览器，都是对用户体验的伤害。之前一直知道chrome的Javascript评测成绩惊人，不过从来没体会到。今天结结实实的体会到，chrome的Javascript能力的惊人之处。</p>
<p><span id="more-876"></span>我一向用firefox，今天在挖淘宝一段js代码研究的时候，因为代码都被压缩过，要把它格式化回来，我把那js文件拷下来，放到apatana中格式化。。apatana卡住，然后装死，格式化格不动。</p>
<p>然后我又转向一个网络上的js格式化工具，地址：<a href="http://www.div-css.com/f/tool/js-format-color.html">http://www.div-css.com/f/tool/js-format-color.html</a></p>
<p>然后把压缩过的js扔进去，格式化，格式到13%左右，firefox提示，脚本执行缓慢，是否终止。继续格式化，终于开始越来越卡。受不了。想起来chrome好像js效率一向不错，打开chrome，执行，我操，15秒！firefox执行到卡死的脚步格式，chrome 15秒内飞快的帮我格式化好了，我一看，格式化后的代码有3000多行。</p>
<p>这次真的见识到了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/876/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQuery lightBox插件的bug解决</title>
		<link>http://www.fangyuqiang.com/archives/874</link>
		<comments>http://www.fangyuqiang.com/archives/874#comments</comments>
		<pubDate>Sun, 09 May 2010 08:31:10 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=874</guid>
		<description><![CDATA[lightBox效果在刚出现的时候引发了一个热潮，但是最开始是基于prototype的，咱一向都用jquery，就用不上了，都用thickbox。后来出了jquery版本的lightbox插件，效果不错，就在项目中用上了。可以点此查看效果：http://www.hxfang.com/action-model-name-newhouse-itemid-13.html 但是在实际使用过程中，发现这个插件还是有些小bug要解决。第一个，IE6，7下会出现影响图片查看的虚线框。 不知道为何，这个bug比较难以重现，lightbox已经通过在css中设定：#lightbox-nav a { outline: none;}来当前激活的链接的虚线边缘，但是在某些情况下还是会出现。最后没办法，自己hack一下。其实去掉虚线框的js代码也很简单，就是让当前元素失去焦点，调用元素的blur事件即可。在lightbox的js代码的280行与300行左右，在其调用点击事件的地方，加入去掉焦点的方法 settings.activeImage = settings.activeImage - 1; _set_image_to_view(); $(this)[0].blur();//让当前元素在点击后失去焦点 return false; 第二个，第一个与最后一个元素的事件处理不当，会触发一些js错误，有些情况下会导致lightbox的半透明边不会消失一直浮动在上层。 激活firebug，到官方的example下面点击它的范例，在最后一个元素再点击下一个的话，就会触发一个js错误：settings.imageArray[settings.activeImage] is undefined。这个js错误有些情况下会导致那个浮动的半透明背景层不会消失，这应该是作者的一个疏忽吧，对于第一个元素跟最后一个元素的触发事件没有更改，导致数组下标越界。修正这个错误也不难，修改第一个与最后一个元素触发事件，改为关闭lightbox。 $('#lightbox-nav-btnNext').unbind() .bind('click',function() { _finish(); return false; }); http://leandrovieira.com/projects/jquery/lightbox/#]]></description>
			<content:encoded><![CDATA[<p>lightBox效果在刚出现的时候引发了一个热潮，但是最开始是基于prototype的，咱一向都用jquery，就用不上了，都用thickbox。后来出了jquery版本的lightbox插件，效果不错，就在项目中用上了。可以点此查看效果：<a href="http://www.hxfang.com/action-model-name-newhouse-itemid-13.html" target="_blank">http://www.hxfang.com/action-model-name-newhouse-itemid-13.html</a></p>
<p>但是在实际使用过程中，发现这个插件还是有些小bug要解决。<span id="more-874"></span>第一个，IE6，7下会出现影响图片查看的虚线框。</p>
<p>不知道为何，这个bug比较难以重现，lightbox已经通过在css中设定：#lightbox-nav a { outline: none;}来当前激活的链接的虚线边缘，但是在某些情况下还是会出现。最后没办法，自己hack一下。其实去掉虚线框的js代码也很简单，就是让当前元素失去焦点，调用元素的blur事件即可。在lightbox的js代码的280行与300行左右，在其调用点击事件的地方，加入去掉焦点的方法</p>
<pre class="js" title="code">settings.activeImage = settings.activeImage - 1;
 _set_image_to_view();
 $(this)[0].blur();//让当前元素在点击后失去焦点
 return false;</pre>
<p>第二个，第一个与最后一个元素的事件处理不当，会触发一些js错误，有些情况下会导致lightbox的半透明边不会消失一直浮动在上层。</p>
<p>激活firebug，到官方的example下面点击它的范例，在最后一个元素再点击下一个的话，就会触发一个js错误：<span class="objectBox objectBox-errorMessage  hasBreakSwitch ">settings.imageArray[settings.activeImage] is undefined。这个js错误有些情况下会导致那个浮动的半透明背景层不会消失，这应该是作者的一个疏忽吧，对于第一个元素跟最后一个元素的触发事件没有更改，导致数组下标越界。修正这个错误也不难，修改第一个与最后一个元素触发事件，改为关闭lightbox。</span></p>
<pre title="code" class="js">$('#lightbox-nav-btnNext').unbind()
					.bind('click',function() {
						_finish();
						return false;
					});
</pre>
<div id="_mcePaste" style="position: absolute; left: -10000px; top: 174px; width: 1px; height: 1px; overflow: hidden;">http://leandrovieira.com/projects/jquery/lightbox/#</div>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/874/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DIV高度自适应实现</title>
		<link>http://www.fangyuqiang.com/archives/856</link>
		<comments>http://www.fangyuqiang.com/archives/856#comments</comments>
		<pubDate>Mon, 26 Apr 2010 12:47:53 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=856</guid>
		<description><![CDATA[项目中用到了google地图，需要地图显示的区域会自动扩展到最大，宽度的自适应是很容易的，width 100%就可以搞定，但是高度试过了几种方法都不满意，浏览器兼容性很难做，很麻烦。最后觉得还是用Javascript来实现最好。范例的代码如下： HXMap.util = { autoResize: function(){ var MINHEIGHT = 450; //浏览器允许的最小高度 var TOPHEIGHT = 100; var viewHeight = HXMap.util.getWindowHeight(); if (viewHeight &#60; MINHEIGHT) { viewHeight = MINHEIGHT; } var contentHeight = viewHeight - TOPHEIGHT; $('#map').height(contentHeight); $('#searchReasultList').height(contentHeight - 119); }, getWindowHeight: function(){ return window.innerHeight &#124;&#124; document.documentElement.clientHeight &#124;&#124; document.body.clientHeight; } } 说起来也很简单，就是先获得当前浏览器窗口的可视高度，兼容性考虑到大部分浏览器了，然后扣除掉顶部的高度，结合jquery 使用设置下所需要设置高度的div。 最后这样调用： HXMap.util.autoResize(); $(window).resize(function(){ [...]]]></description>
			<content:encoded><![CDATA[<p>项目中用到了google地图，需要地图显示的区域会自动扩展到最大，宽度的自适应是很容易的，width 100%就可以搞定，但是高度试过了几种方法都不满意，浏览器兼容性很难做，很麻烦。最后觉得还是用Javascript来实现最好。范例的代码如下：<span id="more-856"></span></p>
<pre class="js" title="code"> HXMap.util =
{
    autoResize: function(){
        var MINHEIGHT = 450; //浏览器允许的最小高度
        var TOPHEIGHT = 100;
        var viewHeight = HXMap.util.getWindowHeight();
        if (viewHeight &lt; MINHEIGHT) {
            viewHeight = MINHEIGHT;
        }
        var contentHeight = viewHeight - TOPHEIGHT;
        $('#map').height(contentHeight);
        $('#searchReasultList').height(contentHeight - 119);
    },
    getWindowHeight: function(){
        return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
    }
}</pre>
<p>说起来也很简单，就是先获得当前浏览器窗口的可视高度，兼容性考虑到大部分浏览器了，然后扣除掉顶部的高度，结合jquery 使用设置下所需要设置高度的div。</p>
<p>最后这样调用：</p>
<pre class="js" title="code">HXMap.util.autoResize();
 $(window).resize(function(){
 HXMap.util.autoResize();
 });</pre>
<p>这样调用的效果就是在初始载入的时候调高度整一次，每次窗口大小改变的时候自动调整div高度。最后的效果如：</p>
<p><a href="http://www.hxfang.com/action-channel-name-map.html" target="_blank">http://www.hxfang.com/action-channel-name-map.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/856/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>IE6下Javascript第一次不执行，刷新后才执行</title>
		<link>http://www.fangyuqiang.com/archives/561</link>
		<comments>http://www.fangyuqiang.com/archives/561#comments</comments>
		<pubDate>Mon, 28 Sep 2009 01:34:45 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[浏览器兼容性]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=561</guid>
		<description><![CDATA[前段时间在整理fckeditor的一个相关项目时候发现，编辑器里的iframe在第一次加载的显示不出来，显示空白，但是很奇怪的，刷新就可以正常显示了。一开始以为这只是IE6下iframe加载的bug，但是最后结果发现这是IE6下Javascript延迟加载的bug。 这个bug只存在于IE6。google搜索一番，目前对于此bug没有明确的定论，难以重现，但是经常的情况就是，有些脚本执行，IE6需要采用setTimeout延迟加载才可以正常的执行。我个人猜测的像类似iframe这些动态加载的项，可能会造成IE6出现这个问题，或者像不同的frame框架同时加载执行Javascript也可能导致。 解决的方法就是将你要执行的Javascript，放在setTimeout(&#8221;,0)里面，这样IE6就可以正常运行了。 此外，调试的时候还发现，如果在代码中加入一个alert，Javascript也会被执行，但是去掉alert代码又不会执行，IE6真是强大的存在啊。]]></description>
			<content:encoded><![CDATA[<p>前段时间在整理fckeditor的一个相关项目时候发现，编辑器里的iframe在第一次加载的显示不出来，显示空白，但是很奇怪的，刷新就可以正常显示了。一开始以为这只是IE6下iframe加载的bug，但是最后结果发现这是IE6下Javascript延迟加载的bug。<span id="more-561"></span></p>
<p>这个bug只存在于IE6。google搜索一番，目前对于此bug没有明确的定论，难以重现，但是经常的情况就是，<strong>有些脚本执行，IE6需要采用setTimeout延迟加载才可以正常的执行</strong>。我个人猜测的像类似iframe这些动态加载的项，可能会造成IE6出现这个问题，或者像不同的frame框架同时加载执行Javascript也可能导致。</p>
<p>解决的方法就是将你要执行的Javascript，放在setTimeout(&#8221;,0)里面，这样IE6就可以正常运行了。</p>
<p>此外，调试的时候还发现，如果在代码中加入一个alert，Javascript也会被执行，但是去掉alert代码又不会执行，IE6真是强大的存在啊。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/561/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>多浏览器兼容性问题及解决方案之Javascript篇</title>
		<link>http://www.fangyuqiang.com/archives/521</link>
		<comments>http://www.fangyuqiang.com/archives/521#comments</comments>
		<pubDate>Wed, 02 Sep 2009 01:44:05 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[Html+CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[浏览器兼容性]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=521</guid>
		<description><![CDATA[CSS跟JavaScript开发中，最令大家头疼的问题就是浏览器兼容性了，虽然很多文章有这方面的文章，但依然让很多开发人员晕头转向，而且也不够全面。这篇文章，将全面收集css和javascript在各种浏览器下的兼容性报告，也期待各位不断补充。 由于发觉内容收集越来越多，决定将CSS跟JavaScript分开。 一、document.formName.item(&#8220;itemName&#8221;) 问题 问题说明：IE下，可以使用 document.formName.item(&#8220;itemName&#8221;) 或 document.formName.elements ["elementName"]；Firefox 下，只能使用document.formName.elements["elementName"]。 解决方法：统一使用document.formName.elements["elementName"]。 二、集合类对象问题 问题说明：IE下，可以使用 () 或 [] 获取集合类对象；Firefox下，只能使用 [ ]获取集合类对象。 解决方法：统一使用 [] 获取集合类对象。 三、自定义属性问题 问题说明：IE下，可以使用获取常规属性的方法来获取自定义属性，也可以使用 getAttribute() 获取自定义属性；Firefox下，只能使用 getAttribute() 获取自定义属性。 解决方法：统一通过 getAttribute() 获取自定义属性。 四、eval(&#8220;idName&#8221;)问题 问题说明：IE下，可以使用 eval(&#8220;idName&#8221;) 或 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象；Firefox下，只能使用 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象。 解决方法：统一用 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象。 五、变量名与某HTML对象ID相同的问题 [...]]]></description>
			<content:encoded><![CDATA[<p>CSS跟JavaScript开发中，最令大家头疼的问题就是浏览器兼容性了，虽然很多文章有这方面的文章，但依然让很多开发人员晕头转向，而且也不够全面。这篇文章，将全面收集css和javascript在各种浏览器下的兼容性报告，也期待各位不断补充。</p>
<p>由于发觉内容收集越来越多，决定将CSS跟JavaScript分开。</p>
<p><span id="more-521"></span></p>
<p><strong>一、document.formName.item(&#8220;itemName&#8221;) 问题</strong></p>
<p>问题说明：IE下，可以使用 document.formName.item(&#8220;itemName&#8221;) 或 document.formName.elements ["elementName"]；Firefox 下，只能使用document.formName.elements["elementName"]。<br />
解决方法：统一使用document.formName.elements["elementName"]。</p>
<p><strong>二、集合类对象问题</strong></p>
<p>问题说明：IE下，可以使用 () 或 [] 获取集合类对象；Firefox下，只能使用 [ ]获取集合类对象。<br />
解决方法：统一使用 [] 获取集合类对象。</p>
<p><strong>三、自定义属性问题</strong></p>
<p>问题说明：IE下，可以使用获取常规属性的方法来获取自定义属性，也可以使用 getAttribute() 获取自定义属性；Firefox下，只能使用 getAttribute() 获取自定义属性。<br />
解决方法：统一通过 getAttribute() 获取自定义属性。</p>
<p><strong>四、eval(&#8220;idName&#8221;)问题</strong></p>
<p>问题说明：IE下，可以使用 eval(&#8220;idName&#8221;) 或 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象；Firefox下，只能使用 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象。<br />
解决方法：统一用 getElementById(&#8220;idName&#8221;) 来取得 id 为 idName 的HTML对象。</p>
<p><strong>五、变量名与某HTML对象ID相同的问题</strong></p>
<p>问题说明：IE下，HTML对象的ID可以作为 document 的下属对象变量名直接使用，Firefox下则不能；Firefox下，可以使用与HTML对象ID相同的变量名，IE下则不能。<br />
解决方法：使用 document.getElementById(&#8220;idName&#8221;) 代替 document.idName。最好不要取HTML对象ID相同的变量名，以减少错误；在声明变量时，一律加上var关键字，以避免歧义。</p>
<p><strong>六、const问题</strong></p>
<p>问题说明：Firefox下，可以使用const关键字或var关键字来定义常量；IE下，只能使用var关键字来定义常量。<br />
解决方法：统一使用var关键字来定义常量。</p>
<p><strong>七、input.type属性问题</strong></p>
<p>问题说明：IE下 input.type 属性为只读；但是Firefox下 input.type 属性为读写。<br />
解决办法：不修改 input.type 属性。如果必须要修改，可以先隐藏原来的input，然后在同样的位置再插入一个新的input元素。</p>
<p><strong>八、window.event问题</strong></p>
<p>问题说明：window.event 只能在IE下运行，而不能在Firefox下运行，这是因为Firefox的event只能在事件发生的现场使用。<br />
解决方法：在事件发生的函数上加上event参数，在函数体内(假设形参为evt)使用 var myEvent = evt?evt:(window.event?window.event:null)<br />
示例：</p>
<pre>&lt;input type="button" onclick="doSomething(event)"/&gt;
&lt;script language="javascript"&gt;
function doSomething(evt) {
var myEvent = evt?evt:(window.event?window.event:null)
...
}</pre>
<p><strong>九、event.x与event.y问题</strong></p>
<p>问题说明：IE下，even对象有x、y属性，但是没有pageX、pageY属性；Firefox下，even对象有pageX、pageY属性，但是没有x、y属性。<br />
解决方法：var myX = event.x ? event.x : event.pageX; var myY = event.y ? event.y:event.pageY;<br />
如果考虑第8条问题，就改用myEvent代替event即可。</p>
<p><strong>十、event.srcElement问题</strong></p>
<p>问题说明：IE下，even对象有srcElement属性，但是没有target属性；Firefox下，even对象有target属性，但是没有srcElement属性。<br />
解决方法：使用srcObj = event.srcElement ? event.srcElement : event.target;<br />
如果考虑第8条问题，就改用myEvent代替event即可。</p>
<p><strong>十一、window.location.href问题</strong></p>
<p>问题说明：IE或者Firefox2.0.x下，可以使用window.location或window.location.href；Firefox1.5.x下，只能使用window.location。<br />
解决方法：使用 window.location 来代替 window.location.href。当然也可以考虑使用 location.replace()方法。</p>
<p><strong>十二、模态和非模态窗口问题</strong></p>
<p>问题说明：IE下，可以通过showModalDialog和showModelessDialog打开模态和非模态窗口；Firefox下则不能。<br />
解决方法：直接使用 window.open(pageURL,name,parameters) 方式打开新窗口。<br />
如果需要将子窗口中的参数传递回父窗口，可以在子窗口中使用window.opener来访问父窗口。如果需要父窗口控制子窗口的话，使用 var subWindow = window.open(pageURL,name,parameters); 来获得新开的窗口对象。</p>
<p><strong>十三、frame和iframe问题</strong></p>
<p>以下面的frame为例：</p>
<p><strong>(1)访问frame对象</strong><br />
IE：使用window.frameId或者window.frameName来访问这个frame对象；<br />
Firefox：使用window.frameName来访问这个frame对象；<br />
解决方法：统一使用 window.document.getElementById(&#8220;frameId&#8221;) 来访问这个frame对象；<br />
<strong>(2)切换frame内容</strong><br />
在IE和Firefox中都可以使用 window.document.getElementById(&#8220;frameId&#8221;).src = &#8220;webjx.com.html&#8221;或 window.frameName.location = &#8220;webjx.com.html&#8221;来切换frame的内容；<br />
如果需要将frame中的参数传回父窗口，可以在frame中使用parent关键字来访问父窗口。</p>
<p><strong>十四、body载入问题</strong></p>
<p>问题说明：Firefox的body对象在body标签没有被浏览器完全读入之前就存在；而IE的body对象则必须在body标签被浏览器完全读入之后才存在。<br />
[注] 这个问题尚未实际验证，待验证后再来修改。<br />
[注] 经验证，IE6、Opera9以及FireFox2中不存在上述问题，单纯的JS脚本可以访问在脚本之前已经载入的所有对象和元素，即使这个元素还没有载入完成。</p>
<p><strong>十五、事件委托方法</strong></p>
<p>问题说明：IE下，使用 document.body.onload = inject; 其中function inject()在这之前已被实现；在Firefox下，使用 document.body.onload = inject();<br />
解决方法：统一使用 document.body.onload=new Function(&#8216;inject()&#8217;); 或者 document.body.onload = function(){/* 这里是代码 */}<br />
[注意] Function和function的区别</p>
<p><strong>十六、访问的父元素的区别</strong></p>
<p>问题说明：在IE下，使用 obj.parentElement 或 obj.parentNode 访问obj的父结点；在firefox下，使用 obj.parentNode 访问obj的父结点。<br />
解决方法：因为firefox与IE都支持DOM，因此统一使用obj.parentNode 来访问obj的父结点。</p>
<p><strong>十七、innerText的问题.</strong></p>
<p>问题说明：innerText在IE中能正常工作，但是innerText在FireFox中却不行。<br />
解决方法：在非IE浏览器中使用textContent代替innerText。<br />
示例：</p>
<pre>if(navigator.appName.indexOf("Explorer") &gt;-1){
document.getElementById('element').innerText = "my text";
} else{
document.getElementById('element').textContent = ";my text";
}</pre>
<p>[注] innerHTML 同时被ie、firefox等浏览器支持，其他的，如outerHTML等只被ie支持，最好不用。</p>
<p><strong>十八、Table操作问题</strong></p>
<p>问题说明：ie、firefox以及其它浏览器对于 table 标签的操作都各不相同，在ie中不允许对table和tr的innerHTML赋值，使用js增加一个tr时，使用appendChild方法也不管用。document.appendChild在往表里插入行时FIREFOX支持，IE不支持<br />
解决办法：把行插入到TBODY中，不要直接插入到表<br />
解决方法：</p>
<p>//向table追加一个空行：</p>
<pre>var row = otable.insertRow(-1);
var cell = document.createElement("td");
cell.innerHTML = "";
cell.className = "XXXX";
row.appendChild(cell);</pre>
<p>[注] 建议使用JS框架集来操作table，如JQuery。</p>
<p><strong>十九、对象宽高赋值问题</strong></p>
<p>问题说明：FireFox中类似 obj.style.height = imgObj.height 的语句无效。<br />
解决方法：统一使用 obj.style.height = imgObj.height + &#8216;px&#8217;;</p>
<p><strong>二十、setAttribute(&#8216;style&#8217;,'color:red;&#8217;)</strong><br />
FIREFOX支持(除了IE，现在所有浏览器都支持)，IE不支持<br />
解决办法：不用setAttribute(&#8216;style&#8217;,'color:red&#8217;)<br />
而用object.style.cssText = &#8216;color:red;&#8217;(这写法也有例外)<br />
最好的办法是上面种方法都用上，万无一失</p>
<p><strong>二一、类名设置</strong><br />
setAttribute(&#8216;class&#8217;,'styleClass&#8217;)<br />
FIREFOX支持，IE不支持(指定属性名为class，IE不会设置元素的class属性，相反只使用setAttribute时IE自动识CLASSNAME属性)<br />
解决办法：<br />
setAttribute(&#8216;class&#8217;,'styleClass&#8217;)</p>
<p>setAttribute(&#8216;className&#8217;,'styleClass&#8217;)</p>
<p>或者直接 object.className=&#8217;styleClass&#8217;;</p>
<p>IE和FF都支持object.className。</p>
<p><strong><strong>二二、</strong>用setAttribute设置事件</strong><br />
var obj = document.getElementById(&#8216;objId&#8217;);<br />
obj.setAttribute(&#8216;onclick&#8217;,'funcitonname();&#8217;);<br />
FIREFOX支持，IE不支持<br />
解决办法：<br />
IE中必须用点记法来引用所需的事件处理程序,并且要用赋予匿名函数<br />
如下：<br />
var obj = document.getElementById(&#8216;objId&#8217;);<br />
obj.onclick=function(){fucntionname();};<br />
这种方法所有浏览器都支持</p>
<p><strong>二三、建立单选钮</strong><br />
IE以外的浏览器<br />
var rdo = document.createElement(&#8216;input&#8217;);<br />
rdo.setAttribute(&#8216;type&#8217;,'radio&#8217;);<br />
rdo.setAttribute(&#8216;name&#8217;,'radiobtn&#8217;);<br />
rdo.setAttribute(&#8216;value&#8217;,'checked&#8217;);</p>
<p>IE:<br />
var rdo =document.createElement(&#8220;&lt;input name=&#8221;radiobtn&#8221; type=&#8221;radio&#8221; value=&#8221;checked&#8221; /&gt;&#8221;);<br />
解决办法：<br />
这一点区别和前面的都不一样。这次完全不同，所以找不到共同的办法来解决，那么只有IF-ELSE了<br />
万幸的是，IE可以识别出document的uniqueID属性，别的浏览器都不可以识别出这一属性。问题解决。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/521/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>简单制作网页彩蛋,JavaScript实现Konami Code</title>
		<link>http://www.fangyuqiang.com/archives/490</link>
		<comments>http://www.fangyuqiang.com/archives/490#comments</comments>
		<pubDate>Tue, 25 Aug 2009 01:43:43 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=490</guid>
		<description><![CDATA[Konami Code简单的说，就是键盘输入 Up, Up, Down, Down, Left, Right, Left, Right, B, A 后，页面上出现特殊的变化。这个规则来自于“魂斗罗”中的“秘技”。“秘技”的术语就叫 Konami Code。这东西还真有趣，有空也可以给自己的网页搞一个彩蛋玩玩。]]></description>
			<content:encoded><![CDATA[<p>很久之前，在圆心的博客上看到了<a href="http://www.planabc.net/2009/05/21/how_to_implement_konami_code_with_javascript/">JavaScript 实现 Konami Code </a>，这东西还真有趣，有空也可以给自己的网页搞一个彩蛋玩玩。</p>
<p>Konami Code简单的说，就是键盘输入 Up, Up, Down, Down, Left, Right, Left, Right, B, A 后，页面上出现特殊的变化。这个规则来自于“魂斗罗”中的“秘技”。“秘技”的术语就叫 <a title="Konami Code" href="http://en.wikipedia.org/wiki/Konami_Code" target="_blank">Konami Code</a></p>
<p><img src="http://www.planabc.net/wp-content/uploads/2009/05/konami.png" alt="Konami Code" /></p>
<p>照着圆心说的，在<a title="Google Reader" href="https://www.google.com/reader/view/" target="_blank">Google Reader</a>上试了一把：</p>
<div id="attachment_491" class="wp-caption aligncenter" style="width: 269px"><img class="size-full wp-image-491" title="google reader konami code" src="http://www.fangyuqiang.com/wp-content/uploads/2009/08/gr.png" alt="google reader konami code" width="259" height="460" /><p class="wp-caption-text">google reader konami code</p></div>
<p>没想到google reader上面居然也有这样的彩蛋，哈哈</p>
<p>圆心在博客也给出了JavaScript实现Konami code的2种方法。</p>
<h3>方法一：</h3>
<p><a title="Abhi’s Weblog - PHP, Apache, MySQL, XMPP and Web Development" href="http://abhinavsingh.com/blog/" target="_blank">Abhi</a> 在 <a title="Konami Code on Facebook : How to implement it on your site" href="http://abhinavsingh.com/blog/2009/05/konami-code-on-facebook-how-to-implement-it-on-your-site/" target="_blank">《Konami Code on Facebook : How to implement it on your site》</a> 一文中提供了大体思路：</p>
<pre class="js" title="code">var $ = {
    enabled: false,
    tmp: Array(),
    _konamiCode: Array(65,66,39,37,39,37,40,40,38,38),
    init: function() {
        this.tmp = Array(65,66,39,37,39,37,40,40,38,38);
    },
    konamiCode: function(e) {
        if(!this.enabled) {
            var t = this.tmp.pop();
            if((e.keyCode-t) == 0) {
                if(this.tmp.length == 0) {
                    this.enabled = true;
                }
            } else {
                this.init();
            }
        } else {
            this.action();
        }
    },
    // Change the action() function to whatever you want to
    action: function() {
        //alert("Konami Code Activated");
    }
}</pre>
<p>然后在 load 的时候调用 $.init() 方法，在 keydown 的时候调用 $.konamiCode(event) 方法。</p>
<h3>方法二：</h3>
<p>不过 Abhi 的方法还是冗余了点，Jan Jarfalk 在留言中提供了一个短小精悍的代码：</p>
<pre class="js" title="code">// Tweetable Konami code
var k=[];
function(e){
    k.push(e.keyCode);
    if(k.toString().indexOf("38,38,40,40,37,39,37,39,66,65")&gt;=0) {
        //alert("Konami Code Activated");
    }
}</pre>
<p>方法2显然更帅气一点，我在自己博客上也搞了一把，不过方法二有点缺陷，需要改进，试过一次就知道了，第一次激活konami code之后，数组没有清空，那么会导致indexOf每次都包含konami code而会再次激活。也就是说，输入一次秘笈之后，每次你再按下任意按键都会触发konami code。此外，这个代码IE下就跑不了了，需要稍微处理一下事件。呃，大师也总有疏忽的时候啊。把方法二改进一下：</p>
<pre class="js" title="code">
var k=[];
function(e){
    e = e||window.event;
    k.push(e.keyCode);
    if(k.toString().indexOf("38,38,40,40,37,39,37,39,66,65")&gt;=0) {
        //alert("Konami Code Activated");
    k=[];//激活后清空数组
}
}</pre>
<p>这样稍微改动即可，我已经在自己博客上加了这个代码了，各位看官可以自己尝试一把，嘿嘿。</p>
<p>这是我放在自己网页上的JavaScript Konami code，想试一下的人，直接把代码copy到自己网页的head中去就行了。</p>
<pre>&lt;script type="text/javascript"&gt;
var k=[];
document.onkeydown = function(e){
    e = e||window.event;
    k.push(e.keyCode);
    if(k.toString().indexOf("38,38,40,40,37,39,37,39,66,65")&gt;=0) {
        alert("谁能比我帅~~");
        k=[];
    }
}
&lt;/script&gt;</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/490/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>让你的浏览器动起来的js代码解析</title>
		<link>http://www.fangyuqiang.com/archives/437</link>
		<comments>http://www.fangyuqiang.com/archives/437#comments</comments>
		<pubDate>Tue, 04 Aug 2009 14:52:11 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=437</guid>
		<description><![CDATA[网上看到的一段很好玩的js代码，感觉写得很精妙，值得收藏。 想让你的浏览器里的图片转起来了，直接在地址栏内输入如下： javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI=document.getElementsByTagName("img"); DIL=DI.length; function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=(Math.sin(R*x1+i*x2+x3)*x4+x5)+"px"; DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+"px"}R++}setInterval('A()',5); void(0); 想让你的浏览器晃起来么，直接在地址栏内输入如下： javascript:function shake_xy(n) {if (self.moveBy) {for (i = 10; i &#62; 0; i--) {for (j = n; j &#62; 0; j--) {self.moveBy(0,i);self.moveBy(i,0); self.moveBy(0,-i);self.moveBy(-i,0);}}}} setInterval('shake_xy(5)',5); void(0); 我们来整理一番，分析下这段华丽的代码是怎么做到的。 深入解析 R = 0; [...]]]></description>
			<content:encoded><![CDATA[<p>网上看到的一段很好玩的js代码，感觉写得很精妙，值得收藏。</p>
<p>想让你的浏览器里的图片转起来了，直接在地址栏内输入如下：</p>
<pre>javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6;
y3=.24; x4=300; y4=200; x5=300; y5=200;
DI=document.getElementsByTagName("img"); DIL=DI.length;
function A(){for(i=0; i-DIL; i++){DIS=DI[ i ].style;
DIS.position='absolute'; DIS.left=(Math.sin(R*x1+i*x2+x3)*x4+x5)+"px";
DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+"px"}R++}setInterval('A()',5);
void(0);</pre>
<p><span id="more-437"></span></p>
<p>想让你的浏览器晃起来么，直接在地址栏内输入如下：</p>
<pre>javascript:function shake_xy(n) {if (self.moveBy)
 {for (i = 10; i &gt; 0; i--)
 {for (j = n; j &gt; 0; j--) {self.moveBy(0,i);self.moveBy(i,0);
self.moveBy(0,-i);self.moveBy(-i,0);}}}}
setInterval('shake_xy(5)',5); void(0);</pre>
<p>我们来整理一番，分析下这段华丽的代码是怎么做到的。</p>
<h3>深入解析</h3>
<pre class="js" title="code">R = 0;
x1 = .1;
y1 = .05;
x2 = .25;
y2 = .24;
x3 = 1.6;
y3 = .24;
x4 = 300;
y4 = 200;
x5 = 300;
y5 = 200;
DI = document.images;
DIL = DI.length;
function A(){
    for (i = 0; i - DIL; i++) {
        DIS = DI[i].style;
        DIS.position = 'absolute';
        DIS.left = Math.sin(R * x1 + i * x2 + x3) * x4 + x5;
        DIS.top = Math.cos(R * y1 + i * y2 + y3) * y4 + y5
    }
    R++
}
setInterval('A()', 5);
void (0);</pre>
<p>其实原理上来说不难，就是将文档中的图片的style属性，位置设置成absolute，然后让left跟top做曲线运动。5ms执行一次变化。<br />
这个源代码的作者确实很赞的说，很好很强大。</p>
<p>这里面有一些技巧性的东西，比如0.x直接简写成.x，for循环里面用i-DIL，利用JavaScript弱类型，0等同于false，来达到与i &lt; DIL 一样的效果</p>
<p>这2天偶然下了下JavaScript王者归来这本电子书，翻开一看，惊奇的发现前面几个部分就是详细的分析了这个函数，让我们来看看JavaScript王者归来的作者是怎么分析的吧。</p>
<blockquote><p>首先，一些浏览器（不是所有的）支持JavaScript伪协议，你可以在浏览器的地址栏里通过“JavaScript:”的形式来执行JavaScript代码。实际上这种良好的执行方式为JavaScript爱好者带来了一个便捷的测试手段，使得他们能够以类似命令行的方式来简易地测试一个没有用过的JavaScript特性，而不必写一大堆文本和HTML标签。</p>
<p>其次，JavaScript支持缺省声明直接赋值的方式来使用全局变量，唯一的约束是命名规则和保留字，作为一种脚本语言，这个特性无疑提供了一种快速便利的执行手段，缺点则也是很明显的，缺乏严谨的约束，为不良代码的产生提供了可能。</p>
<p>注意到document.images的用法，这个指令枚举出页面文档中所有的图片元素，并把这个元素集合的引用赋值给临时变量DI。</p>
<p>DI=document.images;</p>
<p>Document是一个非常有用的接口，它是JavaScript访问页面文档对象的主要方式。除了访问图片的document.images之外，document提供的属性还能够方便地引用页面文档对象中的表单、链接和其他元素。</p>
<p>另一个需要重点关注的特性是函数定义，function A()声明了一个名字叫做“A”的函数，其后的一对大括号内的指令是对这个函数的定义。提供函数文法使得JavaScript成为一种完善的过程式语言。</p>
<p>在函数定义体内，我们可以看到像Math.cos(R*x1+i*x2+x3)这样的用法，Math是JavaScript的一个有用的内置对象，它为JavaScript的使用者提供了一组有用的数学函数，Math.cos返回表达式的余弦值。</p>
<p>在这之后我们通过一个循环将数学计算的结果赋值给document.images集合中提供的图片样式属性，这里引用的是style.top和style.left属性，这两个属性分别定义了图片元素左上角距参照系原点的横坐标和纵坐标的值，默认的单位是像素点（关于元素的定位问题我们将会在后续的章节中有详细的讨论），这样我们相当于将页面文档中的图片元素抽取出来，重新计算了它们的位置，并按照新的位置进行排列。</p>
<p>最后，我们在排列的过程中改变参量R的值，并通过定时器函数setInterval每隔5个毫秒调用一次A()函数，就实现了例子中的图片旋转的特效。</p>
<p>setInterval(&#8216;A()&#8217;,5);</p>
<p>在结束话题之前，顺便提一个不太常用的特性。也许你已经注意到例子末尾的那个不起眼的void(0)，如果你将它去掉，你会发现一切令人惊讶的特效都消失了，甚至连浏览器中的页面也不见踪迹，取而代之的是孤零零地显示在浏览器窗口左上角的一组奇怪的数字，这是怎么回事呢？</p>
<p>原来JavaScript伪协议默认将页面带到一个新的document中并显示程序返回结果，所以正常情况下运算的结果会在一个空文档对象内显示，这样也就没有图片可以展现特效，而void(0)阻止了这个跳转动作。</p>
<p>void是JavaScript的一个特殊的运算符，它的作用是舍弃任何参数表达式的值，这意味着要求解析器检验并计算参数表达式内容，但是却忽略其结果。如果你刻意去检查void运算的返回值，会发现它返回一个undefined标记（事实上任何一个不带return指令的函数运算的默认返回值都是undefined）。在浏览器的缺省行为中，undefined阻止了页面的跳转。</p>
<p>在代码中，我们用表达式undefined;取代void(0)，也能得到相同的结果。</p>
<p>这段代码的经典之处不但在于它实现的效果令人惊叹，还在于它在短短的几行指令中体现了客户端JavaScript中大多数重要的特性，这些特性包括我们前面提到的伪协议、全局变量、文档接口、集合对象、函数、内置对象、元素样式属性、定时器以及void()和undefined，除此以外还提到了代码中没有出现的闭包、函数实例化以及typeof操作符，这些特性几乎构成了客户端JavaScript的全部</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/437/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>优化JavaScript脚本的性能总结</title>
		<link>http://www.fangyuqiang.com/archives/417</link>
		<comments>http://www.fangyuqiang.com/archives/417#comments</comments>
		<pubDate>Fri, 31 Jul 2009 15:48:49 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://www.fangyuqiang.com/?p=417</guid>
		<description><![CDATA[接下来博客的文章，打算结合梅花雪的文章，以及曹力等人的一些文章，来系统的介绍下如何对JavaScript脚本做性能优化。 JavaScript性能优化重要吗？当然，如果你的JavaScript只是做一些简单的表单验证，你几乎可以忽略。但是，如果你是构建一个复杂的基于JavaScript的程序，例如webgame，富客户端，那么优化JavaScript程序的性能就很重要了。 瓶颈在哪里？ 如果你是急匆匆的搜索到这篇文章，觉得你的js太缓慢了，可以先看看下面几个tips，或许对你有帮助： IE6，7的JavaScript解释器非常差，比起firefox，opera，chrome，safari等浏览器，差距是数量级的。相反，这几个浏览器的JavaScript效率都非常的高，如果你的js在这几个浏览器下面也很慢，才真正有问题。而事实上，对JavaScript做优化，目前而言都是在对IE6，7做优化，而IE8的js效率已经提升了很多，跟firefox等没有数量级上的差距了，但是性能还是落后的。 检查你代码里面的循环，递归调用等地方的代码，是否存在逻辑问题？或者说业务本身就这么复杂需要长时间的js执行？ 检查代码里面的字符串拼接操作，IE6，7的字符串拼接，应该说是其JavaScript解释器的错误实现，导致IE6，7在处理字符串拼接上存在严重的效率问题，具体的解决方法可以参看下面的详细介绍。 检查页面DOM元素的数量。页面DOM元素过多,会导致浏览器JS运行和DOM渲染效率降低，这往往是一个根本性的原因，采用ext做出来的系统，很多情况下会出现这个问题，而这个问题，目前而言并没有什么最佳的解决方案。如果ext是选定的架构，那么应该在DOM元素数量的控制上下一番功能。 （51js论坛上有人提出的）过于频繁的DOM操作同样会使得页面速度变得缓慢。例如在拖动效果中，如果拖动容器内的结点数太多，则在拖动过程中出现很卡的现象——在整个拖动过程中，浏览器要不断重新宣染容器及其内部所有结点的相关属性，任务量大，触发又很频繁，CPU占用就会很高。改进这样的拖动效果，可以改成：按下鼠标时，是拖动一个独立的空DIV，松开鼠标时再把真正要移动的窗口重新定位到目标位置就行。这样在拖动过程中，浏览器只需要宣染一个div。 以下我们再结合曹力的如何优化JavaScript脚本的性能一文，来具体的分析优化的具体实现。曹力从多种角度分析了JavaScript脚本可以优化的地方。不过，个人认为，以上提到的几个tips才往往是解决的关键，除此之外的，曹力在文章中提到的一些优化实际操作中意义并不大，因为很多优化往往是需要到一个很高的数量级才会有明显的效果，所以在此我顺便点评了优化指数，即做这个优化的必要性，5星最高，3星程度就是基本一定要做的了。 语言层次方面 循环 循环是很常用的一个控制结构，大部分东西要依靠它来完成，在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。for(;;)和while循环的性能应该说基本（平时使用时）等价。 而事实上，如何使用这两个循环，则有很大讲究。我在测试中有些很有意思的情况，见附录。最后得出的结论是： 如果是循环变量递增或递减，不要单独对循环变量赋值，应该在它最后一次读取的时候使用嵌套的++或&#8211;操作符。 如果要与数组的长度作比较，应该事先把数组的length属性放入一个局部变量中，减少查询次数。 举例，假设arr是一个数组，最佳的遍历元素方式为： for(var i=0, len = arr.length;i0;i--){...} 优化指数：1星。除非你循环的次数达到万以上的数量级，否则这样的优化并不能带来明显的收益，不过养成这样的写法是个好习惯。for(in)的效率有多差这个曹力没给出测试结果，但是我认为该怎么用还是怎么用，前提还是循环的次数，在jQuery之类的框架源码里面都有很多的for(in)的使用。 局部变量和全局变量 局部变量的速度要比全局变量的访问速度更快，因为全局变量其实是全局对象的成员，而局部变量是放在函数的栈当中的。 优化指数：2星。将全局变量改成局部变量提高的性能也并不明显，但是合理设计程序的结构，减少全局变量的使用是比较良好的编程习惯，可以避免一些无意中带来的错误或者bug。 不使用Eval 使用eval相当于在运行时再次调用解释引擎对内容进行运行，需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版（关于闭包的内容请参考函数式编程的有关内容） 优化指数：3星。关于eval我还没有进行过深入的测试，不过根据多个资料的介绍，eval确实会消耗大量时间，不适宜在程序中多使用。此外，with语句也一样，不适宜多使用。 减少对象查找 因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。 这一点可以和循环结合起来，因为我们常常要根据字符串、数组的长度进行循环，而通常这个长度是不变的，比如每次查询a.length，就要额外进行一个操作，而预先把var len=a.length，则就少了一次查询。 优化指数：1星。一样，减少对象查找这样提升的效率也很不明显，一样还是要到一个数量级才行。比如YUI这样的，重度的命名空间，都是XX.XX.XX.XX，但它一样应用得很广泛。 字符串连接 如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。 如果要连接多个字符串，应该少使用+=，如 s+=a; s+=b; s+=c; 应该写成 s+=a + b + c； 而如果是收集字符串，比如多次对同一个字符串进行+=操作的话，最好使用一个缓存。怎么用呢？使用JavaScript数组来收集，最后使用join方法连接起来，如下 var buf = new Array(); for(var i = [...]]]></description>
			<content:encoded><![CDATA[<p>接下来博客的文章，打算结合梅花雪的文章，以及曹力等人的一些文章，来系统的介绍下如何对JavaScript脚本做性能优化。</p>
<p>JavaScript性能优化重要吗？当然，如果你的JavaScript只是做一些简单的表单验证，你几乎可以忽略。但是，如果你是构建一个复杂的基于JavaScript的程序，例如webgame，富客户端，那么优化JavaScript程序的性能就很重要了。<span id="more-417"></span></p>
<h2>瓶颈在哪里？</h2>
<p>如果你是急匆匆的搜索到这篇文章，觉得你的js太缓慢了，可以先看看下面几个tips，或许对你有帮助：</p>
<ul>
<li><strong>IE6，7的JavaScript解释器非常差，比起firefox，opera，chrome，safari等浏览器，差距是数量级的</strong>。相反，这几个浏览器的JavaScript效率都非常的高，如果你的js在这几个浏览器下面也很慢，才真正有问题。而事实上，<strong>对JavaScript做优化，目前而言都是在对IE6，7做优化</strong>，而IE8的js效率已经提升了很多，跟firefox等没有数量级上的差距了，但是性能还是落后的。</li>
<li>检查你代码里面的<strong>循环，递归调用</strong>等地方的代码，是否存在逻辑问题？或者说业务本身就这么复杂需要长时间的js执行？</li>
<li>检查代码里面的<strong>字符串拼接操作</strong>，IE6，7的字符串拼接，应该说是其JavaScript解释器的错误实现，导致IE6，7在处理字符串拼接上存在严重的效率问题，具体的解决方法可以参看下面的详细介绍。</li>
<li>检查页面DOM元素的数量。<strong>页面DOM元素过多,会导致浏览器JS运行和DOM渲染效率降低</strong>，这往往是一个根本性的原因，采用ext做出来的系统，很多情况下会出现这个问题，而这个问题，目前而言并没有什么最佳的解决方案。如果ext是选定的架构，那么应该在DOM元素数量的控制上下一番功能。</li>
<li>（51js论坛上有人提出的）<strong>过于频繁的DOM操作同样会使得页面速度变得缓慢</strong>。例如在拖动效果中，如果拖动容器内的结点数太多，则在拖动过程中出现很卡的现象——<strong>在整个拖动过程中，浏览器要不断重新宣染容器及其内部所有结点的相关属性，任务量大，触发又很频繁</strong>，CPU占用就会很高。改进这样的拖动效果，可以改成：按下鼠标时，是拖动一个独立的空DIV，松开鼠标时再把真正要移动的窗口重新定位到目标位置就行。这样在拖动过程中，浏览器只需要宣染一个div。</li>
</ul>
<p>以下我们再结合曹力的<a href="http://shiningray.cn/improve-javascript-performance.html">如何优化JavaScript脚本的性能</a>一文，来具体的分析优化的具体实现。曹力从多种角度分析了JavaScript脚本可以优化的地方。不过，个人认为，<strong>以上提到的几个tips才往往是解决的关键，除此之外的，曹力在文章中提到的一些优化实际操作中意义并不大，因为很多优化往往是需要到一个很高的数量级才会有明显的效果</strong>，所以在此我顺便点评了优化指数，即做这个优化的必要性，5星最高，3星程度就是基本一定要做的了。</p>
<h2>语言层次方面</h2>
<h3>循环</h3>
<p>循环是很常用的一个控制结构，大部分东西要依靠它来完成，在JavaScript中，我们可以使用for(;;),while(),for(in)三种循环，事实上，这三种循环中for(in)的效率极差，因为他需要查询散列键，只要可以就应该尽量少用。for(;;)和while循环的性能应该说基本（平时使用时）等价。</p>
<p>而事实上，如何使用这两个循环，则有很大讲究。我在测试中有些很有意思的情况，见附录。最后得出的结论是：</p>
<ul>
<li>如果是循环变量递增或递减，不要单独对循环变量赋值，应该在它最后一次读取的时候使用嵌套的++或&#8211;操作符。</li>
<li>如果要与数组的长度作比较，应该事先把数组的length属性放入一个局部变量中，减少查询次数。</li>
</ul>
<p>举例，假设arr是一个数组，最佳的遍历元素方式为：</p>
<pre>for(var i=0, len = arr.length;i0;i--){...}</pre>
<p>优化指数：1星。<strong>除非你循环的次数达到万以上的数量级，否则这样的优化并不能带来明显的收益，不过养成这样的写法是个好习惯</strong>。for(in)的效率有多差这个曹力没给出测试结果，但是我认为该怎么用还是怎么用，前提还是循环的次数，在jQuery之类的框架源码里面都有很多的for(in)的使用。</p>
<h3>局部变量和全局变量</h3>
<p>局部变量的速度要比全局变量的访问速度更快，因为全局变量其实是全局对象的成员，而局部变量是放在函数的栈当中的。</p>
<p>优化指数：2星。将全局变量改成局部变量提高的性能也并不明显，但是<strong>合理设计程序的结构，减少全局变量的使用是比较良好的编程习惯，可以避免一些无意中带来的错误或者bug</strong>。</p>
<h3>不使用Eval</h3>
<p>使用eval相当于在运行时再次调用解释引擎对内容进行运行，需要消耗大量时间。这时候使用JavaScript所支持的闭包可以实现函数模版（关于闭包的内容请参考函数式编程的有关内容）</p>
<p>优化指数：3星。关于eval我还没有进行过深入的测试，不过根据多个资料的介绍，<strong>eval确实会消耗大量时间，不适宜在程序中多使用。此外，with语句也一样，不适宜多使用</strong>。</p>
<h3>减少对象查找</h3>
<p>因为JavaScript的解释性，所以a.b.c.d.e，需要进行至少4次查询操作，先检查a再检查a中的b，再检查b中的c，如此往下。所以如果这样的表达式重复出现，只要可能，应该尽量少出现这样的表达式，可以利用局部变量，把它放入一个临时的地方进行查询。</p>
<p>这一点可以和循环结合起来，因为我们常常要根据字符串、数组的长度进行循环，而通常这个长度是不变的，比如每次查询a.length，就要额外进行一个操作，而预先把var len=a.length，则就少了一次查询。</p>
<p>优化指数：1星。一样，<strong>减少对象查找这样提升的效率也很不明显，一样还是要到一个数量级才行</strong>。比如YUI这样的，重度的命名空间，都是XX.XX.XX.XX，但它一样应用得很广泛。</p>
<h3>字符串连接</h3>
<p>如果是追加字符串，最好使用s+=anotherStr操作，而不是要使用s=s+anotherStr。</p>
<p>如果要连接多个字符串，应该少使用+=，如</p>
<pre>s+=a;
s+=b;
s+=c;</pre>
<p>应该写成</p>
<pre>s+=a + b + c；</pre>
<p>而如果是收集字符串，比如多次对同一个字符串进行+=操作的话，最好使用一个缓存。怎么用呢？使用JavaScript数组来收集，最后使用join方法连接起来，如下</p>
<pre>var buf = new Array();
for(var i = 0; i &lt; 100; i++){ 	

buf.push(i.toString()); 

} 

var all = buf.join("");</pre>
<p>优化指数：4星。如果你的js程序经常涉及到字符串的拼接操作的话，这个优化的意义就很重大了。当然，这个优化在ff，chrome之类的浏览器上面并没有什么明显的效果。但是别忘了有个浏览器叫IE。<strong>ie6跟ie7下面，字符串拼接的引擎实现有错误，所以在大量字符串拼接的情况下，用数组的join操作来拼接字符串会比用+号来拼接提升一个数量级效率</strong>。</p>
<h3>类型转换</h3>
<p>类型转换是大家常犯的错误，因为JavaScript是动态类型语言，你不能指定变量的类型。</p>
<p>1. 把数字转换成字符串，应用&#8221;" + 1，虽然看起来比较丑一点，但事实上这个效率是最高的，性能上来说：</p>
<p>(&#8220;&#8221; + ) &gt; String() &gt; .toString() &gt; new String()</p>
<p>这条其实和下面的“直接量”有点类似，尽量使用编译时就能使用的内部操作要比运行时使用的用户操作要快。</p>
<p>String()属于内部函数，所以速度很快，而.toString()要查询原型中的函数，所以速度逊色一些，new String()用于返回一个精确的副本。</p>
<p>2.浮点数转换成整型，这个更容易出错，很多人喜欢使用parseInt()，其实parseInt()是用于将字符串转换成数字，而不是浮点数和整型之间的转换，我们应该使用Math.floor()或者Math.round()。</p>
<p>另外，和第二节的对象查找中的问题不一样，Math是内部对象，所以Math.floor()其实并没有多少查询方法和调用的时间，速度是最快的。</p>
<p>3.对于自定义的对象，如果定义了toString()方法来进行类型转换的话，推荐显式调用toString()，因为内部的操作在尝试所有可能性之后，会尝试对象的toString()方法尝试能否转化为String，所以直接调用这个方法效率会更高</p>
<p>优化指数：2.5星。这些优化一样是没办法得到多大的提升的，但是养成这样的写法与做法确实很有必要的。很多新手与老手的差距也都体现在对细节的处理上面。</p>
<h3>使用直接量</h3>
<p>其实这个影响倒比较小，可以忽略。什么叫使用直接量，比如，JavaScript支持使用[param,param,param,...]来直接表达一个数组，以往我们都使用new Array(param,param,&#8230;)，使用前者是引擎直接解释的，后者要调用一个Array内部构造器，所以要略微快一点点。</p>
<p>同样，var foo = {}的方式也比var foo = new Object();快，var reg = /../;要比var reg=new RegExp()快。</p>
<p>优化指数：1星。使用直接量是现在很流行的做法，建议写法上养成一样的习惯，代码看起来会更清晰。</p>
<h3>字符串遍历操作</h3>
<p>对字符串进行循环操作，譬如替换、查找，应使用正则表达式，因为本身JavaScript的循环速度就比较慢，而正则表达式的操作是用C写成的语言的API，性能很好。</p>
<p>优化指数：1.5星。优化是有前提的，看你需要操作的字符串有多大，普通的字符串，该用什么方式还是用什么方式。</p>
<h3>高级对象</h3>
<p>自定义高级对象和Date、RegExp对象在构造时都会消耗大量时间。如果可以复用，应采用缓存的方式。</p>
<p>优化指数：2星。</p>
<h2>DOM相关</h2>
<h3>插入HTML</h3>
<p>很多人喜欢在JavaScript中使用document.write来给页面生成内容。事实上这样的效率较低，如果需要直接插入HTML，可以找一个容器元素，比如指定一个div或者span，并设置他们的innerHTML来将自己的HTML代码插入到页面中。</p>
<p>优化指数：3星。document.write虽然方便，但是不仅效率较低，同样也带来一些维护上困难。在你经常需要设置innerHTML的情况下，那就更不要去使用document.write。</p>
<h3>对象查询</h3>
<p>使用[""]查询要比.items()更快，这和前面的减少对象查找的思路是一样的，调用.items()增加了一次查询和函数的调用。</p>
<p>优化指数：2星。使用[""]提升的性能可以忽略，不过我觉得[""]的写法会更加清晰，此外，<strong>item()这个的方法只有IE下才能用，firefox下面是不行的。</strong></p>
<h3>创建DOM节点</h3>
<p>通常我们可能会使用字符串直接写HTML来创建节点，其实这样做</p>
<p>1.无法保证代码的有效性</p>
<p>2.字符串操作效率低</p>
<p>所以应该是用document.createElement()方法，而如果文档中存在现成的样板节点，应该是用cloneNode()方法，因为使用createElement()方法之后，你需要设置多次元素的属性，使用cloneNode()则可以减少属性的设置次数——同样如果需要创建很多元素，应该先准备一个样板节点。</p>
<p>优化指数：2星。同样的，直接用HTML方式来创建节点还是很多便利的，而createElement()的方式则要写不少代码。这性能跟便利之间，取舍其实完全在你自己了。</p>
<h3>定时器</h3>
<p>如果针对的是不断运行的代码，不应该使用setTimeout，而应该是用setInterval。setTimeout每次要重新设置一个定时器。</p>
<p>优化指数：1星。本身这2个定时器使用的场合就不太一样。很多setTimeout的场合用setInterval并不适合。</p>
<h2>其他</h2>
<h3>脚本引擎</h3>
<p>据我测试Microsoft的JScript的效率较Mozilla的Spidermonkey要差很多，无论是执行速度还是内存管理上，因为JScript现在基本也不更新了。但SpiderMonkey不能使用ActiveXObject</p>
<h3>文件优化</h3>
<p>文件优化也是一个很有效的手段，删除所有的空格和注释，把代码放入一行内，可以加快下载的速度，注意，是下载的速度而不是解析的速度，如果是本地，注释和空格并不会影响解释和执行速度。</p>
<p>优化指数：5星。产品化的代码，用压缩工具处理后再放出是必须的。可用的工具很多，比如YUI Compressor，JS min。虽然它并不是提高程序的性能，但是<strong>JavaScript作为客户端执行的程序，更快下载到客户端就能更早得到执行，这个时间往往比你费尽心思的优化提高得多得多</strong>。想象一下，如果extjs没有压缩，那么客户端需要多么漫长的等待才能看到界面。</p>
<h2>曹力的总结</h2>
<p>本文总结了我在JavaScript编程中所找到的提高JavaScript运行性能的一些方法，其实这些经验都基于几条原则：</p>
<p>1.直接拿手头现成的东西比较快，如局部变量比全局变量快，直接量比运行时构造对象快等等。</p>
<p>2.尽可能少地减少执行次数，比如先缓存需要多次查询的。</p>
<p>3.尽可能使用语言内置的功能，比如串链接。</p>
<p>4.尽可能使用系统提供的API，因为这些API是编译好的二进制代码，执行效率很高</p>
<p>同时，一些基本的算法上的优化，同样可以用在JavaScript中，比如运算结构的调整，这里就不再赘述了。但是由于JavaScript是解释型的，一般不会在运行时对字节码进行优化，所以这些优化仍然是很重要的。</p>
<p>当然，其实这里的一些技巧同样使用在其他的一些解释型语言中，大家也可以进行参考。</p>
<h2>参考</h2>
<ul>
<li><a href="http://www.umsu.de/jsperf/ 各种浏览器的测试对比">http://www.umsu.de/jsperf/ 各种浏览器的测试对比</a></li>
<li><a href="http://home.earthlink.net/~kendrasg/info/js_opt/">http://home.earthlink.net/~kendrasg/info/js_opt/</a></li>
<li><a href="http://shiningray.cn/improve-javascript-performance.html">Shining Ray » 如何优化JavaScript脚本的性能</a>.</li>
</ul>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 2430px; width: 1px; height: 1px;">
<h1>附录1</h1>
<p>由于是以前做过的测试，测试代码已经不全，我补充了一部分如下：</p>
<pre class="js" title="code">var print;

if(typeof document != "undefined" ){
    print = function(){
		document.write(arguments[0]);
	}
}else if(typeof WScript != "undefined" ){
    print = function(){
        WScript.Echo(arguments[0],arguments[1],arguments[2]);
    }
}

function empty(){
}

function benchmark(f){
    var i = 0;
    var start = (new Date()).getTime();

    while(i &lt; pressure){
        f(i++);
    }
    var end = (new Date()).getTime();
    WScript.Echo(end-start);
}

/*
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
    c = [i,i,i,i,i,i,i,i,i,i];
    i++;
}
end = (new Date()).getTime();
WScript.Echo(end-start);
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
    c = new Array(i,i,i,i,i,i,i,i,i,i);
    i++;
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
*/

function internCast(i){
    return "" + i;
}

function StringCast(i){
    return String(i)
}
function newStringCast(i){
    return new String(i)
}
function toStringCast(i){
    return i.toString();
}
function ParseInt(){
    return parseInt(j);
}
function MathFloor(){
    return Math.floor(j);
}
function Floor(){
    return floor(j);
}
var pressure = 50000;
var a  = "";
var floor = Math.floor;
j = 123.123;
print("-------------\nString Conversion Test");
print("The empty:", benchmark(empty));
print("intern:", benchmark(internCast));
print("String:");
benchmark(StringCast);
print("new String:");
benchmark(newStringCast);
print("toString:");
benchmark(toStringCast);
print("-------------\nFloat to Int Conversion Test");
print("parseInt");
benchmark(ParseInt);
print("Math.floor");
benchmark(MathFloor);
print("floor")
benchmark(Floor);

function newObject(){
    return new Object();
}

function internObject(){
    return {};
}
print("------------\nliteral Test");
print("runtime new object", benchmark(newObject));
print("literal object", benchmark(internObject));</pre>
<h1>附录2</h1>
<p>代码1：</p>
<pre class="js" title="code">    for(var i=0;i&lt;100;i++){
        arr[i]=0;
    }</pre>
<p>代码2：</p>
<pre class="js" title="code">    var i = 0;
    while(i &lt; 100){
        arr[i++]=0;
    }</pre>
<p>代码3：</p>
<pre class="js" title="code">    var i = 0;
    while(i &lt; 100){
        arr[i]=0;
        i++;
    }</pre>
<p>在firefox下测试这两段代码，结果是代码2优于代码1和3，而代码1一般优于代码3，有时会被代码3超过；而在IE</p>
<p>6.0下，测试压力较大的时候（如测试10000次以上）代码2和3则有时候优于代码1，有时候就会远远落后代码1，而在测试压力较小（如5000次），则代码2&gt;代码3&gt;代码1。</p>
<p>代码4：</p>
<pre class="js" title="code">    var i = 0;
    var a;
    while(i &lt; 100){
        a = 0;
        i++;
    }</pre>
<p>代码5：</p>
<pre class="js" title="code">    var a;
    for(var i=0;i&lt;100;i++){
        a = 0;
    }</pre>
<p>上面两段代码在Firefox和IE下测试结果都是性能接近的。</p>
<p>代码6：</p>
<pre class="js" title="code">    var a;
    var i=0;
    while(i&lt;100){
        a=i;
        i++;
    }</pre>
<p>代码7：</p>
<pre class="js" title="code">    var a;
    var i=0;
    while(i&lt;100){
        a=i++;
    }</pre>
<p>代码8：</p>
<pre class="js" title="code">    var a;
    for(var i=0;i&lt;100;i++){
        a = i;
    }</pre>
<p>代码9：</p>
<pre class="js" title="code">    var a;
    for(var i=0;i&lt;100;){
        a = i++;
    }</pre>
<p>这四段代码在Firefox下6和8的性能接近，7和9的性能接近，而6,</p>
<p>8 &lt; 7, 9；</p>
<p>最后我们来看一下空循环</p>
<p>代码10：</p>
<pre class="js" title="code">for(var i=0;i&lt;100;i++){   

}</pre>
<p>代码11：</p>
<pre class="js" title="code">var i;
 while(i&lt;100){
 i++;
}</pre>
<p>最后的测试出现了神奇的结果，Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值，于是我没有放在一开始给大家看。</p></div>
<h2>附录1</h2>
<p>由于是以前做过的测试，测试代码已经不全，我补充了一部分如下：</p>
<pre class="js" title="code">var print;
if(typeof document != "undefined" ){
print = function(){
document.write(arguments[0]);
}
}else if(typeof WScript != "undefined" ){
print = function(){
WScript.Echo(arguments[0],arguments[1],arguments[2]);
}
}
function empty(){
}
function benchmark(f){
var i = 0;
var start = (new Date()).getTime();
while(i &lt; pressure){
f(i++);
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
}
/*
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
c = [i,i,i,i,i,i,i,i,i,i];
i++;
}
end = (new Date()).getTime();
WScript.Echo(end-start);
i=0
start = (new Date()).getTime();
while(i &lt; 60000){
c = new Array(i,i,i,i,i,i,i,i,i,i);
i++;
}
var end = (new Date()).getTime();
WScript.Echo(end-start);
*/
function internCast(i){
return "" + i;
}
function StringCast(i){
return String(i)
}
function newStringCast(i){
return new String(i)
}
function toStringCast(i){
return i.toString();
}
function ParseInt(){
return parseInt(j);
}
function MathFloor(){
return Math.floor(j);
}
function Floor(){
return floor(j);
}
var pressure = 50000;
var a  = "";
var floor = Math.floor;
j = 123.123;
print("-------------\nString Conversion Test");
print("The empty:", benchmark(empty));
print("intern:", benchmark(internCast));
print("String:");
benchmark(StringCast);
print("new String:");
benchmark(newStringCast);
print("toString:");
benchmark(toStringCast);
print("-------------\nFloat to Int Conversion Test");
print("parseInt");
benchmark(ParseInt);
print("Math.floor");
benchmark(MathFloor);
print("floor")
benchmark(Floor);
function newObject(){
return new Object();
}
function internObject(){
return {};
}
print("------------\nliteral Test");
print("runtime new object", benchmark(newObject));
print("literal object", benchmark(internObject));</pre>
<h2>附录2</h2>
<h3>代码1：</h3>
<pre class="js" title="code">for(var i=0;i&lt;100;i++){
arr[i]=0;
}</pre>
<h3>代码2：</h3>
<pre class="js" title="code">var i = 0;
while(i &lt; 100){
arr[i++]=0;
}</pre>
<h3>代码3：</h3>
<pre class="js" title="code">var i = 0;
while(i &lt; 100){
arr[i]=0;
 i++;
 }</pre>
<p>在firefox下测试这两段代码，结果是代码2优于代码1和3，而代码1一般优于代码3，有时会被代码3超过；而在IE 6.0下，测试压力较大的时候（如测试10000次以上）代码2和3则有时候优于代码1，有时候就会远远落后代码1，而在测试压力较小（如5000次），则代码2&gt;代码3&gt;代码1。</p>
<h3>代码4：</h3>
<pre class="js" title="code">var i = 0;
var a;
while(i &lt; 100){
a = 0;
i++;
}</pre>
<h3>代码5：</h3>
<pre class="js" title="code">var a;
for(var i=0;i&lt;100;i++){
a = 0;
}</pre>
<p>上面两段代码在Firefox和IE下测试结果都是性能接近的。</p>
<h3>代码6：</h3>
<pre class="js" title="code">var a;
var i=0;
while(i&lt;100){
a=i;
i++;
}</pre>
<h3>代码7：</h3>
<pre class="js" title="code">var a;
var i=0;
while(i&lt;100){
a=i++;
}</pre>
<h3>代码8：</h3>
<pre class="js" title="code">var a;
for(var i=0;i&lt;100;i++){
a = i;
}</pre>
<h3>代码9：</h3>
<pre class="js" title="code">var a;
for(var i=0;i&lt;100;){
a = i++;
}</pre>
<p>这四段代码在Firefox下6和8的性能接近，7和9的性能接近，而6,</p>
<p>8 &lt; 7, 9；</p>
<p>最后我们来看一下空循环</p>
<h3>代码10：</h3>
<pre class="js" title="code">for(var i=0;i&lt;100;i++){   }</pre>
<h3>代码11：</h3>
<pre class="js" title="code">var i;
while(i&lt;100){
  i++;
}</pre>
<p>最后的测试出现了神奇的结果，Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值，于是我没有放在一开始给大家看。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/417/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>玩玩webgame开发（4）：游戏数据结构设计</title>
		<link>http://www.fangyuqiang.com/archives/200</link>
		<comments>http://www.fangyuqiang.com/archives/200#comments</comments>
		<pubDate>Wed, 10 Dec 2008 14:59:23 +0000</pubDate>
		<dc:creator>fangyuqiang</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[webgame]]></category>

		<guid isPermaLink="false">http://playfish.javaeye.com/blog/290379</guid>
		<description><![CDATA[很久没做更新了。最近比较忙碌，手头的webgame也都放下。最近很想念我的小webgame了，回来继续写。 上篇玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（下）http://playfish.javaeye.com/blog/267275 在高峰期时候发表的，结果被火速沉底了。。。汗 好了，不小心有说了好多废话，言归正传。 ============= 数据结构设计是门高深的学问，而游戏的数据结构设计，那显然，也是一门很高深的学问（ &#124;&#124;好废话。。），数据结构应该是整个游戏的骨架所在，而游戏数据平衡，（另一门高深的学问。。）跟这游戏的数据结构息息相关。本文只是从自己做的一个小游戏出发，简要的介绍一下我的一个简单的游戏的数据结构设计思路。 一个游戏几个基本的要素： 地图 游戏角色 怪物 物品 建筑 先从地图说起 游戏都在地图上进行的。地图的基本要素包括：地图元素（即每一个地图坐标格子上的元素），不可进入的位置等。其他的还包括一些基本信息。我的地图数据结构设计如下： 这是个很简单的地图结构，包括的几个信息：地图名称，地图等级，地图元素，不可移动的位置。最后生成的展示效果如下（实际界面大很多，这里只是部分）： 关于地图生成以及战争迷雾的部分，可以参看这个系列文章的前2篇。至于在地图上出现的物品，角色，怪物，建筑，并没有放在地图的数据里面，因为我觉得这是属于不同角色的数据，是应该分开的。这样的数据结构可以满足这样的需求：地图按照数据显示，对于指定的地图元素，角色不能进入。 接下来是游戏角色 pos指角色在地图上的坐标，其它的就是一些常见的数据了，包括名称，金钱，满血hp，当前的hp，等级，经验，攻击，防御，速度，幸运，视野，其它的类型，文件，img属于我自己定义的一些结构，用于获得特定状态下的包子的图片。 设计一个这样的数据结构并不难，自己爱怎么设定就怎么设定，呵呵。不过关键的问题在于数据平衡，设置得很bt的数据可以开始玩的时候很爽，但是一结束玩家马上就会失去兴趣，所以，合适的数值以及成长曲线才会保证耐玩度。我个人是喜欢很小的数据，这样玩家自己计算的时候简单，而且数据平衡比较好做。我平时很经常玩一些war3的rpg，只要进去里面的人物或者是物品设定数字都是按百的，alt+q。顺便废话一下我喜欢的元素魔法之战这个。 怪物的数据设计 和游戏角色的数据结构不同，它有额外添加1个id以及一个items数组，id表示怪物类型，因为怪物会在地图上出现很多不同种类的怪物，通过id来区分不同的怪物。items数组，表示这个怪物身上有多大的概率会掉那种类型物品。items数组内的id表示物品的id。 一个怪物需要分布在地图上的各个位置，我目前觉得最简单的方式就是： 哪个位置上哪个怪物，简单明了。 ====未完待续，明晚继续]]></description>
			<content:encoded><![CDATA[<p>很久没做更新了。最近比较忙碌，手头的webgame也都放下。最近很想念我的小webgame了，回来继续写。<span id="more-200"></span></p>
<p>上篇玩玩webgame开发（3）：自动战斗实现以及一些游戏细节（下）<a href="/blog/267275" target="_blank">http://playfish.javaeye.com/blog/267275</a></p>
<p>在高峰期时候发表的，结果被火速沉底了。。。汗</p>
<p>好了，不小心有说了好多废话，言归正传。</p>
<p>=============</p>
<p>数据结构设计是门高深的学问，而游戏的数据结构设计，那显然，也是一门很高深的学问（ ||好废话。。），数据结构应该是整个游戏的骨架所在，而游戏数据平衡，（另一门高深的学问。。）跟这游戏的数据结构息息相关。本文只是从自己做的一个小游戏出发，简要的介绍一下我的一个简单的游戏的数据结构设计思路。</p>
<p>一个游戏几个基本的要素：</p>
<ul>
<li>地图</li>
<li>游戏角色</li>
<li>怪物</li>
<li>物品</li>
<li>建筑</li>
</ul>
<h3>先从地图说起</h3>
<p>游戏都在地图上进行的。地图的基本要素包括：地图元素（即每一个地图坐标格子上的元素），不可进入的位置等。其他的还包括一些基本信息。我的地图数据结构设计如下：</p>
<pre class="js"><!--mce:0--></pre>
<p>这是个很简单的地图结构，包括的几个信息：地图名称，地图等级，地图元素，不可移动的位置。最后生成的展示效果如下（实际界面大很多，这里只是部分）：</p>
<p><img src="/upload/attachment/58556/fd3be481-1163-35e2-83b5-c5279c9b2748.jpg" alt="" /></p>
<p>关于地图生成以及战争迷雾的部分，可以参看这个系列文章的前2篇。至于在地图上出现的物品，角色，怪物，建筑，并没有放在地图的数据里面，因为我觉得这是属于不同角色的数据，是应该分开的。这样的数据结构可以满足这样的需求：地图按照数据显示，对于指定的地图元素，角色不能进入。</p>
<h3>接下来是游戏角色</h3>
<pre class="js"><!--mce:1--></pre>
<p>pos指角色在地图上的坐标，其它的就是一些常见的数据了，包括名称，金钱，满血hp，当前的hp，等级，经验，攻击，防御，速度，幸运，视野，其它的类型，文件，img属于我自己定义的一些结构，用于获得特定状态下的包子的图片。</p>
<p><img src="/upload/attachment/58558/f2f03c78-49e5-3cae-b7bc-b77a5dd9ef58.jpg" alt="" /></p>
<p>设计一个这样的数据结构并不难，自己爱怎么设定就怎么设定，呵呵。不过关键的问题在于数据平衡，设置得很bt的数据可以开始玩的时候很爽，但是一结束玩家马上就会失去兴趣，所以，合适的数值以及成长曲线才会保证耐玩度。我个人是喜欢很小的数据，这样玩家自己计算的时候简单，而且数据平衡比较好做。我平时很经常玩一些war3的rpg，只要进去里面的人物或者是物品设定数字都是按百的，alt+q。顺便废话一下我喜欢的元素魔法之战这个。</p>
<h3>怪物的数据设计</h3>
<pre class="js"><!--mce:2--></pre>
<p>和游戏角色的数据结构不同，它有额外添加1个id以及一个items数组，id表示怪物类型，因为怪物会在地图上出现很多不同种类的怪物，通过id来区分不同的怪物。items数组，表示这个怪物身上有多大的概率会掉那种类型物品。items数组内的id表示物品的id。</p>
<p>一个怪物需要分布在地图上的各个位置，我目前觉得最简单的方式就是：</p>
<pre class="js"><!--mce:3--></pre>
<p>哪个位置上哪个怪物，简单明了。</p>
<p>====未完待续，明晚继续</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fangyuqiang.com/archives/200/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
