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

<channel>
	<title>army8735</title>
	<atom:link href="http://army8735.org/feed" rel="self" type="application/rss+xml" />
	<link>http://army8735.org</link>
	<description>你才土豆，你全家都土豆！</description>
	<lastBuildDate>Fri, 03 Sep 2010 07:13:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>看此图不爽，改之！</title>
		<link>http://army8735.org/2010/09/03/793.html</link>
		<comments>http://army8735.org/2010/09/03/793.html#comments</comments>
		<pubDate>Fri, 03 Sep 2010 07:13:30 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[其它]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=793</guid>
		<description><![CDATA[
]]></description>
			<content:encoded><![CDATA[<p><img src="/wp-content/uploads/2010/09/cxy.jpg" alt="看此图不爽，改之！" /></p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/09/03/793.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>FileReference.load()真TM耗时</title>
		<link>http://army8735.org/2010/09/02/788.html</link>
		<comments>http://army8735.org/2010/09/02/788.html#comments</comments>
		<pubDate>Thu, 02 Sep 2010 08:29:01 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[FileReference]]></category>
		<category><![CDATA[load]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=788</guid>
		<description><![CDATA[想尝试使用FileReference的load方法来加载本地文件，从而在客户端预先进行一些处理，发现这个方法不是一般的耗时。假如选择了一个50M的文件，load就需要8s左右！更别说后续的处理操作了！
2s内能加载完毕的话，只有10m以下的小文件，可这怎么能够行？
而且我还没看到unload方法，adobe，你该改进改进了。
]]></description>
			<content:encoded><![CDATA[<p>想尝试使用FileReference的load方法来加载本地文件，从而在客户端预先进行一些处理，发现这个方法不是一般的耗时。假如选择了一个50M的文件，load就需要8s左右！更别说后续的处理操作了！</p>
<p>2s内能加载完毕的话，只有10m以下的小文件，可这怎么能够行？</p>
<p>而且我还没看到unload方法，adobe，你该改进改进了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/09/02/788.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>可惜的是，designMode目前还无法在safari mobile版上使用</title>
		<link>http://army8735.org/2010/08/17/783.html</link>
		<comments>http://army8735.org/2010/08/17/783.html#comments</comments>
		<pubDate>Tue, 17 Aug 2010 03:47:39 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[safari mobile]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=783</guid>
		<description><![CDATA[ipone、ipad等移动设备上，搭载的是苹果的safari mobile版本。浏览器中常用的富文本编辑器，是依靠designMode或者contentEditable运作的。
可惜的是，designMode目前还无法在safari mobile版上使用，所以在使用时得增加判断，为mobile版本的safari专门区分开富文本编辑。
/apple.*mobile.*safari/.test(userAgent)
]]></description>
			<content:encoded><![CDATA[<p>ipone、ipad等移动设备上，搭载的是苹果的safari mobile版本。浏览器中常用的富文本编辑器，是依靠designMode或者contentEditable运作的。</p>
<p>可惜的是，designMode目前还无法在safari mobile版上使用，所以在使用时得增加判断，为mobile版本的safari专门区分开富文本编辑。</p>
<pre class="brush:js">/apple.*mobile.*safari/.test(userAgent)</pre>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/08/17/783.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Manufactoria：非常好玩的自动机编程游戏</title>
		<link>http://army8735.org/2010/07/13/779.html</link>
		<comments>http://army8735.org/2010/07/13/779.html#comments</comments>
		<pubDate>Tue, 13 Jul 2010 06:59:29 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[其它]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=779</guid>
		<description><![CDATA[http://www.matrix67.com/blog/archives/3306
Matrix67推荐的强大脑力游戏，这是最近我玩过的最好玩的脑力游戏，没有之一。简单地说，这是一个四进制图灵机的设计和布线问题，因此非常适合各种IT民工。前面的关都不难，直到倒数第四列，问题才复杂起来。而最后那些问题基本上对脑力有极大考验。
我目前也卡在倒数第4行了。前面的倒是全部最优解，继续杀脑细胞中。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.matrix67.com/blog/archives/3306">http://www.matrix67.com/blog/archives/3306</a></p>
<p>Matrix67推荐的强大脑力游戏，这是最近我玩过的最好玩的脑力游戏，没有之一。简单地说，这是一个四进制图灵机的设计和布线问题，因此非常适合各种IT民工。前面的关都不难，直到倒数第四列，问题才复杂起来。而最后那些问题基本上对脑力有极大考验。</p>
<p>我目前也卡在倒数第4行了。前面的倒是全部最优解，继续杀脑细胞中。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/07/13/779.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>继续开发JAse</title>
		<link>http://army8735.org/2010/06/18/775.html</link>
		<comments>http://army8735.org/2010/06/18/775.html#comments</comments>
		<pubDate>Fri, 18 Jun 2010 07:45:52 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[JAse]]></category>
		<category><![CDATA[as、flex]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=775</guid>
		<description><![CDATA[http://code.google.com/p/jase/
一段日子没怎么动了，惭愧惭愧。废了一天功夫，终于把redo和undo两个操作，与高亮逻辑关联了起来。具体做法就是将语法解析部分合并到命令链当中，与编辑器脱离了。这样每次编辑器内容发生改变的时候，直接执行命令链来保存改变，无需关心高亮逻辑，这些逻辑全部放在命令链中一同处理了。
当中遇到不少问题，还有以前的一些经验，比如：

侦听textfield的textInput事件时，倘若是手动修改textfield的text，是不会触发的，这点需要相当注意。
ie输入回车时是\r\n，而其它为\n，但是到了textfield里面又会自动将\n替换成\r，这个地方非常迷惑人！在做命令链时保存的内容尤为恼人，必须对所有的内容检测一遍，删掉\r\n，将\r替换成\n。
resize事件放到flash内部了，以前是通过js侦听window的resize，这样需要经过ExternalInterface的中转，效率太低，还需要外部嵌个div之类的。现在直接侦听stage的resize，好很多。
找人重做了图标，怕openoffice说我侵权。
正在加新语种。

这里可以试用svn的每次更新版本：
http://jase.googlecode.com/svn/trunk/jase1/bin/index.html
]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/p/jase/">http://code.google.com/p/jase/</a></p>
<p>一段日子没怎么动了，惭愧惭愧。废了一天功夫，终于把redo和undo两个操作，与高亮逻辑关联了起来。具体做法就是将语法解析部分合并到命令链当中，与编辑器脱离了。这样每次编辑器内容发生改变的时候，直接执行命令链来保存改变，无需关心高亮逻辑，这些逻辑全部放在命令链中一同处理了。</p>
<p>当中遇到不少问题，还有以前的一些经验，比如：</p>
<ol>
<li>侦听textfield的textInput事件时，倘若是手动修改textfield的text，是不会触发的，这点需要相当注意。</li>
<li>ie输入回车时是\r\n，而其它为\n，但是到了textfield里面又会自动将\n替换成\r，这个地方非常迷惑人！在做命令链时保存的内容尤为恼人，必须对所有的内容检测一遍，删掉\r\n，将\r替换成\n。</li>
<li>resize事件放到flash内部了，以前是通过js侦听window的resize，这样需要经过ExternalInterface的中转，效率太低，还需要外部嵌个div之类的。现在直接侦听stage的resize，好很多。</li>
<li>找人重做了图标，怕openoffice说我侵权。</li>
<li>正在加新语种。</li>
</ol>
<p>这里可以试用svn的每次更新版本：</p>
<p><a href="http://jase.googlecode.com/svn/trunk/jase1/bin/index.html">http://jase.googlecode.com/svn/trunk/jase1/bin/index.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/06/18/775.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>比substr更高级的subhtml</title>
		<link>http://army8735.org/2010/06/13/766.html</link>
		<comments>http://army8735.org/2010/06/13/766.html#comments</comments>
		<pubDate>Sun, 13 Jun 2010 08:16:55 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=766</guid>
		<description><![CDATA[subhtml，顾名思义，即截取字符串时忽略html代码，介于后台输出的某些字符串可能包含html代码，因此就不能用简单的substr来处理。不过由于后台输出的代码都是标准的，因此也少了许多校验的必要。但是，譬如自闭合标签、嵌套标签等等，需要考虑的还是很多。
目前两个版本拼杀中，结果稍后公布……
function subhtml_yy(html, n){
	var str = html.split(//g), dstr;
	var m = 0;
	for (var i = 0, l = str.length; i < l;...]]></description>
			<content:encoded><![CDATA[<p>subhtml，顾名思义，即截取字符串时忽略html代码，介于后台输出的某些字符串可能包含html代码，因此就不能用简单的substr来处理。不过由于后台输出的代码都是标准的，因此也少了许多校验的必要。但是，譬如自闭合标签、嵌套标签等等，需要考虑的还是很多。</p>
<p>目前两个版本拼杀中，结果稍后公布……</p>
<pre class="brush:js">function subhtml_yy(html, n){
	var str = html.split(/<.+?>/g), dstr;
	var m = 0;
	for (var i = 0, l = str.length; i < l; i++) {
		dstr = str[i].replace(/([^\x00-\xff])/g, '$1 ');
		m += dstr.length;
		if (m > n) {
			str[i] = dstr.substr(0, m - n).replace(/([^\x00-\xff])\s/g, '$1');
			break;
		}
	}
	str.length = i + 1;
	var regexpstr = str.join('(<.+?>)')
	var parts = html.match(new RegExp(regexpstr));
	var unclose = [];
	for (var i = 1, l = parts.length; i < l; i++) {
		if (parts[i].match(/\/>$/))
			continue;
		else if (parts[i].match(/^<\//))
			unclose.pop();
		else
			unclose.push(parts[i]);
	}
	return (parts[0] + unclose.reverse().map(function(tag){
		return '&lt;/' + tag.match(/\w+/)[0] + '>';
	}).join(''));
}

function subhtml_army(str, limit) {
	var state = false, tag = [], c = '', i = j = index = index2 = 0;
	str = str.replace(/([^\x00-\xff])/g, '$1 ');
	for(var len = str.length; i < len &#038;&#038; j < limit; i++) {
		c = str.charAt(i);
		if(c == '<') {
			if(str.charAt(i + 1) == '/') {
				i += tag.pop().length + 1;
			}
			else {
				index = str.indexOf('>', i + 2);
				if(str.charAt(index - 1) != '/') {
					index2 = str.indexOf(' ', i + 2);
					if(index2 < index &#038;&#038; index2 != -1) {
						tag.push(str.slice(i + 1, index2));
					}
					else {
						tag.push(str.slice(i + 1, index));
					}
				}
				i = index;
			}
		}
		else {
			j++;
		}
   }
   str = str.substr(0, i).replace(/([^\x00-\xff])\s/g, '$1');
   if(tag.length) {
		str += '&lt;/' + tag.reverse().join('>&lt;/') + '>';
   }
   return str;
}</pre>
<h3>测试对象</h3>
<p>&lt;p&gt;&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;br/&gt;的&lt;strong&gt;关键词&lt;/strong&gt;的&lt;em&gt;关键词&lt;/em&gt;&lt;/p&gt;&lt;p&gt;的&lt;em&gt;关键词&lt;/em&gt;关键词关键词&lt;/p&gt;</p>
<h3>算法1（正则）</h3>
<p>结果（14）: &lt;p&gt;&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;br/&gt;的&lt;strong&gt;关键&lt;/strong&gt;&lt;/p&gt;</p>
<p>耗时（1000次）: 19</p>
<h3>算法2（逐字遍历）</h3>
<p>结果（14）: &lt;p&gt;&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;br/&gt;的&lt;strong&gt;关键&lt;/strong&gt;&lt;/p&gt;</p>
<p>耗时（1000次）: 13</p>
<hr />
<h3>测试对象2</h3>
<p>&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;</p>
<h3>算法1（正则）</h3>
<p>结果（14）: &lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;</p>
<p>耗时（1000次）: 17</p>
<h3>算法2（逐字遍历）</h3>
<p>结果（14）: &lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;的&lt;em style=&#8221;color:#f00&#8243;&gt;关键词&lt;/em&gt;</p>
<p>耗时（1000次）: 9</p>
<hr />
<h3>测试对象3</h3>
<p>关键词关键词&lt;em&gt;关键词&lt;/em&gt;关键词关键词关键词关键词关键词关键词关键词关键词关键词关键词</p>
<h3>算法1（正则）</h3>
<p>结果（14）: 关键词关键词&lt;em&gt;关&lt;/em&gt;</p>
<p>耗时（1000次）: 13</p>
<h3>算法2（逐字遍历）</h3>
<p>结果（14）: 关键词关键词&lt;em&gt;关&lt;/em&gt;</p>
<p>耗时（1000次）: 11</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/06/13/766.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>maxthon2.5.13和ie7内核出现冲突bug</title>
		<link>http://army8735.org/2010/06/04/764.html</link>
		<comments>http://army8735.org/2010/06/04/764.html#comments</comments>
		<pubDate>Fri, 04 Jun 2010 03:47:21 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=764</guid>
		<description><![CDATA[今早测试人员发现，新更新的maxthon2.5.13浏览土豆时全乱了，图片不加载js不执行，着实让人吓了一跳。苦心检查半天，才发现是遨游本身的问题……这种情况下看所有网站都会出错，奇怪的居然还是2.5.13正式版，看来遨游的测试这下错大了。
]]></description>
			<content:encoded><![CDATA[<p>今早测试人员发现，新更新的maxthon2.5.13浏览土豆时全乱了，图片不加载js不执行，着实让人吓了一跳。苦心检查半天，才发现是遨游本身的问题……这种情况下看所有网站都会出错，奇怪的居然还是2.5.13正式版，看来遨游的测试这下错大了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/06/04/764.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>flash player在不同浏览器中的表现也不一样</title>
		<link>http://army8735.org/2010/05/25/761.html</link>
		<comments>http://army8735.org/2010/05/25/761.html#comments</comments>
		<pubDate>Tue, 25 May 2010 07:28:30 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=761</guid>
		<description><![CDATA[前阵子adobe和乔布斯大战，我作为as的拥护者，自然会导向adobe一方，不过今天发现乔布斯的一些抨击倒并不是空穴来风。
经常出现的那种js切换图片效果，如果变成js切换flash的话，自然也没什么大不了。切换图片时要么是几张图片轮播，要么是直接更改图片的href；切换flash时要么时call一个flash的侦听方法，要么是直接重写这一段html代码。
在第2种方法的情况下，明显能感觉出来几种浏览器的区别，无论是老的flash player也好、还是新的10.1也好，皆是。这里面google不愧和adobe合作，chrome来回切换丝毫没有问题；firefox很偶尔才会在切换时出现问题；而ie则太频繁了。猜测这也和chrome单进程的模型有关，这样切换时上一个遗留的flash不会造成内存泄漏。
]]></description>
			<content:encoded><![CDATA[<p>前阵子adobe和乔布斯大战，我作为as的拥护者，自然会导向adobe一方，不过今天发现乔布斯的一些抨击倒并不是空穴来风。</p>
<p>经常出现的那种js切换图片效果，如果变成js切换flash的话，自然也没什么大不了。切换图片时要么是几张图片轮播，要么是直接更改图片的href；切换flash时要么时call一个flash的侦听方法，要么是直接重写这一段html代码。</p>
<p>在第2种方法的情况下，明显能感觉出来几种浏览器的区别，无论是老的flash player也好、还是新的10.1也好，皆是。这里面google不愧和adobe合作，chrome来回切换丝毫没有问题；firefox很偶尔才会在切换时出现问题；而ie则太频繁了。猜测这也和chrome单进程的模型有关，这样切换时上一个遗留的flash不会造成内存泄漏。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/05/25/761.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>土豆网的死循环</title>
		<link>http://army8735.org/2010/05/17/759.html</link>
		<comments>http://army8735.org/2010/05/17/759.html#comments</comments>
		<pubDate>Mon, 17 May 2010 07:27:55 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=759</guid>
		<description><![CDATA[http://blog.notsobad.cn/?p=644
今天内部流传了下这篇，哀悼日的死循环。凑巧那几天土豆的几个前端去北京参加adobe的大会，不知道谁写的这个东西……
其实这个bug做过开发的人都知道，经常会犯的小失误，只是实际使用的时候一下就能发觉，所以在自己测试的环节就能找到。但也由于这个缘故，使得人们经常没在意它……
]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.notsobad.cn/?p=644">http://blog.notsobad.cn/?p=644</a></p>
<p>今天内部流传了下这篇，哀悼日的死循环。凑巧那几天土豆的几个前端去北京参加adobe的大会，不知道谁写的这个东西……</p>
<p>其实这个bug做过开发的人都知道，经常会犯的小失误，只是实际使用的时候一下就能发觉，所以在自己测试的环节就能找到。但也由于这个缘故，使得人们经常没在意它……</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/05/17/759.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>发现一个flash player 10.1 rc4的bug</title>
		<link>http://army8735.org/2010/05/07/757.html</link>
		<comments>http://army8735.org/2010/05/07/757.html#comments</comments>
		<pubDate>Fri, 07 May 2010 08:31:18 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=757</guid>
		<description><![CDATA[adobe昨天公布的rc4，咱就迫不及待地用了，结果发现一个bug，这个在rc2中没有。
flash.net.NetStream，在使用seek(offset:Number)进行跳转后立刻togglePause()来暂停流（假设当前状态是播放），读取流的time属性并没有更新到offset。在rc2中确实更新正确了。
]]></description>
			<content:encoded><![CDATA[<p>adobe昨天公布的rc4，咱就迫不及待地用了，结果发现一个bug，这个在rc2中没有。</p>
<p>flash.net.NetStream，在使用seek(offset:Number)进行跳转后立刻togglePause()来暂停流（假设当前状态是播放），读取流的time属性并没有更新到offset。在rc2中确实更新正确了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/05/07/757.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>不使用execution预加载</title>
		<link>http://army8735.org/2010/05/07/754.html</link>
		<comments>http://army8735.org/2010/05/07/754.html#comments</comments>
		<pubDate>Fri, 07 May 2010 05:36:52 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[预加载]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=754</guid>
		<description><![CDATA[预加载有很多种，dom预加载、iframe预加载、ajax预加载等等。但是有另外一种简洁安全的做法：

对ie使用Image来预加载内容
其它浏览器使用动态的object标签

例如：
window.onload = function () {

    var i = 0,
        max...]]></description>
			<content:encoded><![CDATA[<p>预加载有很多种，dom预加载、iframe预加载、ajax预加载等等。但是有另外一种简洁安全的做法：</p>
<ul>
<li>对ie使用Image来预加载内容</li>
<li>其它浏览器使用动态的object标签</li>
</ul>
<p>例如：</p>
<pre class="brush:js">window.onload = function () {

    var i = 0,
        max = 0,
        o = null,

        // list of stuff to preload
        preload = [
            'http://tools.w3clubs.com/pagr2/.sleep.expires.png',
            'http://tools.w3clubs.com/pagr2/.sleep.expires.js',
            'http://tools.w3clubs.com/pagr2/.sleep.expires.css'
        ],
        isIE = navigator.appName.indexOf('Microsoft') === 0;

    for (i = 0, max = preload.length; i &lt; max; i += 1) {

        if (isIE) {
            new Image().src = preload[i];
            continue;
        }
        o = document.createElement('object');
        o.data = preload[i];

        // IE stuff, otherwise 0x0 is OK
        //o.width = 1;
        //o.height = 1;
        //o.style.visibility = "hidden";
        //o.type = "text/plain"; // IE
        o.width  = 0;
        o.height = 0;

        // only FF appends to the head
        // all others require body
        document.body.appendChild(o);
    }

};</pre>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/05/07/754.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>最近在练口琴</title>
		<link>http://army8735.org/2010/04/29/752.html</link>
		<comments>http://army8735.org/2010/04/29/752.html#comments</comments>
		<pubDate>Thu, 29 Apr 2010 06:44:19 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[其它]]></category>
		<category><![CDATA[半音阶]]></category>
		<category><![CDATA[口琴]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=752</guid>
		<description><![CDATA[年前玩了空之轨迹后突然想起来学口琴，大概自己的几大爱好中就差了门艺术吧，于是乎就练起来了。起初尝试布鲁斯，后来因为压音实在太过苦恼（不是不会，其实我学会了压音了已经），后来转战半音阶，而且半音阶口琴也比较适合动漫、流行等音乐主奏。
目前所有学习后的曲目都放在http://www.tudou.com/home/army8735#tui-tab_0这里，可以感觉得到每支新曲子都是有进步的。要吹的还很多，大家有任何喜欢的歌或者建议都可以留下来，我一个个去试～
]]></description>
			<content:encoded><![CDATA[<p>年前玩了空之轨迹后突然想起来学口琴，大概自己的几大爱好中就差了门艺术吧，于是乎就练起来了。起初尝试布鲁斯，后来因为压音实在太过苦恼（不是不会，其实我学会了压音了已经），后来转战半音阶，而且半音阶口琴也比较适合动漫、流行等音乐主奏。</p>
<p>目前所有学习后的曲目都放在<a href="http://www.tudou.com/home/army8735#tui-tab_0">http://www.tudou.com/home/army8735#tui-tab_0</a>这里，可以感觉得到每支新曲子都是有进步的。要吹的还很多，大家有任何喜欢的歌或者建议都可以留下来，我一个个去试～</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/04/29/752.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>土豆映像节颁奖典礼</title>
		<link>http://army8735.org/2010/04/19/749.html</link>
		<comments>http://army8735.org/2010/04/19/749.html#comments</comments>
		<pubDate>Mon, 19 Apr 2010 01:39:55 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=749</guid>
		<description><![CDATA[http://www.tudou.com/programs/view/fL3GI1M-huc
从2月开始接手第2期到现在，终于在高潮后走到尾声了。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.tudou.com/programs/view/fL3GI1M-huc">http://www.tudou.com/programs/view/fL3GI1M-huc</a></p>
<p>从2月开始接手第2期到现在，终于在高潮后走到尾声了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/04/19/749.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>土豆rss主页</title>
		<link>http://army8735.org/2010/04/06/746.html</link>
		<comments>http://army8735.org/2010/04/06/746.html#comments</comments>
		<pubDate>Tue, 06 Apr 2010 10:44:00 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=746</guid>
		<description><![CDATA[冒充了一回设计，我那水平也只能这样了：
http://rss.tudou.com/
]]></description>
			<content:encoded><![CDATA[<p>冒充了一回设计，我那水平也只能这样了：</p>
<p><a href="http://rss.tudou.com/" target="_blank">http://rss.tudou.com/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/04/06/746.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>事件侦听中的逻辑关联</title>
		<link>http://army8735.org/2010/04/02/740.html</link>
		<comments>http://army8735.org/2010/04/02/740.html#comments</comments>
		<pubDate>Fri, 02 Apr 2010 05:35:33 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[事件侦听]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=740</guid>
		<description><![CDATA[昨日，土豆的前端开发人员们就事件侦听之间是否应该出现逻辑关联展开了一场辩论。具体争论的问题如下：
document.body.addEventListener("click", functionA, false);
document.body.addEventListener("click", functionB, false);

functionA() {
    document.body.removeEventListener("click", functionB, false);
}
functionB() {
}
此时如果我在页面的body上点击了一下，会发生什么？回答有两种：A和B都执行、但下一次点击B不会再被执行了；A执行B不被执行、且以后B都不会执行。
答案是什么并不重要，关键是要看浏览器的js引擎如何处理事件侦听。分别假设上面两种答案都是正确的话，那么它们各自的处理方式应该如下：

点击触发后，A和B方法同时收到侦听并触发，此时它们是并行的。因此都会产生调用并存入内存队列中，等待出列执行。
点击触发后，A由于先注册所以先触发侦听，B完全没有任何反应，此时它们是串行的。因此A先进入队列，执行过程中移除了B的侦听，B也就永远销声匿迹了。

那么我们常见的浏览器中的js引擎都是如何实现的呢？因为js是函数式单线程的，所以正确答案是第2个。但是包括标准推荐的做法在内，我的观点是不应该在事件侦听中出现逻辑关联，也就是耦合。
如果两个事件侦听出现了依赖逻辑互相确定执行的话，那么它们本身就应该写在一个事件侦听里面，然后通过重构相分离。依然以上面的为例，B方法的执行依赖于A方法中的某个逻辑的话，更好的做法应该是这样：
document.body.addEventListener("click", listener, false);

function listener() {
   ...]]></description>
			<content:encoded><![CDATA[<p>昨日，土豆的前端开发人员们就事件侦听之间是否应该出现逻辑关联展开了一场辩论。具体争论的问题如下：</p>
<pre class="brush:js">document.body.addEventListener("click", functionA, false);
document.body.addEventListener("click", functionB, false);

functionA() {
    document.body.removeEventListener("click", functionB, false);
}
functionB() {
}</pre>
<p>此时如果我在页面的body上点击了一下，会发生什么？回答有两种：A和B都执行、但下一次点击B不会再被执行了；A执行B不被执行、且以后B都不会执行。</p>
<p>答案是什么并不重要，关键是要看浏览器的js引擎如何处理事件侦听。分别假设上面两种答案都是正确的话，那么它们各自的处理方式应该如下：</p>
<ol>
<li>点击触发后，A和B方法同时收到侦听并触发，此时它们是并行的。因此都会产生调用并存入内存队列中，等待出列执行。</li>
<li>点击触发后，A由于先注册所以先触发侦听，B完全没有任何反应，此时它们是串行的。因此A先进入队列，执行过程中移除了B的侦听，B也就永远销声匿迹了。</li>
</ol>
<p>那么我们常见的浏览器中的js引擎都是如何实现的呢？因为js是函数式单线程的，所以正确答案是第2个。但是包括标准推荐的做法在内，我的观点是不应该在事件侦听中出现逻辑关联，也就是耦合。</p>
<p>如果两个事件侦听出现了依赖逻辑互相确定执行的话，那么它们本身就应该写在一个事件侦听里面，然后通过重构相分离。依然以上面的为例，B方法的执行依赖于A方法中的某个逻辑的话，更好的做法应该是这样：</p>
<pre class="brush:js">document.body.addEventListener("click", listener, false);

function listener() {
    if(A()) return;
    B();
}
functionA() {
    if(/*某个条件达成*/) return true;
    return false;
}
functionB() {
}</pre>
<p>如果出现了不同事件侦听有逻辑关联的情况的话，那么最初的设计可能就需要考虑一下。反对者（其实就是指<a href="http://www.limboy.com/" target="_blank">某人</a>）的论据则是灵活度以及js的函数式和单线程特性。在日益复杂的情势中，前端是否也应该像java摒弃多继承一样，而降低某些灵活度呢？</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/04/02/740.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>as3和java的byte编码</title>
		<link>http://army8735.org/2010/03/17/736.html</link>
		<comments>http://army8735.org/2010/03/17/736.html#comments</comments>
		<pubDate>Wed, 17 Mar 2010 05:40:35 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[byte编码]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=736</guid>
		<description><![CDATA[as3和java互相通信，这是现在经常能看到的一种方式了。很多大型应用、富客户端和服务器通信、webgame等，基本上都选择了这一组合。
这几天我在研究as3和java的socket通信时，遇到了点问题，后来结果证明，我是杞人忧天了……
socket通信as3和java都有比较底层的api可以使用，比如传输byte流。我们可以通过对一个字符串编码进行实验：
String s = "army阿米";
byte[] b = s.getBytes("UTF-8");
var s:String = "army阿米";
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes(s);
值得一提的是，as3默认编码就是UTF-8，这点无需关心；java的默认编码和操作系统平台有关，比如我的机子默认是GBK编码，如果要和as3保持一致，就得在读取时手动指定。如果不知道默认编码是什么，可以通过FileWriter.getEncodeing()方法来取得。
这两种语言在编码的结果上是一致的（废话，编码可是个标准），但是在显示方面就不一样了，这也导致我郁闷了半天为何显示结果不相同？
1100001
1110010
1101101
1111001
11101001
10011000
10111111
11100111
10110001
10110011
以上是最终存储的结果。但是问题来了，as3的ByteArray类用来存储字节，其中每个字节是无符号的；java中byte却是有符号的，它的最高为用来表示正负。因此打印的时候一个是正数（范围0到255），另外一个就变成了负数（范围-128到127）。
]]></description>
			<content:encoded><![CDATA[<p>as3和java互相通信，这是现在经常能看到的一种方式了。很多大型应用、富客户端和服务器通信、webgame等，基本上都选择了这一组合。</p>
<p>这几天我在研究as3和java的socket通信时，遇到了点问题，后来结果证明，我是杞人忧天了……</p>
<p>socket通信as3和java都有比较底层的api可以使用，比如传输byte流。我们可以通过对一个字符串编码进行实验：</p>
<pre class="brush:java">String s = "army阿米";
byte[] b = s.getBytes("UTF-8");</pre>
<pre class="brush:as3">var s:String = "army阿米";
var ba:ByteArray = new ByteArray();
ba.writeUTFBytes(s);</pre>
<p>值得一提的是，as3默认编码就是UTF-8，这点无需关心；java的默认编码和操作系统平台有关，比如我的机子默认是GBK编码，如果要和as3保持一致，就得在读取时手动指定。如果不知道默认编码是什么，可以通过FileWriter.getEncodeing()方法来取得。</p>
<p>这两种语言在编码的结果上是一致的（废话，编码可是个标准），但是在显示方面就不一样了，这也导致我郁闷了半天为何显示结果不相同？</p>
<pre class="brush:as3">1100001
1110010
1101101
1111001
11101001
10011000
10111111
11100111
10110001
10110011</pre>
<p>以上是最终存储的结果。但是问题来了，as3的ByteArray类用来存储字节，其中每个字节是无符号的；java中byte却是有符号的，它的最高为用来表示正负。因此打印的时候一个是正数（范围0到255），另外一个就变成了负数（范围-128到127）。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/03/17/736.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Project Darkstar虽死，RedDwarf Server已活</title>
		<link>http://army8735.org/2010/03/11/731.html</link>
		<comments>http://army8735.org/2010/03/11/731.html#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:39:34 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[其它]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=731</guid>
		<description><![CDATA[Sun被Oracle收购后，停掉了不少开源项目，其中就有我关心的《Project Darkstar》。今日突发奇想又登录了下老的网站主页，发现关闭之后多出了一个链接：
http://www.reddwarfserver.org/。
哦也，开源之火生生不息！目前的0.10.0版本其实就是Project Darkstar停之前最新的发布版本。期待你的表现，某人赶快给我研究去……嘿嘿……
]]></description>
			<content:encoded><![CDATA[<p>Sun被Oracle收购后，停掉了不少开源项目，其中就有我关心的《Project Darkstar》。今日突发奇想又登录了下老的网站主页，发现关闭之后多出了一个链接：</p>
<p><a href="http://www.reddwarfserver.org/">http://www.reddwarfserver.org/</a>。</p>
<p>哦也，开源之火生生不息！目前的0.10.0版本其实就是Project Darkstar停之前最新的发布版本。期待你的表现，<a href="http://www.david0446.com/" target="_blank">某人</a>赶快给我研究去……嘿嘿……</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/03/11/731.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TUI: Tudou’s Javascript Library</title>
		<link>http://army8735.org/2010/03/09/723.html</link>
		<comments>http://army8735.org/2010/03/09/723.html#comments</comments>
		<pubDate>Tue, 09 Mar 2010 01:59:18 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[tui]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=723</guid>
		<description><![CDATA[这是由Dexter同学厚积薄发的作品，分为第三方类库、核心、输入输出、视图、界面组件、工具以及插件等几大部分。

]]></description>
			<content:encoded><![CDATA[<p>这是由Dexter同学厚积薄发的作品，分为第三方类库、核心、输入输出、视图、界面组件、工具以及插件等几大部分。</p>
<p><a href="http://army8735.org/wp-content/uploads/2010/03/tui.png" target="_blank"><img class="alignnone size-medium wp-image-726" title="tui" src="http://army8735.org/wp-content/uploads/2010/03/tui-174x300.png" alt="" width="174" height="300" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/03/09/723.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>JAcld beta1</title>
		<link>http://army8735.org/2010/03/07/708.html</link>
		<comments>http://army8735.org/2010/03/07/708.html#comments</comments>
		<pubDate>Sun, 07 Mar 2010 09:41:58 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[JAcld]]></category>
		<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=708</guid>
		<description><![CDATA[http://code.google.com/p/jacld/
预览地址：http://jacld.googlecode.com/svn/trunk/bin/index.html
JAcld(Javascript &#38; Actionscript CapsLock Detection)是一款基于as和js的大写锁定检测工具，大小只有1k多，作用于web上。
今天终于搞定了针对webkit的特殊修正，所以目前主要浏览器都能使用了。不过还有2点遗憾：

webkit由于flash的聚焦bug，无法通过flash检测，因此使用了js检测。它跟flash相比起来体验方面要稍微差一点。
ie下亦存在聚焦问题，当使用tab键切换focus到输入框上时，有一定几率聚焦失败。

综合而言beta1倒是可以尝试使用的。谁能研究出搞定那2个bug的方法就谢天谢地了……
]]></description>
			<content:encoded><![CDATA[<p><a href="http://code.google.com/p/jacld/">http://code.google.com/p/jacld/</a></p>
<p>预览地址：<a href="http://jacld.googlecode.com/svn/trunk/bin/index.html">http://jacld.googlecode.com/svn/trunk/bin/index.html</a></p>
<p>JAcld(Javascript &amp; Actionscript CapsLock Detection)是一款基于as和js的大写锁定检测工具，大小只有1k多，作用于web上。</p>
<p>今天终于搞定了针对webkit的特殊修正，所以目前主要浏览器都能使用了。不过还有2点遗憾：</p>
<ol>
<li>webkit由于flash的聚焦bug，无法通过flash检测，因此使用了js检测。它跟flash相比起来体验方面要稍微差一点。</li>
<li>ie下亦存在聚焦问题，当使用tab键切换focus到输入框上时，有一定几率聚焦失败。</li>
</ol>
<p>综合而言beta1倒是可以尝试使用的。谁能研究出搞定那2个bug的方法就谢天谢地了……</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/03/07/708.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>[译]理解删除</title>
		<link>http://army8735.org/2010/03/05/691.html</link>
		<comments>http://army8735.org/2010/03/05/691.html#comments</comments>
		<pubDate>Fri, 05 Mar 2010 07:57:28 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[删除]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=691</guid>
		<description><![CDATA[http://perfectionkills.com/understanding-delete/
原文作者是在读《Object-Oriented Javascript》的Function章节后有感，写下的一篇博文。
书中有一句话：function其实就是一个普通变量——它可以被复制到另一个变量中而不会被删除。如果这样解释的话，这里有个例子：
//army注：这一源代码片段是在Firebug下的Console控制台运行的，放在页面中需改写
var sum = function(a, b) {return a + b;}
var add = sum;
delete sum;
true
typeof sum;
"undefined"
忽略代码中省略的两个分号，你注意到这个代码片段的问题了吗？按那句话所说，删除sum不应该成功；delete语句返回的值不可能是true；typeof sum的结果不会是&#8221;undefined&#8221;。可是事实却非如此，所有的这一切都是因为：Javascript中不可能删除变量。至少不能以这种方式删除。
 这是为什么呢？
要回答这个问题，我们需要理解delete操作符是怎么运作的：即什么可以删除、什么不可以删除、为什么？
原理
我们为什么可以这样删除对象的属性？
var o = {...]]></description>
			<content:encoded><![CDATA[<p><a href="http://perfectionkills.com/understanding-delete/">http://perfectionkills.com/understanding-delete/</a></p>
<p>原文作者是在读<a href="http://www.amazon.com/Object-Oriented-JavaScript-high-quality-applications-libraries/dp/1847194141" target="_blank">《Object-Oriented Javascript》</a>的Function章节后有感，写下的一篇博文。</p>
<p>书中有一句话：function其实就是一个普通变量——它可以被复制到另一个变量中而不会被删除。如果这样解释的话，这里有个例子：</p>
<pre class="brush:js">//army注：这一源代码片段是在Firebug下的Console控制台运行的，放在页面中需改写
var sum = function(a, b) {return a + b;}
var add = sum;
delete sum;
true
typeof sum;
"undefined"</pre>
<p>忽略代码中省略的两个分号，你注意到这个代码片段的问题了吗？按那句话所说，删除sum不应该成功；delete语句返回的值不可能是true；typeof sum的结果不会是&#8221;undefined&#8221;。可是事实却非如此，所有的这一切都是因为：<strong>Javascript中不可能删除变量。至少不能以这种方式删除。</strong></p>
<p><strong> </strong>这是为什么呢？</p>
<p>要回答这个问题，我们需要理解delete操作符是怎么运作的：即什么可以删除、什么不可以删除、为什么？</p>
<h3>原理</h3>
<p>我们为什么可以这样删除对象的属性？</p>
<pre class="brush:js">var o = { x: 1 };
delete o.x; // true
o.x; // undefined</pre>
<p>但是变量就完全不同了：</p>
<pre class="brush:js">var x = 1;
delete x; // false
x; // 1</pre>
<p>方法声明也是：</p>
<pre class="brush:js">function x(){}
delete x; // false
typeof x; // "function"</pre>
<p>注意当一个属性<strong>不能被删除时</strong>，它会返回false。</p>
<p>要解释这些，我们首先要理解变量的实例化以及属性的特性——很遗憾，这些很少在Javascript书籍中被提到。下面这节将做个简明的介绍，它很容易理解。如果你不关心<strong>一切为何按照它目前的样子进行工作</strong>的话，可以跳过此节。</p>
<p><strong>代码类型</strong></p>
<p><strong></strong>在ECMAScript中共有3种执行方式：Global、Function、Eval。这些类型某种程度上正如其名，但还不足：</p>
<p>当一份源代码作为程序运行时，它在全局作用域内执行，就会被认为是Global代码。在浏览器环境中，script标签通常被解析为一段程序，因此它是全局代码。</p>
<p>直接运行在function内的代码显然是Function代码。例如浏览器中的&lt;p onclick=&#8221;&#8230;&#8221;&gt;。</p>
<p>另外，作为参数传入evel函数的源代码字符串会以Eval方式执行。我们很快就会看到其特殊性。</p>
<p><strong> 运行上下文</strong></p>
<p><strong></strong>当ECMAScript代码运行时，它是发生在一个运行上下文（execution context）中的。运行上下文是个抽象实体，可以帮助我们理解作用域和变量实例化是如何工作的。这3种代码各自有自己的运行上下文。当一个function执行时，就可以说控制器进入Function运行上下文中；当全局代码执行时，就进入了Global运行上下文。</p>
<p>如你所知，运行上下文可以逻辑递归。首先一段代码肯定有自己的Global运行上下文；如果调用了function，那么function也有自己的运行上下文；如果function又调用了另外一个function……如此递归。甚至function调用了它本身，每次也会产生一个新的运行上下文。</p>
<p><strong>激活变量对象/激活对象</strong></p>
<p><strong></strong>每一个运行上下文都和一个变量对象（Variable Object）相关联。类似运行上下文，变量对象是一个抽象实体，一种描述变量实例化的机制。现在有趣的事情来了，源代码中的变量和函数声明，实际上<strong>成为这个变量对象上的一组属性。</strong></p>
<p><strong></strong>当控制器进入Global方式的运行上下文时，一个全局对象被创建用来作为变量对象。这就解释了为何定义的全局方法成为了全局对象的属性。</p>
<pre class="brush:js">/* remember that `this` refers to global object when in global scope */
var GLOBAL_OBJECT = this;

var foo = 1;
GLOBAL_OBJECT.foo; // 1
foo === GLOBAL_OBJECT.foo; // true

function bar(){}
typeof GLOBAL_OBJECT.bar; // "function"
GLOBAL_OBJECT.bar === bar; // true</pre>
<p>ok，当全局变量成为全局对象的属性时，方法内的局部变量发生了什么事情呢？行为是类似的：它们变成了一个变量对象的一组属性。唯一的不同之处在于，此处的变量对象不是全局对象，但仍然是个激活对象。激活对象在每次进入方法创建运行上下文时都会被创建。</p>
<p>不仅function内的变量和方法声明会成为激活对象的属性，相同的事情还发生在传入的function参数身上，它在arguments下产生了一个Arguments对象。注意激活对象是内部机制，不能够被程序直接访问。</p>
<pre class="brush:js">(function(foo){

	var bar = 2;
	function baz(){}

	/*
	In abstract terms,

	Special `arguments` object becomes a property of containing function's Activation object:
	ACTIVATION_OBJECT.arguments; // Arguments object

	...as well as argument `foo`:
	ACTIVATION_OBJECT.foo; // 1

	...as well as variable `bar`:
	ACTIVATION_OBJECT.bar; // 2

	...as well as function declared locally:
	typeof ACTIVATION_OBJECT.baz; // "function"
	*/

})(1);</pre>
<p>最后，eval中的变量声明会作为<strong>它被引用的上下文的变量对象的属性</strong>。eval代码只是使用它被调用的运行环境的变量对象。</p>
<pre class="brush:js">var GLOBAL_OBJECT = this;

/* `foo` is created as a property of calling context Variable object,
which in this case is a Global object */

eval('var foo = 1;');
GLOBAL_OBJECT.foo; // 1

(function(){

	/* `bar` is created as a property of calling context Variable object,
	which in this case is an Activation object of containing function */

	eval('var bar = 1;');

	/*
	In abstract terms,
	ACTIVATION_OBJECT.bar; // 1
	*/

})();</pre>
<p><strong>属性特性</strong></p>
<p><strong></strong>终于说到这里了。现在我们已经清楚变量声明时发生的事情，剩下就是理解属性特性。每个属性可以有任意个以下特性——只读、不可枚举、不可删除、内部的。你可以把它们理解为属性上的选项——有或者没有。因为今天讨论的目的，这里只说不可删除特性。</p>
<p>当声明变量或者函数时，它们成为变量对象（对于function代码来说是激活对象，对于全局代码来说是全局对象）的属性，这些属性产生的同时具有不可删除特性。然而，任何直接或者内部的属性分配在创建属性时都没有不可删除特性。这就是为什么有的属性可以删除有的不可以。</p>
<pre class="brush:js">var GLOBAL_OBJECT = this;

/*  `foo` is a property of a Global object.
It is created via variable declaration and so has DontDelete attribute.
This is why it can not be deleted. */

var foo = 1;
delete foo; // false
typeof foo; // "number"

/*  `bar` is a property of a Global object.
It is created via function declaration and so has DontDelete attribute.
This is why it can not be deleted either. */

function bar(){}
delete bar; // false
typeof bar; // "function"

/*  `baz` is also a property of a Global object.
However, it is created via property assignment and so has no DontDelete attribute.
This is why it can be deleted. */

GLOBAL_OBJECT.baz = 'blah';
delete GLOBAL_OBJECT.baz; // true
typeof GLOBAL_OBJECT.baz; // "undefined"</pre>
<p><strong>内建和不可删除</strong></p>
<p><strong></strong>一个属性上的特殊特性控制了它能否被删除。注意一些内建的的属性一开始就有不可删除特性，它们是永远不能被删除的。例如arguments、函数实例的length属性等。</p>
<pre class="brush:js">(function(){

	/* can't delete `arguments`, since it has DontDelete */

	delete arguments; // false
	typeof arguments; // "object"

	/* can't delete function's `length`; it also has DontDelete */

	function f(){}
	delete f.length; // false
	typeof f.length; // "number"

})();</pre>
<p>函数的形参同样也有不可删除特性：</p>
<pre class="brush:js">(function(foo, bar){

	delete foo; // false
	foo; // 1

	delete bar; // false
	bar; // 'blah'

})(1, 'blah');</pre>
<p><strong>未声明的分配</strong></p>
<p><strong></strong>未声明的变量会在全局对象上生成属性，除非在作用域链中于全局对象之前找到这个变量声明。现在我们知道了属性分配和变量声明之间的区别——后者具有不可删除特性而前者没有——这就解释了为何未经声明的变量可以被删除。</p>
<pre class="brush:js">var GLOBAL_OBJECT = this;

/* create global property via variable declaration; property has DontDelete */
var foo = 1;

/* create global property via undeclared assignment; property has no DontDelete */
bar = 2;

delete foo; // false
typeof foo; // "number"

delete bar; // true
typeof bar; // "undefined"</pre>
<p>注意在属性创建时特性已经被定义了（除了ie），再次分配的话并不会修改已经存在的特性。</p>
<pre class="brush:js">/* `foo` is created as a property with DontDelete */
function foo(){}

/* Later assignments do not modify attributes. DontDelete is still there! */
foo = 1;
delete foo; // false
typeof foo; // "number"

/* But assigning to a property that doesn't exist,
creates that property with empty attributes (and so without DontDelete) */

this.bar = 1;
delete bar; // true
typeof bar; // "undefined"</pre>
<h3>Firebug的困惑</h3>
<p>那么在Firebug中发生了什么？为何在控制台console中的声明变量可以被删除？还记得前面说的吗，当eval代码进行变量声明时有个特殊的行为，这些声明的变量没有不可删除特性，所以它们可以被删除。</p>
<p><strong>通过eval删除变量</strong></p>
<p><strong></strong>由于eval行为的特殊性，再加上ECMAScript允许我们删除没有不可删除特性的属性，在同一运行上下文中函数声明可以覆盖已经声明的变量。</p>
<pre class="brush:js">function x(){ }
var x;
typeof x; // "function"</pre>
<p>注意函数声明是如何获得优先权并覆盖掉原有变量声明的，这是因为函数声明的实例化晚于变量声明的实例化，并且允许覆盖。不仅如此，它还会覆盖属性特性。假如我们通过eval方式来声明函数，也会这样。</p>
<pre class="brush:js">var x = 1;

/* Can't delete, `x` has DontDelete */

delete x; // false
typeof x; // "number"

eval('function x(){}');

/* `x` property now references function, and should have no DontDelete */

typeof x; // "function"
delete x; // should be `true`
typeof x; // should be "undefined"</pre>
<p>不幸的是，我在尝试这段代码的时候失败了，可能哪里出了点错误。</p>
<h3>浏览器的让步</h3>
<p>原理已然弄清，实践更为重要。浏览器们都按照标准做了吗？答案是：大部分是。</p>
<p>我对以下现代浏览器做了一个测试：Opera 7.54+、Firefox 1.0+、Safari 3.1.2+、Chrome 4+。<br />
Safari 2.x和3.0.4在删除函数参数时有问题，这些属性看上去没有不可删除特性，因此它们竟被删除了。Safari 2.x的问题还不止这些——删除没有引用的变量（如delete 1，army注：我感觉这应该是常量才对）会抛出异常；函数声明具有可删除特性（变量声明没有）；eval中的变量声明有不可删除特性（函数声明没有）。</p>
<p>类似的，Konqueror（3.5而非4.3）在删除没有引用的变量的时候会抛出异常，并且允许删除函数参数。</p>
<p><strong>Gecko的不可删除特性bug</strong></p>
<p><strong></strong>基于Gecko 1.8.x的浏览器——Firefox 2.x、Camino 1.x、Seamonkey 1.x等等——有个很有趣的bug：可以删除一个属性的不可删除特性，尽管这个属性是通过变量声明或者函数声明而产生的。</p>
<pre class="brush:js">function foo(){}
delete foo; // false (as expected)
typeof foo; // "function" (as expected)

/* now assign to a property explicitly */

this.foo = 1; // erroneously clears DontDelete attribute
delete foo; // true
typeof foo; // "undefined"

/* note that this doesn't happen when assigning property implicitly */

function bar(){}
bar = 1;
delete bar; // false
typeof bar; // "number" (although assignment replaced property)</pre>
<p>让人震惊的是，IE5.5到IE8居然全部通过了测试！除了那个删除没有引用的变量外。然而即使如此，IE却在另外的方面有着严重的bug！这些bug很隐晦，和全局变量有关。</p>
<h3>IE的bug</h3>
<p>在IE中（至少是6到8版本），下面的表达式会抛出异常。</p>
<pre class="brush:js">this.x = 1;
delete x; // TypeError: Object doesn't support this action</pre>
<p>再来看看另外一个，非常有趣：</p>
<pre class="brush:js">var x = 1;
delete this.x; // TypeError: Cannot delete 'this.x'</pre>
<p>这个情况看上去好像全局代码上的变量声明没有在全局对象上产生属性，甚至删除操作时会抛出异常。</p>
<pre class="brush:js">this.x = 1;

delete this.x; // TypeError: Object doesn't support this action
typeof x; // "number" (still exists, wasn't deleted as it should have been!)

delete x; // TypeError: Object doesn't support this action
typeof x; // "number" (wasn't deleted again)</pre>
<p>与之相反的是，未声明变量却具有可删除特性。</p>
<pre class="brush:js">x = 1;
delete x; // true
typeof x; // "undefined"</pre>
<p>但是你若通过this来引用全局的话却又会异常：</p>
<pre class="brush:js">x = 1;
delete this.x; // TypeError: Cannot delete 'this.x'</pre>
<p>如果概括一下的话，那就是在全局代码中delete this.x从未成功过。</p>
<p>我在2009年9月发现了的这一问题，Garrett Smith回答我说“IE中全局变量对象被实现为一个JScript对象，全局对象却被实现为一个宿主对象（host object）”。（army注：延伸阅读hax的文章：<a href="http://hax.javaeye.com/blog/349569" target="_blank">http://hax.javaeye.com/blog/349569</a>）</p>
<p>我们可以通过一些测试在某种程度上验证这一回答。注意this和window看上去引用了同一对象（如果===全等操作符可以信赖的话），但是变量对象（函数返回的值）却和this不同。</p>
<pre class="brush:js">/* in Global code */
function getBase(){ return this; }

getBase() === this.getBase(); // false
this.getBase() === this.getBase(); // true
window.getBase() === this.getBase(); // true
window.getBase() === getBase(); // false</pre>
<h3>删除和宿主对象</h3>
<p>关于delete操作的规则如下：</p>
<ul>
<li>如果操作数中没有引用值，返回true</li>
<li>如果对象没有直接属性，返回true</li>
<li>如果属性存在并且具有不可删除特性，返回false</li>
<li>其它情况，移除属性并且返回true</li>
</ul>
<p>然而，IE环境的delete操作在删除宿主对象时却经常让人捉摸不透。</p>
<pre class="brush:js">/* "alert" is a direct property of `window` (if we were to believe `hasOwnProperty`) */
window.hasOwnProperty('alert'); // true

delete window.alert; // true
typeof window.alert; // "function"</pre>
<p>最好的习惯是从不信任宿主对象。</p>
<h3>ES5严格模式</h3>
<p>ECMAScript 5的严格模式带来了哪些条规？它引进了诸多限制。比如删除引用变量、函数参数和标志符的时候会抛出SyntaxError。另外，如果属性包含[[Configurable]] == false键值对，删除时会抛出TypeError。</p>
<pre class="brush:js">(function(foo){

"use strict"; // enable strict mode within this function

var bar;
function baz(){}

delete foo; // SyntaxError (when deleting argument)
delete bar; // SyntaxError (when deleting variable)
delete baz; // SyntaxError (when deleting variable created with function declaration)

/* `length` of function instances has { [[Configurable]] : false } */

delete (function(){}).length; // TypeError

})();</pre>
<p>还有，删除未声明变量时也会抛出SyntaxError：</p>
<pre class="brush:js">"use strict";
delete i_dont_exist; // SyntaxError</pre>
<p>这和在严格模式中使用未声明的变量类似：</p>
<pre class="brush:js">"use strict";
i_dont_exist = 1; // ReferenceError</pre>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/03/05/691.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>[转]Google Nexus One上的Flash Player 10.1演示</title>
		<link>http://army8735.org/2010/02/25/689.html</link>
		<comments>http://army8735.org/2010/02/25/689.html#comments</comments>
		<pubDate>Thu, 25 Feb 2010 03:56:24 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[flash player 10.1]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=689</guid>
		<description><![CDATA[在7yue的blog上看到fp10.1的表现让人兴奋不已，希望Adobe摆脱“很有压力，才有推力”的形象……
http://www.7yue.com/post/430.html
]]></description>
			<content:encoded><![CDATA[<p>在7yue的blog上看到fp10.1的表现让人兴奋不已，希望Adobe摆脱“很有压力，才有推力”的形象……</p>
<p><a href="http://www.7yue.com/post/430.html">http://www.7yue.com/post/430.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/25/689.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web端语法高亮原理：走进jssc的世界（五）</title>
		<link>http://army8735.org/2010/02/23/669.html</link>
		<comments>http://army8735.org/2010/02/23/669.html#comments</comments>
		<pubDate>Tue, 23 Feb 2010 06:45:47 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[jssc]]></category>
		<category><![CDATA[系列文章]]></category>
		<category><![CDATA[语法高亮原理]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=669</guid>
		<description><![CDATA[整体流程
终于说到整体流程上了。之前的文章一直在解说as中如何来做词法分析，js方面丝毫未提，更没说jssc到底在页面上是怎么工作的。现在，就来详细地解释一下。
环境需求：

现代浏览器（废话）
装有Adobe Flash Player插件，版本号为9或9以上
javascript启用
页面中放入jssc.swf文件

大致流程：

swf文件载入完毕
内嵌在swf中的js首先被执行，寻找页面中所有符合规则的pre节点
顺序遍历这些pre节点，提取每个pre节点的文本内容（即原始代码）
将原始代码传递给swf
swf对传递来的原始代码进行词法分析，并生成一段结果html片段（即一串li节点）
将结果传递回js
js对结果进行包装（一串li节点放入ol节点中，以及标题头、边距和复制等等）
将对应的原始pre节点隐藏（display:none）
将新生成的内容插入原始pre节点的前面

可以看出，js和as耦合的地方在哪里，以及它们之间是如何相互合作的。下面将对以上9个步骤细细说来，希望更多的开发者能提出改进意见～
1.载入swf
这里没什么好说的，在页面底部加入flash标签即可。值得注意的是不同浏览器中标签有所区别，理想情况下可以使用swfobject来插入标准的html标签。不过为了兼容以及简单，一般我是这样做的：
&#60;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5" style="position:absolute;visibility:hidden;"&#62;
	&#60;param name="movie" value="jssc5.swf"/&#62;
	&#60;param name="flashvars" value="find=brush"/&#62;
	&#60;embed src="jssc5.swf" flashvars="find=brush" name="jssc5" type="application/x-shockwave-flash" style="position:absolute;visibility:hidden;"/&#62;
&#60;/object&#62;
这里面有许多可配置的地方。
object的id和embed的name必须一致且唯一（应该是唯二才对），为了满足不同浏览器的需要。我设为jssc5，这也是默认值。如果和页面上某个节点有冲突需要修改，那么就需要传入参数修改配置。比如说变成jssc5_modify，就得在flashvars中这样做：
&#60;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5_modify" style="position:absolute;visibility:hidden;"&#62;
	&#60;param name="movie" value="jssc5.swf"/&#62;
	&#60;param...]]></description>
			<content:encoded><![CDATA[<h3>整体流程</h3>
<p>终于说到整体流程上了。之前的文章一直在解说as中如何来做词法分析，js方面丝毫未提，更没说jssc到底在页面上是怎么工作的。现在，就来详细地解释一下。</p>
<p>环境需求：</p>
<ol>
<li>现代浏览器（废话）</li>
<li>装有Adobe Flash Player插件，版本号为9或9以上</li>
<li>javascript启用</li>
<li>页面中放入jssc.swf文件</li>
</ol>
<p>大致流程：</p>
<ol>
<li>swf文件载入完毕</li>
<li>内嵌在swf中的js首先被执行，寻找页面中所有符合规则的pre节点</li>
<li>顺序遍历这些pre节点，提取每个pre节点的文本内容（即原始代码）</li>
<li>将原始代码传递给swf</li>
<li>swf对传递来的原始代码进行词法分析，并生成一段结果html片段（即一串li节点）</li>
<li>将结果传递回js</li>
<li>js对结果进行包装（一串li节点放入ol节点中，以及标题头、边距和复制等等）</li>
<li>将对应的原始pre节点隐藏（display:none）</li>
<li>将新生成的内容插入原始pre节点的前面</li>
</ol>
<p>可以看出，js和as耦合的地方在哪里，以及它们之间是如何相互合作的。下面将对以上9个步骤细细说来，希望更多的开发者能提出改进意见～</p>
<h3>1.载入swf</h3>
<p>这里没什么好说的，在页面底部加入flash标签即可。值得注意的是不同浏览器中标签有所区别，理想情况下可以使用swfobject来插入标准的html标签。不过为了兼容以及简单，一般我是这样做的：</p>
<pre class="brush:html">&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5" style="position:absolute;visibility:hidden;"&gt;
	&lt;param name="movie" value="jssc5.swf"/&gt;
	&lt;param name="flashvars" value="find=brush"/&gt;
	&lt;embed src="jssc5.swf" flashvars="find=brush" name="jssc5" type="application/x-shockwave-flash" style="position:absolute;visibility:hidden;"/&gt;
&lt;/object&gt;</pre>
<p>这里面有许多可配置的地方。</p>
<p><span style="color: #ff0000;">object</span>的<span style="color: #ff0000;">id</span>和<span style="color: #ff0000;">embed</span>的<span style="color: #ff0000;">name</span>必须一致且唯一（应该是唯二才对），为了满足不同浏览器的需要。我设为<span style="color: #ff0000;">jssc5</span>，这也是默认值。如果和页面上某个节点有冲突需要修改，那么就需要传入参数修改配置。比如说变成<span style="color: #ff0000;">jssc5_modify</span>，就得在flashvars中这样做：</p>
<pre class="brush:html">&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5_modify" style="position:absolute;visibility:hidden;"&gt;
	&lt;param name="movie" value="jssc5.swf"/&gt;
	&lt;param name="flashvars" value="find=brush&amp;swf=jssc5_modify"/&gt;
	&lt;embed src="jssc5.swf" flashvars="find=brush&amp;swf=jssc5_modify" name="jssc5_modify" type="application/x-shockwave-flash" style="position:absolute;visibility:hidden;"/&gt;
&lt;/object&gt;</pre>
<p>注意到param标签和embed标签中都得改，为了满足浏览器兼容需要……</p>
<p>同样，jssc会占用一个全局js变量名<span style="color: #ff0000;">jssc</span>（注意这个jssc是指变量名字符串，而前者是指软件），这是为了在js和as之间互相调用通信必须的。如果这个变量名和页面上的js变量有冲突，那么就会造成错误。所以它也可以进行修改配置，假如要改成<span style="color: #ff0000;">jssc_js</span>，就得在flashvars中这么做：</p>
<pre class="brush:html">&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5_modify" style="position:absolute;visibility:hidden;"&gt;
	&lt;param name="movie" value="jssc5.swf"/&gt;
	&lt;param name="flashvars" value="find=brush&amp;swf=jssc5_modify&amp;js=jssc_js"/&gt;
	&lt;embed src="jssc5.swf" flashvars="find=brush&amp;swf=jssc5_modify&amp;js=jssc_js" name="jssc5_modify" type="application/x-shockwave-flash" style="position:absolute;visibility:hidden;"/&gt;
&lt;/object&gt;</pre>
<p>最后，还有两个可以配置的参数：<span style="color: #ff0000;">css</span>和<span style="color: #ff0000;">url</span>。前者是指新生成的结果节点的class名称，你可以用firebug看到默认的亦是<span style="color: #ff0000;">jssc</span>；后者是指定swf的路径，这是为了在非ie浏览器下做copy使用（ie可以直接调用api做复制功能），从这个意义上说，整个swf文件其实是有两种功能——词法分析和复制按钮。这么做是为了减少http请求，同时js融合在as里也是为了减少http请求。</p>
<h3>2.内嵌的js执行</h3>
<p>js首先会寻找页面上所有符合规则的pre节点，那么是什么规则的？默认情况下，pre的class名称如果这样开头，js就会认为它是正确的（其实并不一定要求是开头，出现在其它位置也可以，但为了良好的习惯推荐如此）：</p>
<pre class="brush:html">&lt;pre class="brush:html"&gt;&lt;/pre&gt;</pre>
<p>这段被高亮的代码其实就是它本身。<span style="color: #ff0000;">brush</span>是<strong>键名</strong>，<span style="color: #ff0000;">html</span>是<strong>键值</strong>。假如想要高亮一段js代码，那么就需要更改键值：</p>
<pre class="brush:html">&lt;pre class="brush:js"&gt;&lt;/pre&gt;</pre>
<p>其它语言道理相同。另外，可以高亮的代码必须是jssc本身已经支持的语法种类，不支持的话也会被格式化，但没有高亮效果。</p>
<p>细心的人可能已经发现，<span style="color: #ff0000;">brush</span>键名和最开始那段代码中出现的相一致。没错，假如pre节点的class名称也有冲突，不能使用<span style="color: #ff0000;">brush</span>，要改成<span style="color: #ff0000;">brush_modify</span>，那么就要如此修改配置：</p>
<pre class="brush:html">&lt;object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="jssc5_modify" style="position:absolute;visibility:hidden;"&gt;
	&lt;param name="movie" value="jssc5.swf"/&gt;
	&lt;param name="flashvars" value="find=brush_modify&amp;swf=jssc5_modify&amp;js=jssc_js"/&gt;
	&lt;embed src="jssc5.swf" flashvars="find=brush_modify&amp;swf=jssc5_modify&amp;js=jssc_js" name="jssc5_modify" type="application/x-shockwave-flash" style="position:absolute;visibility:hidden;"/&gt;
&lt;/object&gt;</pre>
<p>注意param和embed中要修改2次。</p>
<p>在找到所有符合规则的pre节点之后，js将这些节点的引用存储下来，然后一一遍历它们。下面的经过就是每次遍历一个pre节点时所发生的。</p>
<h3>3.遍历提取内容</h3>
<p>提取pre节点的内容很简单，即我们熟知的<span style="color: #ff0000;">innerText</span>。不过在不同浏览器中也有让人头疼的地方。以前在做jssc4的时候，firefox2版本的<span style="color: #ff0000;">innerText</span>容量有限制，如果代码过多，提取的内容就不完整。另外也有低版本浏览器不支持<span style="color: #ff0000;">innerText</span>的可能性发生。所以综合考虑我写了个如下的js方法：</p>
<pre class="brush:js">function getText(node) {
	var code = node.textContent || node.innerText;
	if(!code &amp;&amp; node.firstChild) {
		code = node.firstChild.nodeValue;
	}
	return code || "";
}</pre>
<h3>4.传递内容给as</h3>
<p>这是as定义好的接口，js和as可以通过<span style="color: #ff0000;">ExternalInterface</span>类来实现互调。不再多说。</p>
<h3>5.as做词法分析</h3>
<p>这是前几篇一直在说的内容，不再多说。</p>
<h3>6.传递结果给js</h3>
<p>同第4点。</p>
<h3>7.js包装结果</h3>
<p>生成的结果其实是一串<span style="color: #ff0000;">li</span>节点，js要做的就是创建一个<span style="color: #ff0000;">ol</span>节点，然后设置<span style="color: #ff0000;">innerHTML</span>为传递来的结果字符串。如此最基本的高亮代码就完成了。之后是设置标题、起始行数、边距、复制功能和鼠标移入高亮当前行背景。</p>
<p>其中边距是指ol节点的<span style="color: #ff0000;">paddingLeft</span>值，因为代码行数不一样，所以左边距一定是根据行数动态进行计算的。在js中我的公式如下：</p>
<pre class="brush:js">oOl.style.paddingLeft = Math.max((line.length + 2) * 9, 30) + "px";</pre>
<h3>8.隐藏pre节点</h3>
<p>最后是将本次循环的这个pre节点隐藏。注意，这里是隐藏不是删除！因为后面还要用到代码复制功能，所以只能隐藏不能删除！</p>
<h3>9.插入结果</h3>
<p>将包装好的结果插入本次循环pre节点的前面，这轮循环就算走完了，再继续下一轮循环。</p>
<h3>结束语</h3>
<p>好了，整个系列文章算结束了。欢迎大家提出好的建议和想法，或者直接参与到开发当中来，亦或以别的方式来参与（比如说做wordpress的插件）。如果你能做出比jssc更好的高亮插件，那么我也会放弃jssc，投入新的、更好的项目中去的——这话说的好假：）</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/23/669.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>js和swf交互时不同浏览器中的顺序</title>
		<link>http://army8735.org/2010/02/20/649.html</link>
		<comments>http://army8735.org/2010/02/20/649.html#comments</comments>
		<pubDate>Sat, 20 Feb 2010 09:44:51 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[JAcld]]></category>
		<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=649</guid>
		<description><![CDATA[接上篇，继续做的测试，有了点新发现。解说测试之前，先说明下用flash检测大写锁定键是否开启的原理。
前提要求是：普通的input文本输入框（无论是text还是password），用户输入还是以html的input组件为基础，并非在其上加入透明的flash输入框或者其它技术平台的组件；无干扰性，用户输入没有任何其它干扰的感觉。
以此，唯一的解决办法就是js结合swf来控制。input的各种事件侦听（获得焦点、失去焦点、按键触发）都只能由js来完成，而对当前键盘状态的检测则交给flash来处理。它们之间有个很大的障碍——flash对当前键盘状态的识别必须首先获得焦点，而我们在input中输入内容的时候焦点却在input上，这成为最大的矛盾。
利用js控制页面焦点可以解决这一问题，除了webkit内核的浏览器。我们可以写出如下的伪代码：
oInput.onfocus = function() {
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测，并根据检测结果调用某个js函数
	setTimeout(function() {
		oInput.focus(); //input重新获得焦点，无干扰用户输入
	}, 0);
}
你可能困扰为何要用setTimeout来使input重新获得焦点，这是为了让用户输入时感觉不到焦点在input和flash之间走了一圈，就好象什么事都没有发生一样。至于为什么一定要用setTimeout，那是为了模拟线程同步，确保重新获得焦点这一操作发生在最后。
就几行代码看上去很简单，实际上有几个隐蔽的信息藏在其中。在flash获得焦点并进行检测之后，input重新获得焦点，试问：这样会不会再次触发onfocus？答案是肯定的，如果不做任何处理的话，这将是个死循环；另外，input还应该侦听onblur，没道理用户在离开输入框之后还在进行提示（除非你能忍受），那么onblur这个侦听函数也会进行不断重复；更恐怖的在下面，我为每一步标上了序号，以表示它们的执行步骤：
function result() {
	//1
	//调用的结果函数，用以让提示区域显示或隐藏
}
oInput.onfocus = function() {
	//2
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测，并根据检测结果调用结果函数
	//3
	setTimeout(function() {
		//4
		oInput.focus(); //input重新获得焦点，无干扰用户输入
	}, 0);
	//5
}
oInput.onblur =...]]></description>
			<content:encoded><![CDATA[<p><a href="/2010/02/20/646.html" target="_blank">接上篇</a>，继续做的测试，有了点新发现。解说测试之前，先说明下用flash检测大写锁定键是否开启的原理。</p>
<p>前提要求是：普通的input文本输入框（无论是text还是password），用户输入还是以html的input组件为基础，并非在其上加入透明的flash输入框或者其它技术平台的组件；无干扰性，用户输入没有任何其它干扰的感觉。</p>
<p>以此，唯一的解决办法就是js结合swf来控制。input的各种事件侦听（获得焦点、失去焦点、按键触发）都只能由js来完成，而对当前键盘状态的检测则交给flash来处理。它们之间有个很大的障碍——flash对当前键盘状态的识别必须首先获得焦点，而我们在input中输入内容的时候焦点却在input上，这成为<strong>最大的矛盾</strong>。</p>
<p>利用js控制页面焦点可以解决这一问题，除了webkit内核的浏览器。我们可以写出如下的伪代码：</p>
<pre class="brush:js">oInput.onfocus = function() {
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测，并根据检测结果调用某个js函数
	setTimeout(function() {
		oInput.focus(); //input重新获得焦点，无干扰用户输入
	}, 0);
}</pre>
<p>你可能困扰为何要用<strong>setTimeout</strong>来使input重新获得焦点，这是为了让用户输入时感觉不到焦点在input和flash之间走了一圈，就好象什么事都没有发生一样。至于为什么一定要用setTimeout，那是为了模拟线程同步，确保重新获得焦点这一操作发生在最后。</p>
<p>就几行代码看上去很简单，实际上有几个隐蔽的信息藏在其中。在flash获得焦点并进行检测之后，input重新获得焦点，试问：这样会不会再次触发onfocus？答案是肯定的，如果不做任何处理的话，这将是个死循环；另外，input还应该侦听onblur，没道理用户在离开输入框之后还在进行提示（除非你能忍受），那么onblur这个侦听函数也会进行不断重复；更恐怖的在下面，我为每一步标上了序号，以表示它们的执行步骤：</p>
<pre class="brush:js">function result() {
	//1
	//调用的结果函数，用以让提示区域显示或隐藏
}
oInput.onfocus = function() {
	//2
	oSwf.focus(); //flash获得焦点
	oSwf.detect(); //flash进行检测，并根据检测结果调用结果函数
	//3
	setTimeout(function() {
		//4
		oInput.focus(); //input重新获得焦点，无干扰用户输入
	}, 0);
	//5
}
oInput.onblur = function() {
	//6
	//失去焦点后该怎么做，略
}</pre>
<p>猜一猜这个步骤顺序是多少？你永远也答不对，因为即使在<span style="color: #ff0000;">trident</span>（ie为代表）和<span style="color: #ff0000;">gecko</span>（firefox为代表）两种内核下，它们也不相同（别提webkit了，搞定那个bug先）。</p>
<p>在trident中，input被用户激活后（比如说用鼠标点击），先触发focus，因此2会先执行；接下来flash获得焦点，再调用结果方法，1会被执行；继续回到onfocus方法，顺序走完3和5；onblur被触发，执行一下6；最后是setTimeout那里的4。</p>
<p>很奇怪的现象，因为在2时，input失去焦点而swf获得焦点，此时并没有触发onblur去执行6，反而是先执行的1；之后还有没执行完的3和5；在接下来才能轮到6。由此我们可以观察出一些trident内核的优先级顺序设计的端倪。</p>
<p>再来看看gecko，input被激活后，依然会先触发focus，2第一个执行；接下来也是flash获得焦点，不过在这之前input要先失去焦点，因此先触发了onblur，执行了6；然后flash进行判断，并调用结果方法，执行了1；再往后就类似了，3和5搞定后setTimeout的4最后。</p>
<p>探索完原理后，才有可能继续开发。我也只“刨根问底”到这个程度上，欢迎有兴趣的同学继续“往祖坟上刨”，彻底翻出来赤裸裸的现实。后续如果有新的进展，我会继续把它写出来。：）</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/20/649.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>webkit内核浏览器中swf获取焦点的bug</title>
		<link>http://army8735.org/2010/02/20/646.html</link>
		<comments>http://army8735.org/2010/02/20/646.html#comments</comments>
		<pubDate>Sat, 20 Feb 2010 04:17:42 +0000</pubDate>
		<dc:creator>army</dc:creator>
				<category><![CDATA[JAcld]]></category>
		<category><![CDATA[前端开发]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=646</guid>
		<description><![CDATA[http://army8735.org/2009/09/15/82.html
曾经考虑过用swf来检测密码输入框大写锁定键是否被打开，并且也进行了一个小实验，基本是成功的。时隔多日，最近想要把它完善一下，突然发现在chrome中根本不起作用！
一步步排查下来，终于发现在webkit内核的浏览器下，以往的使得swf获取焦点的方法根本不起作用。随之google一番，发现老外早已发现这个bug，并且目前webkit仍未解决：
http://stackoverflow.com/questions/594821/object-focus-problem-with-safari-and-chrome-browsers
这样就影响到了部分功能：比如想使用flash的检测按键功能，但它必须要求flash是在获得焦点的情况下才行。使用js可以在ie和gecko内核下轻松办到，webkit只能继续等待了。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://army8735.org/2009/09/15/82.html">http://army8735.org/2009/09/15/82.html</a></p>
<p>曾经考虑过用swf来检测密码输入框大写锁定键是否被打开，并且也进行了一个小实验，基本是成功的。时隔多日，最近想要把它完善一下，突然发现在chrome中根本不起作用！</p>
<p>一步步排查下来，终于发现在webkit内核的浏览器下，以往的使得swf获取焦点的方法根本不起作用。随之google一番，发现老外早已发现这个bug，并且目前webkit仍未解决：</p>
<p><a href="http://stackoverflow.com/questions/594821/object-focus-problem-with-safari-and-chrome-browsers">http://stackoverflow.com/questions/594821/object-focus-problem-with-safari-and-chrome-browsers</a></p>
<p>这样就影响到了部分功能：比如想使用flash的检测按键功能，但它必须要求flash是在获得焦点的情况下才行。使用js可以在ie和gecko内核下轻松办到，webkit只能继续等待了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/20/646.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web中的区域对齐</title>
		<link>http://army8735.org/2010/02/10/626.html</link>
		<comments>http://army8735.org/2010/02/10/626.html#comments</comments>
		<pubDate>Wed, 10 Feb 2010 03:59:43 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[as、flex]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[StageAlign]]></category>
		<category><![CDATA[对齐]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=626</guid>
		<description><![CDATA[说到对齐方式，一般联想到的无非四种：左对齐、右对齐、上对齐和下对齐。通过其中的两两组合，可以衍生出：左上角对齐、左下角对齐、右上角对齐和右下角对齐。在css中这些类型很常见，比如绝对定位：
.left_top {
	position: absolute;
	left: 0;
	top: 0;
}
.left_bottom {
	position: absolute;
	left: 0;
	bottom: 0;
}
.right_top {
	position: absolute;
	right: 0;
	top: 0;
}
.right_bottom {
	position: absolute;
	right: 0;
	bottom: 0;
}
我们很容易用css来作出四个角对齐或者四个方向居中对齐的效果。但是在as当中，则有一点点麻烦了。
说到对齐之前，首先要接触到StageScaleMode这个常量，它被赋给stage.scaleMode，用以指定整个swf程序的缩放模式，默认的是NO_SCALE，即不缩放。详细示例如下图：

当然StageScaleMode还有保持高宽比的SHOW_ALL常量以及保持高宽比并可能进行裁剪的NO_BORDER常量。上面只例举了两种对立的情形。当涉及到StageAlign的时候，我们默认为StageScaleMode就是默认的NO_SCALE，这样对齐才有意义。
在css中，也经常会遇到类似的情况。一个div区域有自己的高宽，超出区域范围之外的用overflow来控制可见度。譬如是右上角对齐的css，例子是这样：
&#60;style&#62;
.outer{position:relative;width:100px;height:100px;border:1px solid #f00;overflow:hidden;}
.inner{position:absolute;top:0;right:0;width:200px;height:200px;background:#000;}
&#60;/style&#62;

&#60;div class="outer"&#62;
	&#60;div...]]></description>
			<content:encoded><![CDATA[<p>说到对齐方式，一般联想到的无非四种：左对齐、右对齐、上对齐和下对齐。通过其中的两两组合，可以衍生出：左上角对齐、左下角对齐、右上角对齐和右下角对齐。在css中这些类型很常见，比如绝对定位：</p>
<pre class="brush:css">.left_top {
	position: absolute;
	left: 0;
	top: 0;
}
.left_bottom {
	position: absolute;
	left: 0;
	bottom: 0;
}
.right_top {
	position: absolute;
	right: 0;
	top: 0;
}
.right_bottom {
	position: absolute;
	right: 0;
	bottom: 0;
}</pre>
<p>我们很容易用css来作出四个角对齐或者四个方向居中对齐的效果。但是在as当中，则有一点点麻烦了。</p>
<p>说到对齐之前，首先要接触到<strong>StageScaleMode</strong>这个常量，它被赋给<strong>stage.scaleMode</strong>，用以指定整个swf程序的缩放模式，默认的是<strong>NO_SCALE</strong>，即不缩放。详细示例如下图：</p>
<p><img class="aligncenter size-full wp-image-629" title="stagealign1" src="http://army8735.org/wp-content/uploads/2010/02/stagealign1.png" alt="stagealign1" width="400" height="400" /></p>
<p>当然<strong>StageScaleMode</strong>还有保持高宽比的<strong>SHOW_ALL</strong>常量以及保持高宽比并可能进行裁剪的<strong>NO_BORDER</strong>常量。上面只例举了两种对立的情形。当涉及到<strong>StageAlign</strong>的时候，我们默认为<strong>StageScaleMode</strong>就是默认的<strong>NO_SCALE</strong>，这样对齐才有意义。</p>
<p>在css中，也经常会遇到类似的情况。一个div区域有自己的高宽，超出区域范围之外的用<strong>overflow</strong>来控制可见度。譬如是右上角对齐的css，例子是这样：</p>
<pre class="brush:html;">&lt;style&gt;
.outer{position:relative;width:100px;height:100px;border:1px solid #f00;overflow:hidden;}
.inner{position:absolute;top:0;right:0;width:200px;height:200px;background:#000;}
&lt;/style&gt;

&lt;div class="outer"&gt;
	&lt;div class="inner"&gt;&lt;/div&gt;
&lt;/div&gt;</pre>
<p>在as当中，想要做到同样的效果的话，可以借助<strong>StageAlign</strong>这个常量，它被赋给<strong>stage.align</strong>属性，所起的作用就和上面说的css对齐方式一样。同样是右上角对齐，我们只要在文档类中声明一下即可达到效果：</p>
<pre class="brush:as3">package {
	import flash.display.*;

	public class Main extends Sprite {
		public function Main():void {
			stage.align = StageAlign.TOP_RIGHT;
		}
	}
}</pre>
<p>用图片做示例，页面嵌入一个原始大小为50*50的swf文件，假如外部容器（object标签或者emebed标签）的高宽值被改变，swf仍然是右上角对齐：</p>
<p><img class="aligncenter size-full wp-image-642" title="stagealign2" src="http://army8735.org/wp-content/uploads/2010/02/stagealign2.png" alt="stagealign2" width="400" height="260" /></p>
<p>依此我们便可以作出自由指定显示swf内容范围的功能，比如初始swf原始大小为100*100，但是外部容器只设定宽高为50*50。当为右上角对齐时，swf只显示右上区域的50*50部分。当某件事发生时（比如鼠标点击一个按钮），外部容器款高变成100*100，如此便能看见全部的swf了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/10/626.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>web端语法高亮原理：走进jssc的世界（四）</title>
		<link>http://army8735.org/2010/02/02/608.html</link>
		<comments>http://army8735.org/2010/02/02/608.html#comments</comments>
		<pubDate>Tue, 02 Feb 2010 06:11:39 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[jssc]]></category>
		<category><![CDATA[系列文章]]></category>
		<category><![CDATA[语法高亮原理]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=608</guid>
		<description><![CDATA[内嵌解析
很容易遇到这样的情况：在需要高亮的代码中还混淆着其它语言种类的代码（最常见的例子为Html内嵌css和js，以下也将以此为例）。这是一件让人头疼的事情，因为无论采用何种方法，内嵌的语言和原本语言的规则一定是不同的。这意味着必须将它们区分开来对待。从这一点出发，自然而然就能引出问题的关键所在——如何区分？
剥离内容
先来考虑最简单的情况：
&#60;head&#62;
&#60;script&#62;var i = 0;&#60;/script&#62;
&#60;/head&#62;
假如没有第2行的script标签以及其内部的代码，那么整个就是纯html代码高亮，这个没有什么难度（如果已经完全理解前三篇的此法分析的话）。然而不凑巧的是，关键点就在于script标签中会出现js代码，html的此法分析中并没有js的词法规则，两者不能等同。那么怎么办呢？
答案是将它们剥离出来。上例是最简单的例子，我们在对html进行此法分析的时候，一旦读到了&#60;script&#62;开始标签，接着便去寻找&#60;/script&#62;结束标签（一般会使用String.indexOf()来查找），然后将标签里面的内容单独提取出来。这是第一步，如果做完的话，此时html的高亮结果应该是：除了js代码没有高亮（即默认颜色）以外，其它的html代码均被正确高亮了。
更复杂的情况
剥离到此还没有结束，因为剥离要考虑其它一些复杂的元素。看以下代码：
&#60;head&#62;
&#60;script&#62;var i = 0;
//&#60;/script&#62;
&#60;/script&#62;
&#60;/head&#62;
代码的第3行中，出现了单行注释，其中有被注释掉的script结束标签。这点需要格外注意。假若使用String.indexOf()来查询script结束标签的话，那么就会在第3行结束。这样就错了，因为第3行实际上是个注释，真正的结束符在第4行。
以此延伸，除了上面的情况以外，引号中的字符串、多行注释、正则里面均会出现类似情况。因此，单纯的String.indexOf()是肯定不行的。我们必须对js代码部分进行预处理。
预处理
在as的解析部分，实际上主要分为两大块：词法分析和存储结果。词法分析即是前面几篇一直在讲解的内容；存储结果即是将分析出来的代码链接起来，说白了就是简单的字符串拼接。
在html中的js代码可能会出现混淆script结束标签的情况之下，唯一解决的办法就是对js也进行简单的词法分析预处理，但不存储结果。因为分析是“读”，而存储是“写”。写的耗时要比读多多了，而且预处理只是为了防止注释、字符串和正则的混淆，不需要真正地进行解析，实现复杂读也比较低。等完全将js代码从html中剥离后，再交给js解析器来做真正的工作，如此也保证了代码的不重复。
&#60;head&#62;
&#60;script&#62;
var i = 0;
//&#60;/script&#62;
"&#60;/script&#62;"
/*&#60;/script&#62;*/
/[&#60;/script&#62;]/
&#60;/script&#62;
&#60;/head&#62;
html中的预处理，至少要保证能将3到7行的js代码完全剥离出来交给js解析器处理，其它html代码则由本身来完成高亮。
状态区分
接下来的难点可能还是在如何在html解析的时候完成区分上面。在这里，我设置了一个state变量用以标识状态。仔细考虑下html，无非发现它主要有以下几种状态：

html节点：即&#60;&#62;内的tag，还有随之的一些属性内容。如：&#60;img width=&#8221;100px&#8221;/&#62;。
text节点：文本内容，段落p中最常见到。
css节点：style中的css代码。
script节点：script中的js代码。

在默认最开始的时候，是文本节点。一旦遇到了左尖括号，并且随后跟的是个正确的节点名（&#60;x&#62;绝对不是个正确的节点，所以不能当成节点来处理），那么就进入节点状态来解析；当节点解析完了之后，返回文本状态。css和script节点是个两个特殊的节点，因为在它们的开始标签结束之后，要进行预处理查找结束标签。实际上会做其中的一个，另外一个也就懂了。
值得注意的是，html标签中有单个类型的存在，比如&#60;br/&#62;，它不需要成对出现，甚至可以写成&#60;br&#62;。省略/的又是另外一种自闭合类型。它们在处理起来有点麻烦，特别是涉及到深度折叠的时候。解决的办法也是设置状态变量，标识当前节点属于那种类型，以此来区分判断。
这篇写得可能有点简单，因为的确是比较抽象的东西。我也偷偷懒，相信能做到前章所提的词法分析的情况下，纯理论来读本篇也不是什么难事了。可能直接读我的源代码反而会更容易些。在下一篇当中，我会介绍as和js的交互以及jssc的大概处理流程，它将作为结束篇章。
]]></description>
			<content:encoded><![CDATA[<h3>内嵌解析</h3>
<p>很容易遇到这样的情况：在需要高亮的代码中还混淆着其它语言种类的代码（最常见的例子为Html内嵌css和js，以下也将以此为例）。这是一件让人头疼的事情，因为无论采用何种方法，内嵌的语言和原本语言的规则一定是不同的。这意味着必须将它们区分开来对待。从这一点出发，自然而然就能引出问题的关键所在——如何区分？</p>
<h3>剥离内容</h3>
<p>先来考虑最简单的情况：</p>
<pre class="brush:html">&lt;head&gt;
&lt;script&gt;var i = 0;&lt;/script&gt;
&lt;/head&gt;</pre>
<p>假如没有第2行的script标签以及其内部的代码，那么整个就是纯html代码高亮，这个没有什么难度（如果已经完全理解前三篇的此法分析的话）。然而不凑巧的是，关键点就在于script标签中会出现js代码，html的此法分析中并没有js的词法规则，两者不能等同。那么怎么办呢？</p>
<p>答案是将它们剥离出来。上例是最简单的例子，我们在对html进行此法分析的时候，一旦读到了&lt;script&gt;开始标签，接着便去寻找&lt;/script&gt;结束标签（一般会使用String.indexOf()来查找），然后将标签里面的内容单独提取出来。这是第一步，如果做完的话，此时html的高亮结果应该是：除了js代码没有高亮（即默认颜色）以外，其它的html代码均被正确高亮了。</p>
<h3>更复杂的情况</h3>
<p>剥离到此还没有结束，因为剥离要考虑其它一些复杂的元素。看以下代码：</p>
<pre class="brush:html">&lt;head&gt;
&lt;script&gt;var i = 0;
//&lt;/script&gt;
&lt;/script&gt;
&lt;/head&gt;</pre>
<p>代码的第3行中，出现了单行注释，其中有被注释掉的script结束标签。这点需要格外注意。假若使用String.indexOf()来查询script结束标签的话，那么就会在第3行结束。这样就错了，因为第3行实际上是个注释，真正的结束符在第4行。</p>
<p>以此延伸，除了上面的情况以外，引号中的字符串、多行注释、正则里面均会出现类似情况。因此，单纯的String.indexOf()是肯定不行的。我们必须对js代码部分进行预处理。</p>
<h3>预处理</h3>
<p>在as的解析部分，实际上主要分为两大块：词法分析和存储结果。词法分析即是前面几篇一直在讲解的内容；存储结果即是将分析出来的代码链接起来，说白了就是简单的字符串拼接。</p>
<p>在html中的js代码可能会出现混淆script结束标签的情况之下，唯一解决的办法就是对js也进行<strong>简单的词法分析预处理</strong>，但不存储结果。因为分析是“读”，而存储是“写”。写的耗时要比读多多了，而且预处理只是为了防止注释、字符串和正则的混淆，不需要真正地进行解析，实现复杂读也比较低。等完全将js代码从html中剥离后，再交给js解析器来做真正的工作，如此也保证了代码的不重复。</p>
<pre class="brush:html">&lt;head&gt;
&lt;script&gt;
var i = 0;
//&lt;/script&gt;
"&lt;/script&gt;"
/*&lt;/script&gt;*/
/[&lt;/script&gt;]/
&lt;/script&gt;
&lt;/head&gt;</pre>
<p>html中的预处理，至少要保证能将3到7行的js代码完全剥离出来交给js解析器处理，其它html代码则由本身来完成高亮。</p>
<h3>状态区分</h3>
<p>接下来的难点可能还是在如何在html解析的时候完成区分上面。在这里，我设置了一个state变量用以标识状态。仔细考虑下html，无非发现它主要有以下几种状态：</p>
<ol>
<li>html节点：即&lt;&gt;内的tag，还有随之的一些属性内容。如：&lt;img width=&#8221;100px&#8221;/&gt;。</li>
<li>text节点：文本内容，段落p中最常见到。</li>
<li>css节点：style中的css代码。</li>
<li>script节点：script中的js代码。</li>
</ol>
<p>在默认最开始的时候，是文本节点。一旦遇到了左尖括号，并且随后跟的是个正确的节点名（&lt;x&gt;绝对不是个正确的节点，所以不能当成节点来处理），那么就进入节点状态来解析；当节点解析完了之后，返回文本状态。css和script节点是个两个特殊的节点，因为在它们的开始标签结束之后，要进行预处理查找结束标签。实际上会做其中的一个，另外一个也就懂了。</p>
<p>值得注意的是，html标签中有单个类型的存在，比如&lt;br/&gt;，它不需要成对出现，甚至可以写成&lt;br&gt;。省略/的又是另外一种自闭合类型。它们在处理起来有点麻烦，特别是涉及到深度折叠的时候。解决的办法也是设置状态变量，标识当前节点属于那种类型，以此来区分判断。</p>
<p>这篇写得可能有点简单，因为的确是比较抽象的东西。我也偷偷懒，相信能做到前章所提的词法分析的情况下，纯理论来读本篇也不是什么难事了。可能直接读我的源代码反而会更容易些。在<a href="http://army8735.org/2010/02/23/669.html" target="_blank">下一篇</a>当中，我会介绍as和js的交互以及jssc的大概处理流程，它将作为结束篇章。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/02/608.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>YY一下各种土豆</title>
		<link>http://army8735.org/2010/02/01/606.html</link>
		<comments>http://army8735.org/2010/02/01/606.html#comments</comments>
		<pubDate>Mon, 01 Feb 2010 06:54:07 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[其它]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=606</guid>
		<description><![CDATA[首先还是感谢下小麦，让偶有机会加入土豆大家庭。作为新土豆，来胡乱YY一下假想中的各种土豆吧，我只知道“黑豆”是高清……

红豆：SNS的代表，红色是社交的颜色，符合这个主题。
绿豆：健康的代表，绿豆本身就是很有营养价值的豆子，不都说绿色食品么。
金豆：理财投资的代表，这个没必要解释了吧。
紫豆：女性专题的代表，貌似粉豆也差不多。
蓝豆：科技的代表，科技是比较新潮梦幻的，蓝色也是梦幻的。
黄豆：城市消费？想不出来该是啥……
魔豆：没想好该是什么……

]]></description>
			<content:encoded><![CDATA[<p>首先还是感谢下<a href="http://www.mikkolee.com/" target="_blank">小麦</a>，让偶有机会加入<a href="http://www.tudou.com" target="_blank">土豆大家庭</a>。作为新土豆，来胡乱YY一下假想中的各种土豆吧，我只知道“<a href="http://hd.tudou.com" target="_blank">黑豆</a>”是高清……</p>
<ol>
<li>红豆：SNS的代表，红色是社交的颜色，符合这个主题。</li>
<li>绿豆：健康的代表，绿豆本身就是很有营养价值的豆子，不都说绿色食品么。</li>
<li>金豆：理财投资的代表，这个没必要解释了吧。</li>
<li>紫豆：女性专题的代表，貌似粉豆也差不多。</li>
<li>蓝豆：科技的代表，科技是比较新潮梦幻的，蓝色也是梦幻的。</li>
<li>黄豆：城市消费？想不出来该是啥……</li>
<li>魔豆：没想好该是什么……</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/02/01/606.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>如何访问作为命名空间的函数内部变量</title>
		<link>http://army8735.org/2010/01/26/591.html</link>
		<comments>http://army8735.org/2010/01/26/591.html#comments</comments>
		<pubDate>Tue, 26 Jan 2010 01:28:06 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[翻译]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=591</guid>
		<description><![CDATA[原文标题：《Functions as Namespaces, and How to Peek Inside》
原文地址：http://www.davidflanagan.com/2009/11/functions-as-na.html
很精彩的技巧，通过闭包和eval()的使用，达到标题中的功能。
var value = (function() {  // Wrapper function creates a local scope...]]></description>
			<content:encoded><![CDATA[<p>原文标题：《Functions as Namespaces, and How to Peek Inside》</p>
<p>原文地址：<a href="http://www.davidflanagan.com/2009/11/functions-as-na.html">http://www.davidflanagan.com/2009/11/functions-as-na.html</a></p>
<p>很精彩的技巧，通过闭包和eval()的使用，达到标题中的功能。</p>
<pre class="brush:js">var value = (function() {  // Wrapper function creates a local scope or namespace
	// your code goes here
	return value;  // Export a value from the namespace
})();  // Invoke the wrapper function to run your code</pre>
<p>以上代码是我们经常用到的技巧：赋值时通过执行一个匿名函数来防止一些代码变量污染全局空间，并且函数内部可以写很复杂的实现而无需担心对外部的影响。</p>
<p>但是有些情况下我们得到的js代码是一串字符串——例如，用xhr读取到的js代码。倘若想要使用它，可以用eval()，还可以用更方便的Function()构造器。</p>
<pre class="brush:js">var code = "alert(1);";  // A string of JS code to evaluate
var f = new Function(code);   // Wrap it in a function
f();    // And run the function

//army注：这段代码和下面是完全等同的：
function f() {
	alert(1);
}
f();</pre>
<p>所以，通过这种技巧，哪怕是从一段js字符串源代码来赋值，也是可行的：</p>
<pre class="brush:js">var code = "return 3;";
var f = new Function(code);
var i = f(); //i是3</pre>
<p>但是这里却有一个问题。因为是由Function()构造函数而来的，相当于创造了一个密封的命名空间（所有代码都在一个匿名function内执行），我们无法从外部访问它。倘若里面有一些定义的类或者函数之类的东西，那就难办了。比如这样：</p>
<pre class="brush:js">var code = "function Test() {};";
var f = new Function(code);
f();
//这相当于执行了以下方法：
function f() {
	function Test() {
	}
};
f();</pre>
<p>内部定义了一个Test类，我们很难访问到它。不过这里有个技巧——这也是本篇要介绍的主角——可以通过<strong>闭包+eval()</strong>结合使用来绕过这种限制。</p>
<pre class="brush:js">var code = "function Test() { alert('a test'); };";
var f = new Function(code + "return function(s) { return eval(s); };")(); //关键！还有后面的括号！
var Test = f("Test");
new Test();</pre>
<p>如何？内部的Test类成功从外部创建了。关键就在于第2行，这里有个小小限制，第3行传入的参数需和要使用的内部变量名相等。外部的Test其实相当于密封函数内的Test的一个copy，没想明白的话根据代码倒着走一遍就ok了。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/01/26/591.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>ecmascript中的命令链</title>
		<link>http://army8735.org/2010/01/25/567.html</link>
		<comments>http://army8735.org/2010/01/25/567.html#comments</comments>
		<pubDate>Mon, 25 Jan 2010 03:10:28 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[前端开发]]></category>
		<category><![CDATA[设计模式]]></category>
		<category><![CDATA[命令]]></category>
		<category><![CDATA[命令链]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=567</guid>
		<description><![CDATA[有人好奇JAse中的undo和redo是怎么做的，并且给出自己的设计做法也各有特色。我最初采用的是全文保存方法（这一方法也是最简单有效、使用最广泛的），后来被人痛批一顿换成了命令链。命令链其实是基于一种叫做“命令”的设计模式的，关键思想在于面向接口编程。这个东西随便搜搜有很多例子，我再重复制造一下轮子吧。
AS3中的命令链
as3对OOP的支持已经比较完善，所以可以据此写出很好的命令链，先从简单的例子来说起（以下代码均被简化）。假如我们要做一个Dog类，Dog的“说话”方式是bark（狗叫）：
class Dog {
	public function bark():void {
		trace("汪汪！");
	}
}
这很简单，没有什么特殊之处。可是奇怪的事情发生了，中学英语课本中有个闻名的澳洲野狗Dingo，它的叫声和普通的狗不一样：
class Dingo extends Dog {
	public override function bark():void {
		trace("呜呜——");
	}
}
也很简单，Dingo毕竟还是一只狗，只需继承并覆盖即可。好了现在需求来了：我们想听听这些动物的叫声是什么样的，只需要调用下相应的方法即可。
public class Test {
	public function Test():void {
		var...]]></description>
			<content:encoded><![CDATA[<p>有人好奇JAse中的undo和redo是怎么做的，并且给出自己的设计做法也各有特色。我最初采用的是全文保存方法（这一方法也是最简单有效、使用最广泛的），后来被人痛批一顿换成了命令链。命令链其实是基于一种叫做“命令”的设计模式的，关键思想在于<strong>面向接口编程</strong>。这个东西随便搜搜有很多例子，我再重复制造一下轮子吧。</p>
<h3>AS3中的命令链</h3>
<p>as3对OOP的支持已经比较完善，所以可以据此写出很好的命令链，先从简单的例子来说起（以下代码均被简化）。假如我们要做一个Dog类，Dog的“说话”方式是bark（狗叫）：</p>
<pre class="brush:as3">class Dog {
	public function bark():void {
		trace("汪汪！");
	}
}</pre>
<p>这很简单，没有什么特殊之处。可是奇怪的事情发生了，中学英语课本中有个闻名的澳洲野狗Dingo，它的叫声和普通的狗不一样：</p>
<pre class="brush:as3">class Dingo extends Dog {
	public override function bark():void {
		trace("呜呜——");
	}
}</pre>
<p>也很简单，Dingo毕竟还是一只狗，只需继承并覆盖即可。好了现在需求来了：我们想听听这些动物的叫声是什么样的，只需要调用下相应的方法即可。</p>
<pre class="brush:as3">public class Test {
	public function Test():void {
		var dog:Dog = new Dog();
		dog.bark();

		var dingo:Dog = new Dingo();
		dingo.bark();
	}
}</pre>
<p>目前为止一切顺利，可惜未来总是不像我们想象的那样。动物中又多了只公鸡，它的叫法完全不一样，是打鸣。</p>
<pre class="brush:as3">class Cock {
	public function crow():void {
		trace("喔喔——");
	}
}</pre>
<p>这下坏了，我们在听叫声的时候得记住，公鸡的叫法和狗不一样：</p>
<pre class="brush:as3">public class Test {
	public function Test():void {
		var dog:Dog = new Dog();
		dog.bark();

		var dingo:Dog = new Dingo();
		dingo.bark();

		var cock:Cock = new Cock();
		cock.crow();
	}
}</pre>
<p>倘若把这些动物排成一列，让它们依次各自叫一下的话就更麻烦了：</p>
<pre class="brush:as3">public class Test {
	public function Test():void {
		var list:Array = [new Dog(), new Dingo(), new Cock()];
		for (var i:int = 0; i &lt; list.length; i++) {
			var item = list[i];
			if (item is Dog) {
				item.bark();
			}
			else if (item is Cock) {
				item.crow();
			}
		}
	}
}</pre>
<p>我们得对每种类型做单独判断，可所谓不胜其烦，动物的种类是不可预知的，倘若再来一只猫，还要继续增加判别吗？当然不能。</p>
<p>显然，关于叫法这里我们需要解耦。不管你是什么动物，这些叫声其实都可以概括为“说话”（动物们也有自己的语言和说话方式）。在主调程序中，我们并不想关心动物是“怎么说话”、“说些什么”的，我们只想调用一个命令，动物对象就能自动按照自己的方式来“说话”，甚至我们不用关心这个动物到底是什么。通过分离做什么和怎么做来实现这个目标的方式，就称为<strong>命令模式</strong>。</p>
<p>好了，首先是命令接口：</p>
<pre class="brush:as3">public interface Command {
	function say():void;
}</pre>
<p>所有动物只要实现了这个接口就行，各自具体的执行方式自己来定：</p>
<pre class="brush:as3">class Dog implements Commad {
	public function say():void {
		bark();
	}
	protected function bark():void {
		trace("汪汪！");
	}
}

class Dingo extends Dog {
	protected override function bark():void {
		trace("呜呜——"");
	}
}

class Cock implements Commad {
	public function say():void {
		crow();
	}
	private function crow():void {
		trace("喔喔——");
	}
}</pre>
<p>这样的话，在主调程序中，管它排成一列的动物有哪些，统统视作Command接口的实现即可：</p>
<pre class="brush:as3">public class Test {
	public function Test():void {
		var list:Array = [new Dog(), new Dingo(), new Cock()];
		for (var i:int = 0; i &lt; list.length; i++) {
			(list[i] as Command).say();
		}
	}
}</pre>
<p>哪怕再多出来一只猫，我们只需要增加猫的这一类别，列表中多出只猫来即可，主调程序无需关心具体实现。甚至猫的方式更加复杂有感情：</p>
<pre class="brush:as3">class Cat implements Command {
	private var isHappy:Boolean = true;

	public function say():void {
		if (isHappy) {
			purr();
		}
		else {
			mew();
		}
	}

	private function purr():void {
		trace("咕噜……");
	}
	private function mew():void {
		trace("喵——");
	}
}

public class Test {
	public function Test():void {
		var list:Array = [new Dog(), new Dingo(), new Cock(), new Cat()];
		for (var i:int = 0; i &lt; list.length; i++) {
			(list[i] as Command).say();
		}
	}
}</pre>
<h3>undo、redo的命令链</h3>
<p>熟悉了这些后，undo和redo的做法同理：只需实现了命令接口，每个操作各是独自的命令，互不干涉，具体实现自己决定，最大程度上解耦。</p>
<p>定义命令接口（以下代码均被简化）：</p>
<pre class="brush:as3">package command {

	public interface ICommand {
		function redo():void;
		function undo():void;
	}

}</pre>
<p>输入命令——也就是在编辑器中敲入代码时：</p>
<pre class="brush:as3">package command {
	import flash.text.*;

	public class InputCommand implements ICommand {
		private var tf:TextField;
		private var index:int;
		private var text:String;

		public function InputCommand(tf:TextField, index:int, text:String):void {
			this.tf = tf;
			this.index = index;
			this.text = text;
		}

		public function redo():void {
			tf.setSelection(index + text.length, index + text.length);
		}
		public function undo():void {
			tf.replaceText(index, index + text.length, "");
		}
	}
}</pre>
<p>删除命令——当按Delete键将编辑器里的内容删除时：</p>
<pre class="brush:as3">package command {
	import flash.text.*;

	public class DeleteCommand implements ICommand {
		private var tf:TextField;
		private var index:int;
		private var end:int;
		private var text:String;

		public function DeleteCommand(tf:TextField, index:int, end:int, text:String):void {
			this.tf = tf;
			this.index = index;
			this.end = end;
			this.text = text;
		}

		public function redo():void {
			tf.replaceText(index, index + text.length, "");
		}
		public function undo():void {
			tf.replaceText(index, index, text);
		}
	}
}</pre>
<p>于是，每当我们输入一个字符时，向一个记录命令步骤的数组里存入一个输入命令；而在按下Delete键时，存入一个删除命令；其它多一个命令多建一个类实现，这样一个链连下来就是<strong>命令链</strong>。</p>
<pre class="brush:as3">package command {
	import flash.text.*;
	import edit.*;

	public class CommandList {
		private var undoList:Array, redoList:Array;

		public function CommandList():void {
			clear();
		}

		public function addCommand(cmd:ICommand):void {
			//超过最大命令链长度需先出队列一个
			if (undoList.length &gt; Editor.UNDO_SIZE) {
				undoList.shift();
			}
			//每添加一次命令，清空redoList
			if(redoList.length) {
				redoList = new Array();
			}
			undoList.push(cmd);
		}
		public function undo():Boolean {
			//undoList中有命令则执行，并将相应命令出栈存入redoList中
			if(undoList.length) {
				var cmd:ICommand = undoList.pop() as ICommand;
				cmd.undo();
				redoList.push(cmd);
				return true;
			}
			//为空返回false
			else {
				return false;
			}
		}
		public function redo():Boolean {
			//redoList中有命令则执行，并将相应命令出栈存入undoList中
			if (redoList.length) {
				var cmd:ICommand = redoList.pop() as ICommand;
				cmd.redo();
				undoList.push(cmd);
				return true;
			}
			//为空返回false
			else {
				return false;
			}
		}
		public function clear():void {
			undoList = new Array();
			redoList = new Array();
		}
	}

}</pre>
<p>其实基于fp10中as3的新特性，有个叫Vector的类，它是存储命令链数组的更好的替代者，因为它规定数组里所有元素的类型必须是相同的。这样在编译期间便能防止出错，于是undoList和redoList更好的定义方式是这样：</p>
<pre class="brush:as3">undoList = new Vector.&lt;ICommand&gt;();
redoList = new Vector.&lt;ICommand&gt;();</pre>
<p>熟悉Java的很容易理解：这就是Java5+中的泛型。</p>
<h3>js中的命令链</h3>
<p>扯了这么远才到js，而且篇幅也不会多长，真是愧对这标题。</p>
<p>js中并不存在接口，所以也就无从说起面向接口编程。然而以此就下定论说“不能使用命令链”尚为时过早。的确，js由于其本身特性原因，不能像传统OOP语言那样使用，但命令链模式其实就存在于日常生活当中：</p>
<pre class="brush:js">function Dog() {
}
Dog.prototype.say = function() {
	this.bark();
}
Dog.prototype.bark = function() {
	alert("汪汪！");
}

function Dingo() {
}
Dingo.prototype = new Dog();
Dingo.prototype.bark = function() {
	alert("呜呜——");
}

function Cock() {
}
Cock.prototype.say = function() {
	this.crow();
}
Cock.prototype.crow = function() {
	alert("喔喔——");
}

function Cat() {
	this.bHappy = true;
}
Cat.prototype.say = function() {
	if(this.bHappy) {
		this.purr();
	}
	else {
		this.mew();
	}
}
Cat.prototype.purr = function() {
	alert("咕噜……");
}
Cat.prototype.mew = function() {
	alert("喵——");
}

var aList = [new Dog(), new Dingo(), new Cock(), new Cat()];
for(var i = 0; i &lt; aList.length; i++) {
	aList[i].say();
}</pre>
<p>基于弱类型，每个类都可以拥有一个同名方法，广义上说这也可以看作是实现了一个“通用接口”。js没有编译过程，因此无法在前期（编译期）实现检查，只能靠后期（运行时）来确定。网上也有很多例子模拟出js的接口和命令链，使得一个类在实现接口但却没有实现接口定义的方法时抛出异常。这样做的好处是在运行出错时有详尽的异常信息供使用者检查，但在目前firebug等工具的情况下所提供的能效有限，在大型的开发中才会有很好的帮助。因此我们目前大部分情况下——似乎最好的办法就是<strong>相信别人</strong>。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/01/25/567.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>jssc 5.0 beta5</title>
		<link>http://army8735.org/2010/01/22/560.html</link>
		<comments>http://army8735.org/2010/01/22/560.html#comments</comments>
		<pubDate>Fri, 22 Jan 2010 01:28:25 +0000</pubDate>
		<dc:creator>army8735</dc:creator>
				<category><![CDATA[jssc]]></category>
		<category><![CDATA[前端开发]]></category>
		<category><![CDATA[beta5]]></category>

		<guid isPermaLink="false">http://army8735.org/?p=560</guid>
		<description><![CDATA[下载页面：http://code.google.com/p/jssc/downloads/list
源码地址：http://jssc.googlecode.com/svn/trunk/
预览效果：http://army8735.org/wp-content/uploads/jssc/
全部是细节方面的调整。
性能有所略微的提升，体积稍微减少一点，可能整体没啥感觉。因为性能瓶颈主要在两方面：as的分析阶段和js的显示阶段。分析阶段中主要是词法分析阶段和字符串拼接阶段，调整的是词法分析阶段，而这个部分占整体所耗时间不是最多的，所以提升不明显。
接口稍微改了下，具体的看源代码。php由原本的纯php代码变为了内嵌显示方式，像html那样。
这个可能是最后一个beta版了，rc如果放出基本都是针对bug的修补，另外会全面更新wiki的使用方法。
说下5.x系列的计划吧：

首先是增加语言：诸如jsp、ruby、csharp等等。语系的增加不会增加子版本号，如5.1，而是后缀的小版本号——5.0.1。
新特性增加将以子版本号形式出现，譬如5.1版本首先考虑的是缓存输出优化（针对代码行上万的高亮显示）。
也是以前考虑实现而没有实现的特性：自动格式化，这个可能难一点，在以后的计划之内吧。

暂且这么多，有想到新的或者别人的想法再列入计划里。
]]></description>
			<content:encoded><![CDATA[<p>下载页面：<a href="http://code.google.com/p/jssc/downloads/list">http://code.google.com/p/jssc/downloads/list</a></p>
<p>源码地址：<a href="http://jssc.googlecode.com/svn/trunk/">http://jssc.googlecode.com/svn/trunk/</a></p>
<p>预览效果：<a href="http://army8735.org/wp-content/uploads/jssc/">http://army8735.org/wp-content/uploads/jssc/</a></p>
<p><strong>全部是细节方面的调整。</strong></p>
<p>性能有所略微的提升，体积稍微减少一点，可能整体没啥感觉。因为性能瓶颈主要在两方面：as的分析阶段和js的显示阶段。分析阶段中主要是词法分析阶段和字符串拼接阶段，调整的是词法分析阶段，而这个部分占整体所耗时间不是最多的，所以提升不明显。</p>
<p>接口稍微改了下，具体的看源代码。php由原本的纯php代码变为了内嵌显示方式，像html那样。</p>
<p>这个可能是最后一个beta版了，rc如果放出基本都是针对bug的修补，另外会全面更新wiki的使用方法。</p>
<p>说下5.x系列的计划吧：</p>
<ol>
<li>首先是增加语言：诸如jsp、ruby、csharp等等。语系的增加不会增加子版本号，如5.1，而是后缀的小版本号——5.0.1。</li>
<li>新特性增加将以子版本号形式出现，譬如5.1版本首先考虑的是缓存输出优化（针对代码行上万的高亮显示）。</li>
<li>也是以前考虑实现而没有实现的特性：自动格式化，这个可能难一点，在以后的计划之内吧。</li>
</ol>
<p>暂且这么多，有想到新的或者别人的想法再列入计划里。</p>
]]></content:encoded>
			<wfw:commentRss>http://army8735.org/2010/01/22/560.html/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
