<?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>简单生活 -- Kevin Yang的博客 &#187; Javascript</title>
	<atom:link href="http://www.imkevinyang.com/tags/javascript/feed" rel="self" type="application/rss+xml" />
	<link>http://www.imkevinyang.com</link>
	<description>It&#039;s all about sharing</description>
	<lastBuildDate>Sun, 05 Feb 2012 15:37:14 +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>Java/Js如何使用正则表达式匹配嵌套Html标签</title>
		<link>http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html</link>
		<comments>http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html#comments</comments>
		<pubDate>Fri, 30 Jul 2010 08:02:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[其他随笔]]></category>
		<category><![CDATA[Html嵌套标签匹配]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[正则表达式]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html</guid>
		<description><![CDATA[<p>以前写过一篇文章讲解如何使用正则表达式完美解决Html嵌套标签的匹配问题（<a title="使用正则表达式匹配嵌套Html标签" href="http://www.imkevinyang.com/2009/07/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%B9%E9%85%8D%E5%B5%8C%E5%A5%97html%E6%A0%87%E7%AD%BE.html" target="_blank">使用正则表达式匹配嵌套Html标签</a>），但是里头用到了平衡组这样的高级特性，貌似只有DotNet还有Perl正则引擎支持，因此通用性不高。有朋友留言说Java直接使用的话会报错。我后来查了一下，发现Java正则引擎支持的特性相对&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>以前写过一篇文章讲解如何使用正则表达式完美解决Html嵌套标签的匹配问题（<a title="使用正则表达式匹配嵌套Html标签" href="http://www.imkevinyang.com/2009/07/%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%B9%E9%85%8D%E5%B5%8C%E5%A5%97html%E6%A0%87%E7%AD%BE.html" target="_blank">使用正则表达式匹配嵌套Html标签</a>），但是里头用到了平衡组这样的高级特性，貌似只有DotNet还有Perl正则引擎支持，因此通用性不高。有朋友留言说Java直接使用的话会报错。我后来查了一下，发现Java正则引擎支持的特性相对比较少。在1.6版本中不能使用命名组（貌似1.7的时候开始支持了），否则会报以下错误，更别说平衡组了。因此感觉要实现无限级的嵌套匹配不大现实。</p>
<blockquote><p>java.util.regex.PatternSyntaxException: Look-behind group does not have an obvious maximum length near index<span style="background-color: #ffffff;"> XX</span></p></blockquote>
<p>在网上搜了好久也没找到完美的解决方案。不过，我们可以实现有限级Html嵌套标签匹配。思路相对于无限级来说就简单了好多，不需要那么多高级的特性。</p>
<p>示例：</p>
<pre class="brush: html">&lt;div id='container'&gt;
    &lt;div style='background-color:gray;' id='footer'&gt;
        &lt;a id='gotop' href='#' onclick='MGJS.goTop();return false;'&gt;Top&lt;/a&gt;
        &lt;a id='powered' href='http://wordpress.org/'&gt;WordPress&lt;/a&gt;
        &lt;div id='copyright'&gt;
            Copyright &amp;copy; 2009 简单生活 —— Kevin Yang的博客
         &lt;/div&gt;
        &lt;div id='themeinfo'&gt;
            Theme by &lt;a href='http://www.neoease.com/'&gt;mg12&lt;/a&gt;. Valid &lt;a href='http://validator.w3.org/check?uri=referer'&gt;XHTML 1.1&lt;/a&gt;
            and &lt;a href='http://jigsaw.w3.org/css-validator/'&gt;CSS 3&lt;/a&gt;.
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</pre>
<p>在上面这个示例中，我们打算匹配id为footer的这个嵌套div，而且<strong>假设我们预先知道footer这个div里面最多只会嵌套一级div</strong>。更多级的情况我们一会儿再讲。</p>
<p>footer的开始和结束标签匹配很简单：</p>
<blockquote><p>&lt;div [^&gt;]*id='footer'[^&gt;]*&gt;......(这里的省略号是一会要填写的)&lt;/div&gt;</p></blockquote>
<p>夹在开始和结束标签之间的内容无非有两种情况：</p>
<ul>
<li>内容A: div标签，并且此div内无嵌套div</li>
<li>内容B: 任意其他内容</li>
</ul>
<p>然后就是这两种内容的不断重复而已。正则表示如下：</p>
<blockquote><p>(<span style="color: #ff0000;">&lt;div[^&gt;]*&gt;.*?&lt;/div&gt;</span>|<span style="color: #008000;"><strong>.</strong></span>)*?</p></blockquote>
<p>注意最后面的问号必须要加上，否则由于正则的贪婪匹配特性，footer的闭合标签会匹配失误。</p>
<p>OK了，<strong>匹配最多嵌套一级div</strong>的正则表达式如下：</p>
<blockquote><p>&lt;div [^&gt;]*id='footer'[^&gt;]*&gt;(<span style="color: #ff0000;">&lt;div[^&gt;]*&gt;.*?&lt;/div&gt;</span>|.)*?&lt;/div&gt;</p></blockquote>
<p>那么如果footer标签里头最多会嵌套两级div的话怎么办呢？</p>
<p>其实也不难，我们只需要把上面的“内容A”部分中的点号稍作替换即可。修改如下：</p>
<blockquote><p>&lt;div [^&gt;]*id='footer'[^&gt;]*&gt;(<span style="color: #ff0000;">&lt;div[^&gt;]*&gt;</span><span style="color: #0000ff;">(&lt;div[^&gt;]*&gt;.*?&lt;/div&gt;|.)</span>*?&lt;/div&gt;|.)*?&lt;/div&gt;</p></blockquote>
<p>到这里你可能就知道，如果要匹配最多嵌套三级div的话，正则应该怎么写了：</p>
<blockquote><p>&lt;div [^&gt;]*id='footer'[^&gt;]*&gt;(<span style="color: #ff0000;">&lt;div[^&gt;]*&gt;</span><span style="color: #0000ff;">(&lt;div[^&gt;]*&gt;</span><span style="color: #ff8000;">(&lt;div[^&gt;]*&gt;.*?&lt;/div&gt;|.)</span>*?&lt;/div&gt;|.)*?&lt;/div&gt;|.)*?&lt;/div&gt;</p></blockquote>
<p>所以实际上，只要你的html结构不是特别复杂的话，也就是说嵌套不会很深的话，那么你完全可以使用这种方式来匹配嵌套html标签。</p>
<p>这个正则在Java和Javascript中都可以使用，因为它没有用到任何高级特性。</p>
<p style="text-align: right;">——<a title="Java/Js如何使用正则表达式匹配嵌套Html标签" href="http://www.imkevinyang.com/2010/07/javajs%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%8C%B9%E9%85%8D%E5%B5%8C%E5%A5%97html%E6%A0%87%E7%AD%BE.html" target="_self"><em>Kevin Yang</em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/html%e5%b5%8c%e5%a5%97%e6%a0%87%e7%ad%be%e5%8c%b9%e9%85%8d" title="Html嵌套标签匹配" rel="tag">Html嵌套标签匹配</a>, <a href="http://www.imkevinyang.com/tags/java" title="Java" rel="tag">Java</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/categories/techarticles/othertecharticles" title="其他随笔" rel="tag">其他随笔</a>, <a href="http://www.imkevinyang.com/tags/%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f" title="正则表达式" rel="tag">正则表达式</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="使用正则表达式匹配嵌套Html标签 (2009/07/22)">使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/08/%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e6%89%be%e5%87%ba%e4%b8%8d%e5%8c%85%e5%90%ab%e7%89%b9%e5%ae%9a%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%9a%84%e6%9d%a1%e7%9b%ae.html" title="使用正则表达式找出不包含特定字符串的条目 (2009/08/04)">使用正则表达式找出不包含特定字符串的条目</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>几个有趣的Javascript Hack</title>
		<link>http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html</link>
		<comments>http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html#comments</comments>
		<pubDate>Fri, 23 Jul 2010 12:06:48 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[显示密码]]></category>
		<category><![CDATA[编辑网页]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html</guid>
		<description><![CDATA[<p>在网上看到几个有意思的Javascript代码，和大家分享一下。</p>
<p style="font-weight: bold">1. 直接在浏览器中编辑网页内容</p>
<pre class="brush: js">javascript:document.body.contentEditable='true';void(0);</pre>
<p><strong></strong></p>
<p>访问任意网站，在地址栏输入以上代码，会发生当前网页已经变成编辑模式了。将上述代码中的true改&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>在网上看到几个有意思的Javascript代码，和大家分享一下。</p>
<p style="font-weight: bold">1. 直接在浏览器中编辑网页内容</p>
<pre class="brush: js">javascript:document.body.contentEditable='true';void(0);</pre>
<p><strong></strong></p>
<p>访问任意网站，在地址栏输入以上代码，会发生当前网页已经变成编辑模式了。将上述代码中的true改成false重新执行一遍即可恢复。</p>
<p><img style="display: inline" title="在浏览器中编辑网页内容" alt="在浏览器中编辑网页内容" src="http://www.imkevinyang.com/wp-content/uploads/2010/07/image14.png" width="581" height="195" /></p>
<p>&#160; </p>
<p style="font-weight: bold">2. 舞动的图片</p>
<pre class="brush: 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.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)+&quot;px&quot;; DIS.top=(Math.cos(R*y1+i*y2+y3)*y4+y5)+&quot;px&quot;}R++}setInterval('A()',5); void(0);</pre>
<p>这段js代码可能很多人已经见识过了。他的作用就是让网页上的图片飞舞起来。</p>
<p><img style="display: inline" title="舞动的图片" alt="舞动的图片" src="http://www.imkevinyang.com/wp-content/uploads/2010/07/image15.png" width="542" height="215" /> </p>
<p>&#160;</p>
<p style="font-weight: bold">3. 密码框密文变明文</p>
<pre class="brush: js">javascript:(function(){var s,F,j,f,i;s=&quot;&quot;;F=document.forms;for(j=0;j&lt;F.length;++j){f=F[j];for(i=0;i&lt;f.length;++i){if(f[i].type.toLowerCase()==&quot;password&quot;)s+=f[i].value+&quot;\n&quot;;}}if(s)alert(&quot;Passwords in forms on this page:\n\n&quot;+s);else alert(&quot;There are no passwords in forms on this page.&quot;);})();</pre>
<p>访问一个带密码框的页面，然后地址栏输入以上代码，就会弹出当前密码框中的密码了，别干坏事哟~</p>
<p><img style="display: inline" title="密码框密文变明文" alt="密码框密文变明文" src="http://www.imkevinyang.com/wp-content/uploads/2010/07/image16.png" width="302" height="288" /> </p>
<p style="text-align: right">——<a title="几个有趣的Javascript Hack" href="http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84Javascript%20Hack.html"><em>Kevin Yang</em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/hack" title="hack" rel="tag">hack</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e6%98%be%e7%a4%ba%e5%af%86%e7%a0%81" title="显示密码" rel="tag">显示密码</a>, <a href="http://www.imkevinyang.com/tags/%e7%bc%96%e8%be%91%e7%bd%91%e9%a1%b5" title="编辑网页" rel="tag">编辑网页</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/02/%e5%bd%93%e5%89%8d%e6%97%a5%e6%9c%9f110%e5%b9%b4.html" title="当前日期110年 (2010/02/12)">当前日期110年</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>为什么IIS7/7.5的Gzip不起作用</title>
		<link>http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html</link>
		<comments>http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html#comments</comments>
		<pubDate>Sat, 08 May 2010 09:56:35 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[疑难杂症]]></category>
		<category><![CDATA[GZip压缩]]></category>
		<category><![CDATA[IIS6]]></category>
		<category><![CDATA[IIS7]]></category>
		<category><![CDATA[IIS7.5]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[动态压缩]]></category>
		<category><![CDATA[静态压缩]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/?p=1418</guid>
		<description><![CDATA[<p>我在<a title="IIS7配置Gzip压缩" href="http://www.imkevinyang.com/2009/06/iis7%E9%85%8D%E7%BD%AEgzip%E5%8E%8B%E7%BC%A9.html" target="_blank">IIS7配置Gzip压缩</a>一文中介绍了IIS7对于gzip压缩的相关配置，以及默认情况下，由于IIS7将Javascript配置为动态压缩（Dynamic Compression），受CPU还有其他因素的影响，不一定会返回gzip压缩后的内容。 但是前阵子发现，尽管将Javascript配置成了静态压&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>我在<a title="IIS7配置Gzip压缩" href="http://www.imkevinyang.com/2009/06/iis7%E9%85%8D%E7%BD%AEgzip%E5%8E%8B%E7%BC%A9.html" target="_blank">IIS7配置Gzip压缩</a>一文中介绍了IIS7对于gzip压缩的相关配置，以及默认情况下，由于IIS7将Javascript配置为动态压缩（Dynamic Compression），受CPU还有其他因素的影响，不一定会返回gzip压缩后的内容。 但是前阵子发现，尽管将Javascript配置成了静态压缩，请求Javascript脚本文件的时候偶尔还是会出现没有gzip的情况。这篇文章和大家分享一下我遇到的这个问题以及解决这个问题的过程和思路，希望对大家有所帮助。</p>
<h2>“随机”的gzip行为</h2>
<p>问题的症状非常简单而又奇怪。有时候连续访问脚本多次，刚开始没有gzip，再次访问又有gzip。等过好一会再去访问，gzip又没有了。有的时候则是无论怎么访问都不给我返回gzip后的响应。</p>
<h2>问题的分析</h2>
<p>排除了CPU负载过大的因素，因为发现当深夜机器CPU负载正常的时候也一样出现这样的问题。</p>
<p>在系统日志中发现以下Warning条目，引起了我的注意：</p>
<blockquote><p>Warning    2010/4/13 6:32:41    IIS-W3SVC-WP    2264    None</p>
<p>The directory specified for caching compressed content C:\inetpub\temp\IIS Temporary Compressed Files\XXX is invalid.  Static compression is being disabled.</p></blockquote>
<p>通过日志筛选，发现从09年7月份就一直出现这样的Warning了，而且出现频率是隔1-3天左右。</p>
<p>这个文件夹是IIS用于存放压缩后的静态内容缓存。按照上面日志的意思，是说这个目录出了问题，导致静态压缩功能被禁用了。但是我明明可以访问这个文件夹，而且里头确实还放着缓存的脚本。</p>
<p>IIS论坛上提这个问题的帖子很多，但最终得到解答的没看到。不过其中一些人的回复倒是给了我不少思路。其中有人说道可能是文件夹权限问题，我看了看那个压缩缓存目录，上面的权限的确是应用程序池的身份，没有问题。使用ProcessMonitor监测了w3wp.exe进程的活动情况，没有看到这个进程在访问文件系统时出现错误。</p>
<p>后来在网上看到了<a href="http://www.ksingla.net/">Kanwaljeet Singla</a>（IIS开发团队成员）的一篇文章，介绍IIS7相比IIS6在压缩模块上的改动，文中提到了一点，<strong><span style="color: #008000;">从IIS7开始，为了降低开销，IIS只对那些频繁访问的静态资源启用压缩</span></strong>。通过IIS7新引入的两个配置选项frequentHitThreshold和frequentHitTimePeriod，我们可以设定，当某个资源在frequentHitTimePeriod时间内被连续访问了frequentHitThreshold次，那么就算是“频繁访问”了。默认的配置是10秒钟内连续对同一Url发起2次请求就算此Url对应的资源属于频繁访问的资源，IIS服务器就会对其进行压缩，然后丢入缓存目录。</p>
<p>这也就解释了为什么有时候第一次请求脚本的时候，服务器没有返回gzip压缩后的内容，而是等你接着下一次访问的时候才会返回gzip响应。</p>
<p><img style="display: inline; border-width: 0px;" title="连续访问Javascript才会gzip" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image2.png" border="0" alt="连续访问Javascript才会gzip" width="494" height="85" /></p>
<p>但是按照这篇文章提到的IIS的设计理念，一旦资源被压缩缓存过，那么以后就不会再应用这个“频繁访问”的检测逻辑了，因为毕竟已经没有压缩开销了。而我非常确信这个脚本已经被缓存在服务器硬盘上了，那为什么我过一段时间再去访问的时候还是没有gzip呢？</p>
<p>在IIS7中有一个功能，叫做失败请求跟踪（Failed request tracing），允许技术人员跟踪那些出问题的请求在IIS内部都发生了什么事。为了揭开我的疑问，我对此网站开启了失败请求跟踪。</p>
<h2>IIS7的Bug？！</h2>
<p>打开IIS7管理器，定位到相应的网站右侧的操作面板，开启“失败请求跟踪”。默认跟踪日志文件是存放在%SystemDrive%\inetpub\logs\FailedReqLogFiles目录中。</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image3.png" border="0" alt="image" width="138" height="93" /> <img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image4.png" border="0" alt="image" width="192" height="120" /></p>
<p>然后在功能面板中找到“失败请求跟踪规则”进行配置：</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image5.png" border="0" alt="image" width="202" height="128" /></p>
<p>为了防止其他脚本的干扰，在这里我限定了只跟踪测试的脚本</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image6.png" border="0" alt="image" width="164" height="159" /></p>
<p>响应状态填写200即可</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image7.png" border="0" alt="image" width="146" height="151" /></p>
<p>接下来是选择跟踪提供程序，也就是给你提供跟踪日志源的程序，由于我们的脚本只经过静态文件处理器，因此这里我们只需要选择www server处理程序即可。</p>
<p><img style="display: inline; border-width: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image8.png" border="0" alt="image" width="274" height="245" /></p>
<p>然后我们就可以去测试一下访问出问题的脚本了。一旦IIS中途处理遇到些问题，那么就会以xml形式记录下相关的日志。打开FailedReqLogFiles目录，里头会有一些fr000001.xml这样格式的文件，每个文件代表一次失败请求。我们打开这个文件，查找compression关键词，发现了以下内容：</p>
<pre class="brush: xml;">&lt;Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event"&gt;
 &lt;System&gt;
  &lt;Provider Name="WWW Server" Guid="{3A2A4E84-4C21-4981-AE10-3FDA0D9B0F83}"/&gt;
  &lt;EventID&gt;0&lt;/EventID&gt;
  &lt;Version&gt;1&lt;/Version&gt;
  &lt;Level&gt;4&lt;/Level&gt;
  &lt;Opcode&gt;3&lt;/Opcode&gt;
  &lt;Keywords&gt;0x40&lt;/Keywords&gt;
  &lt;TimeCreated SystemTime="2010-05-13T16:59:08.086Z"/&gt;
  &lt;Correlation ActivityID="{00000000-0000-0000-FD2B-008041000061}"/&gt;
  &lt;Execution ProcessID="10752" ThreadID="14504"/&gt;
  &lt;Computer&gt;DMZ&lt;/Computer&gt;
 &lt;/System&gt;
 &lt;EventData&gt;
  &lt;Data Name="ContextId"&gt;{00000000-0000-0000-FD2B-008041000061}&lt;/Data&gt;
  &lt;Data Name="Reason"&gt;14&lt;/Data&gt;
 &lt;/EventData&gt;
 &lt;RenderingInfo Culture="zh-CN"&gt;
  &lt;Opcode&gt;STATIC_COMPRESSION_NOT_SUCCESS&lt;/Opcode&gt;
  &lt;Keywords&gt;
   &lt;Keyword&gt;Compression&lt;/Keyword&gt;
  &lt;/Keywords&gt;
  &lt;freb:Description Data="Reason"&gt;NOT_FREQUENTLY_HIT&lt;/freb:Description&gt;
 &lt;/RenderingInfo&gt;
 &lt;ExtendedTracingInfo xmlns="http://schemas.microsoft.com/win/2004/08/events/trace"&gt;
  &lt;EventGuid&gt;{E60CEE96-4472-448D-A13C-2170B18220EC}&lt;/EventGuid&gt;
 &lt;/ExtendedTracingInfo&gt;
&lt;/Event&gt;</pre>
<p>在上面，我们看到了NOT_FREQUENTLY_HIT的字样，看上去响应没有gzip的原因，还是因为没有达到“频繁访问”的要求，即使请求的资源已经被压缩过然后存放在硬盘上了。似乎这个压缩缓存是有一定的时效的，就是过了多长时间就得重新验证一下这个“频繁访问”的逻辑了。</p>
<p>我又进行了大量的测试，发现这个失效时间大约是在5分钟。也就是说，当你频繁访问一个资源，IIS开始对其进行压缩并存放在本地压缩缓存目录之后，大约过5分钟，你再去访问，还是会重新执行“频繁访问”这个验证逻辑。</p>
<p>为了证实我得到的结论，我在推特上向<a href="http://www.ksingla.net/">Kanwaljeet Singla</a>（他的推特是@kjsingla）询问了这个问题。出乎我的意料，他很快就回复了我，估计是因为我在做这个测试的时候已经半夜了，他那边刚好是白天的缘故吧。他经过测试，证实“频繁访问”的逻辑检测发生在“响应是否已经压缩”逻辑之前，这确实是IIS7/7.5的一个Bug。</p>
<p>解决办法倒是很简单，只需要将“频繁访问”定义得更宽泛一些即可。例如1分钟内1次访问。</p>
<pre class="brush: xml">&lt;configuration&gt;
    &lt;system.webServer&gt;
        &lt;serverRuntime frequentHitThreshold="1" frequentHitTimePeriod="00:01:00" /&gt;
    &lt;/system.webServer&gt;
&lt;/configuration&gt;</pre>
<h2>问题真的解决了吗？</h2>
<p>当我以为问题圆满解决，满意的睡着之后，第二天测试的时候发现请求脚本又没有gzip了，而且这次是连着访问好几次都没有压缩，这没法用我昨晚得到的结论去解释。让我非常郁闷-_-|||</p>
<p>冷静！</p>
<p>在系统日志中，我又看到了压缩目录无效的警告信息了，但这次，这个压缩目录是真没了。回想起那个时刻做的操作，当时运营的网站抛出未处理的异常，我修改完这个异常就把应用程序池给重启了。难道是说，当网站出现异常的时候，如果强制回收应用程序池的话，会导致静态压缩目录被删除？更奇怪的是，当我再次回收应用程序池，发现这个压缩目录又被重新创建了。</p>
<p>为了验证我的猜想，我又重复了这个过程，让网站抛出异常=&gt;重启应用程序池=&gt;再次请求脚本，问题重现；我又新建了一个一摸一样配置的测试网站，同样的测试流程，却发现压缩目录正常，没有出现上述的症状。</p>
<p>经过细致的对比，我发现运营的网站和我测试的网站环境还是不大一样的。运营的网站时时刻刻都有外部的请求，而且还很频繁。而测试网站不会有任何干扰的流量。</p>
<p>为了模拟真实的情况，我用iMacro写了一个宏，不间断的向测试网站请求该脚本。一开始，可以看到压缩目录确实是存在的，然后我在中途手动回收了应用程序池。发现压缩缓存目录确实被删除了。</p>
<p><img style="display: inline; border: 0px;" title="image" src="http://www.imkevinyang.com/wp-content/uploads/2010/05/image9.png" border="0" alt="image" width="449" height="115" /></p>
<p>经过再细致的测试，我最终得到一个结论：</p>
<blockquote><p>在IIS7/7.5中，如果为应用程序池配置了administrator的账号权限，那么如果在应用程序池处理静态文件压缩的时候回收应用程序池，会导致压缩缓存目录被删除。直到下次应用程序池健康重启的时候，此压缩缓存目录才会被重新创建。</p></blockquote>
<p>这个结论我还没有得到IIS团队的证实。但在我几台机器上的IIS7和7.5测试的结果确实都是这样的。联想之前的系统日志中，每隔1-3天就出现这样的问题，刚好是因为IIS7默认的回收间隔是1740分钟，也就是1天5小时。我计算了一下系统日志中的所有关于静态压缩目录警告出现的时间，和这个回收间隔的倍数非常吻合。</p>
<p>解决办法有两个：</p>
<ul>
<li>如果没有必要，则不要给应用程序池配置administrator的账号，使用内置的账号不会出现这样的问题。</li>
<li>禁用固定时间间隔回收，改成在一个相对空闲的固定时刻回收，例如半夜4点。</li>
</ul>
<ul>希望我奋战2个晚上得到的结论对你有所帮助~</ul>
<p style="text-align: right;">——<a title="为什么IIS7/7.5的Gzip不起作用" href="http://www.imkevinyang.com/2010/05/%E4%B8%BA%E4%BB%80%E4%B9%88iis77-5%E7%9A%84gzip%E4%B8%8D%E8%B5%B7%E4%BD%9C%E7%94%A8.html" target="_self"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/gzip%e5%8e%8b%e7%bc%a9" title="GZip压缩" rel="tag">GZip压缩</a>, <a href="http://www.imkevinyang.com/tags/iis6" title="IIS6" rel="tag">IIS6</a>, <a href="http://www.imkevinyang.com/tags/iis7" title="IIS7" rel="tag">IIS7</a>, <a href="http://www.imkevinyang.com/tags/iis7-5" title="IIS7.5" rel="tag">IIS7.5</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/%e5%8a%a8%e6%80%81%e5%8e%8b%e7%bc%a9" title="动态压缩" rel="tag">动态压缩</a>, <a href="http://www.imkevinyang.com/categories/techarticles/knottyproblems" title="疑难杂症" rel="tag">疑难杂症</a>, <a href="http://www.imkevinyang.com/tags/%e9%9d%99%e6%80%81%e5%8e%8b%e7%bc%a9" title="静态压缩" rel="tag">静态压缩</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2010/05/64%e4%bd%8d%e7%b3%bb%e7%bb%9f%e4%b8%8biis7-isapi%e5%a4%84%e7%90%86%e5%99%a8%e5%8a%a0%e8%bd%bd%e5%a4%b1%e8%b4%a5.html" title="64位系统下IIS7 ISAPI处理器加载失败 (2010/05/05)">64位系统下IIS7 ISAPI处理器加载失败</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/iis7%e9%85%8d%e7%bd%aegzip%e5%8e%8b%e7%bc%a9.html" title="IIS7配置Gzip压缩 (2009/06/29)">IIS7配置Gzip压缩</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>让博客不用Anti-Spam插件一样没有垃圾评论</title>
		<link>http://www.imkevinyang.com/2010/02/%e8%ae%a9%e5%8d%9a%e5%ae%a2%e4%b8%8d%e7%94%a8anti-spam%e6%8f%92%e4%bb%b6%e4%b8%80%e6%a0%b7%e6%b2%a1%e6%9c%89%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba.html</link>
		<comments>http://www.imkevinyang.com/2010/02/%e8%ae%a9%e5%8d%9a%e5%ae%a2%e4%b8%8d%e7%94%a8anti-spam%e6%8f%92%e4%bb%b6%e4%b8%80%e6%a0%b7%e6%b2%a1%e6%9c%89%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba.html#comments</comments>
		<pubDate>Mon, 15 Feb 2010 17:12:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[工具技巧]]></category>
		<category><![CDATA[AntiSpam plugin]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[博客]]></category>
		<category><![CDATA[垃圾评论]]></category>
		<category><![CDATA[表单]]></category>
		<category><![CDATA[评论机器人]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/02/%e8%ae%a9%e5%8d%9a%e5%ae%a2%e4%b8%8d%e7%94%a8anti-spam%e6%8f%92%e4%bb%b6%e4%b8%80%e6%a0%b7%e6%b2%a1%e6%9c%89%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba.html</guid>
		<description><![CDATA[<p>写博客的人最讨厌的就是垃圾评论了。以前开博才不到半年没有装反垃圾评论插件的时候，平均一天会收到5条左右的垃圾评论，而且一看显然是机器人提交的，后来不得不找插件防着。现在网络上最常见的反垃圾评论插件就是加验证码了。让用户每次发表评论的时候都输入验证码。稍微用户体验好点的就只在用户第一次评论的时候才需要&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>写博客的人最讨厌的就是垃圾评论了。以前开博才不到半年没有装反垃圾评论插件的时候，平均一天会收到5条左右的垃圾评论，而且一看显然是机器人提交的，后来不得不找插件防着。现在网络上最常见的反垃圾评论插件就是加验证码了。让用户每次发表评论的时候都输入验证码。稍微用户体验好点的就只在用户第一次评论的时候才需要验证码，以后就不需要了。但这种方式很容易和那些缓存插件冲突，而且让用户多输入一个验证码感觉也挺无奈的。</p>
<p>后来我就用了WP-SpamFree插件。据说这插件是利用Cookie和Javascript互相配合来实现防范垃圾评论的，细节我没有去深究，不是很清楚。之前观察过一阵子他记录的调试日志，确实是能够100%的拦截垃圾评论，没有误报。</p>
<p>但前阵子这个插件突然大罢工了，随便怎么评论都说我的留言有问题，通不过。经过一番瞎折腾之后，发现又无缘无故好了。但是我对这插件开始有了不信任感~</p>
<p>我后来就在想，与其用别人现成的插件来实现反垃圾评论，为什么不自己实现一个简单易用，而又适合自己实际情况的反垃圾评论机制呢？</p>
<p>我对评论机器人软件不是很熟悉，猜想大概他们会维护一个庞大的博客列表，然后定时去爬取上面的网页，分析页面，找到上面的评论表单——可能是有特征识别，也可能不管三七二十一找到表单就算，然后填写其中的各个字段，最后提交表单。所以<strong><span style="color: #008000;">如果我把评论表单的提交地址给删了，那么评论机器人找不到提交地址或者找到错误的提交地址，就无法成功提交评论了。那真正的用户如何评论呢？我可以在表单加载完之后立刻通过Javascript动态更新评论表单的提交地址就行了</span></strong>。</p>
<p>代码修改非常简单，打开主题文件夹中，找到评论表单所在的模板文件，一般是在comments.php中。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">form</span> <span class="attr">action</span><span class="kwrd">="/wp-comments-post.php"</span> <span class="attr">method</span><span class="kwrd">="post"</span> <span class="attr">id</span><span class="kwrd">="commentform"</span><span class="kwrd">&gt;</span>
...
<span class="kwrd">&lt;/</span><span class="html">form</span><span class="kwrd">&gt;</span></pre>
<p>这是未修改之前的代码。将其action属性的值改为空字符串。然后在结束标签下面添加一行Javascript。如下所示：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">form</span> <span class="attr">action</span><span class="kwrd">=""</span> <span class="attr">method</span><span class="kwrd">="post"</span> <span class="attr">id</span><span class="kwrd">="commentform"</span><span class="kwrd">&gt;</span>
...
<span class="kwrd">&lt;/</span><span class="html">form</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    document.getElementById(<span class="str">"commentform"</span>).action = <span class="str">"/wp-comments-post.php"</span>;
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>OK，这样代码重构完之后就和原来的一样了。</p>
<p>但是这样带来的问题就是，如果对方浏览器禁用了Javascript，那么他也无法评论了。对于我来说，这个比例基本可以忽略。当然，这个方法并不是万金油，不能抵挡所有垃圾评论。毕竟我没有广泛研究过评论机器人的工作原理，有可能人家就是使用自动化脚本模拟用户打开浏览器，输入网址然后填写评论，这也说不准。但是经过半个多月的试验，这个方法还算是比较靠谱的。至今没有见过一条机器人评论。有兴趣的朋友也可以试试。</p>
<p style="text-align: right;">——<a title="让博客不用Anti-Spam插件一样没有垃圾评论" href="http://www.imkevinyang.com/2010/02/%e8%ae%a9%e5%8d%9a%e5%ae%a2%e4%b8%8d%e7%94%a8Anti-Spam%e6%8f%92%e4%bb%b6%e4%b8%80%e6%a0%b7%e6%b2%a1%e6%9c%89%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba.html"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/antispam-plugin" title="AntiSpam plugin" rel="tag">AntiSpam plugin</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/wordpress" title="WordPress" rel="tag">WordPress</a>, <a href="http://www.imkevinyang.com/tags/%e5%8d%9a%e5%ae%a2" title="博客" rel="tag">博客</a>, <a href="http://www.imkevinyang.com/tags/%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba" title="垃圾评论" rel="tag">垃圾评论</a>, <a href="http://www.imkevinyang.com/categories/techarticles/toolskills-techarticles" title="工具技巧" rel="tag">工具技巧</a>, <a href="http://www.imkevinyang.com/tags/%e8%a1%a8%e5%8d%95" title="表单" rel="tag">表单</a>, <a href="http://www.imkevinyang.com/tags/%e8%af%84%e8%ae%ba%e6%9c%ba%e5%99%a8%e4%ba%ba" title="评论机器人" rel="tag">评论机器人</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/10/wordpress%e8%af%84%e8%ae%ba%e4%b8%ad%e4%bf%9d%e7%95%99html%e4%bb%a3%e7%a0%81.html" title="WordPress评论中保留Html代码 (2009/10/31)">WordPress评论中保留Html代码</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/08/%e4%b8%80%e5%8f%a5%e8%af%9d%e5%8d%9a%e5%ae%a22009-08-04.html" title="一句话博客2009-08-04 (2009/08/04)">一句话博客2009-08-04</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/02/%e8%ae%a9%e5%8d%9a%e5%ae%a2%e4%b8%8d%e7%94%a8anti-spam%e6%8f%92%e4%bb%b6%e4%b8%80%e6%a0%b7%e6%b2%a1%e6%9c%89%e5%9e%83%e5%9c%be%e8%af%84%e8%ae%ba.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>当前日期110年</title>
		<link>http://www.imkevinyang.com/2010/02/%e5%bd%93%e5%89%8d%e6%97%a5%e6%9c%9f110%e5%b9%b4.html</link>
		<comments>http://www.imkevinyang.com/2010/02/%e5%bd%93%e5%89%8d%e6%97%a5%e6%9c%9f110%e5%b9%b4.html#comments</comments>
		<pubDate>Thu, 11 Feb 2010 17:27:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[110]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[兼容性]]></category>
		<category><![CDATA[时间函数]]></category>
		<category><![CDATA[脚本]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/02/%e5%bd%93%e5%89%8d%e6%97%a5%e6%9c%9f110%e5%b9%b4.html</guid>
		<description><![CDATA[<p>很多网站，特别是政府网站，喜欢在页面上放置当前的时间，我最近在网上瞎逛的时候注意到，部分网站显示的日期非常诡异，居然是“110年”。我用的是Chrome，所以第一反应就是看看在IE下是不是一样——如果一个做网站的做完之后都不在IE下看一眼的话，那就太不负责任了。果然，IE下显示的是2010年，很正常&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>很多网站，特别是政府网站，喜欢在页面上放置当前的时间，我最近在网上瞎逛的时候注意到，部分网站显示的日期非常诡异，居然是“110年”。我用的是Chrome，所以第一反应就是看看在IE下是不是一样——如果一个做网站的做完之后都不在IE下看一眼的话，那就太不负责任了。果然，IE下显示的是2010年，很正常。</p>
<p>跟了一下Javascript，发现该网站是使用getYear函数来获取当前年份。查了一下JS手册，getYear函数返回的其实是当前年份距离1900年的年数。2010-1900=110。此函数是在ECMAScript v1版本规定实现，到V3版本的时候已经废弃了，getFullYear才是用来获取当前年份的函数。Chrome和Firefox等浏览器在实现的时候都是遵循标准，而IE的JScript在实现的时候却没有遵循标准，结果getYear和getFullYear函数返回的都是当前年份。估计写Javascript的人在使用函数的时候没有看清楚手册说明就直接用了。</p>
<p style="text-align: right;">——<a title="当前日期110年" href="http://www.imkevinyang.com/2010/02/当前日期110年.html"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/110" title="110" rel="tag">110</a>, <a href="http://www.imkevinyang.com/tags/ie" title="IE" rel="tag">IE</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%85%bc%e5%ae%b9%e6%80%a7" title="兼容性" rel="tag">兼容性</a>, <a href="http://www.imkevinyang.com/tags/%e6%97%b6%e9%97%b4%e5%87%bd%e6%95%b0" title="时间函数" rel="tag">时间函数</a>, <a href="http://www.imkevinyang.com/tags/%e8%84%9a%e6%9c%ac" title="脚本" rel="tag">脚本</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/08/firebug%e5%9c%a8edithtml%e6%97%b6%e4%b8%a2%e5%a4%b1%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e5%87%bd%e6%95%b0-2.html" title="Firebug在EditHtml时丢失事件处理函数 (2009/08/19)">Firebug在EditHtml时丢失事件处理函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/09/ie%e6%97%a0%e6%b3%95%e8%ae%be%e7%bd%ae%e7%9f%ad%e5%9f%9f%e5%90%8d%e4%b8%8bcookie.html" title="IE无法设置短域名下Cookie (2010/09/06)">IE无法设置短域名下Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/02/%e5%bd%93%e5%89%8d%e6%97%a5%e6%9c%9f110%e5%b9%b4.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>解析IE中的Javascript Error对象</title>
		<link>http://www.imkevinyang.com/2010/01/%e8%a7%a3%e6%9e%90ie%e4%b8%ad%e7%9a%84javascript-error%e5%af%b9%e8%b1%a1.html</link>
		<comments>http://www.imkevinyang.com/2010/01/%e8%a7%a3%e6%9e%90ie%e4%b8%ad%e7%9a%84javascript-error%e5%af%b9%e8%b1%a1.html#comments</comments>
		<pubDate>Sun, 17 Jan 2010 06:31:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[Error]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[异常处理机制]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2010/01/%e8%a7%a3%e6%9e%90ie%e4%b8%ad%e7%9a%84javascript-error%e5%af%b9%e8%b1%a1.html</guid>
		<description><![CDATA[<p>之前写过一篇<a title="Javascript获取出错代码所在行数及文件名" href="http://www.imkevinyang.com/2009/05/javascript%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%87%BA%E9%94%99%E4%BB%A3%E7%A0%81%E6%89%80%E5%9C%A8%E6%96%87%E4%BB%B6%E5%8F%8A%E8%A1%8C%E6%95%B0.html" target="_blank">文章</a>，提到怎么在各个浏览器下返回执行错误的Javascript代码所在的行数以及文件名。其中在IE下，如果你使用了try-catch，那么当出现异常的时候，浏览器会传递一个Error对象。</p>
<pre class="csharpcode"><span class="kwrd">&#60;</span><span class="html">script</span><span class="kwrd">&#62;</span>
    <span class="kwrd">try</span>{
        sldfj
    }<span class="kwrd">catch</span>(e){
        <span class="kwrd">for</span>(<span class="kwrd">var</span> p <span class="kwrd">in</span> e){
            docu&#8230;</pre>]]></description>
			<content:encoded><![CDATA[<p>之前写过一篇<a title="Javascript获取出错代码所在行数及文件名" href="http://www.imkevinyang.com/2009/05/javascript%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%87%BA%E9%94%99%E4%BB%A3%E7%A0%81%E6%89%80%E5%9C%A8%E6%96%87%E4%BB%B6%E5%8F%8A%E8%A1%8C%E6%95%B0.html" target="_blank">文章</a>，提到怎么在各个浏览器下返回执行错误的Javascript代码所在的行数以及文件名。其中在IE下，如果你使用了try-catch，那么当出现异常的时候，浏览器会传递一个Error对象。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span><span class="kwrd">&gt;</span>
    <span class="kwrd">try</span>{
        sldfj
    }<span class="kwrd">catch</span>(e){
        <span class="kwrd">for</span>(<span class="kwrd">var</span> p <span class="kwrd">in</span> e){
            document.writeln(p + <span class="str">&quot;=&quot;</span> + e[p]);
        }
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>输出：name=TypeError message='sldfj' 未定义 number=-2146823279 description='sldfj' 未定义</p>
<p>其中的number属性是一个整数，表示的是错误码，但这并不是真正的错误码，我们需要先将其做一下转换</p>
<pre class="csharpcode"><span class="kwrd">var</span> errCode = err.number&amp; x0FFFF; </pre>
<p>这得到真正的错误码，例如上述的-2146823279 转换之后就得到5009。有了这个错误码之后，我们可以到<a href="http://msdn.microsoft.com/en-us/library/1dk3k160(VS.85).aspx">http://msdn.microsoft.com/en-us/library/1dk3k160(VS.85).aspx</a>微软msdn上查找此错误码对应的。5009对应的错误是Undefined identifier。</p>
<p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/error" title="Error" rel="tag">Error</a>, <a href="http://www.imkevinyang.com/tags/ie" title="IE" rel="tag">IE</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%bc%82%e5%b8%b8%e5%a4%84%e7%90%86%e6%9c%ba%e5%88%b6" title="异常处理机制" rel="tag">异常处理机制</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/09/ie%e6%97%a0%e6%b3%95%e8%ae%be%e7%bd%ae%e7%9f%ad%e5%9f%9f%e5%90%8d%e4%b8%8bcookie.html" title="IE无法设置短域名下Cookie (2010/09/06)">IE无法设置短域名下Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2010/01/%e8%a7%a3%e6%9e%90ie%e4%b8%ad%e7%9a%84javascript-error%e5%af%b9%e8%b1%a1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Button标签鼠标点击事件的触发源问题</title>
		<link>http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html</link>
		<comments>http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html#comments</comments>
		<pubDate>Thu, 26 Nov 2009 16:10:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[Button]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[兼容性]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html</guid>
		<description><![CDATA[<p>写Javascript有时候真是挺郁闷的，一听到兼容性问题就头大。好多东西看起来简简单单的，还是得拿到至少5大主流浏览器上去测试才能放心。像下面的这个例子，button标签内嵌套了一个img标签。</p>
<pre class="csharpcode"><span class="kwrd">&#60;</span><span class="html">body</span><span class="kwrd">&#62;</span>
    <span class="kwrd">&#60;</span><span class="html">button</span> <span class="attr">id</span><span class="kwrd">=&#34;test&#34;</span><span class="kwrd">&#62;</span>
          <span class="kwrd">&#60;</span><span class="html">img&#8230;</span></pre>]]></description>
			<content:encoded><![CDATA[<p>写Javascript有时候真是挺郁闷的，一听到兼容性问题就头大。好多东西看起来简简单单的，还是得拿到至少5大主流浏览器上去测试才能放心。像下面的这个例子，button标签内嵌套了一个img标签。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">button</span> <span class="attr">id</span><span class="kwrd">=&quot;test&quot;</span><span class="kwrd">&gt;</span>
          <span class="kwrd">&lt;</span><span class="html">img</span> <span class="attr">src</span><span class="kwrd">=&quot;http://www.google.cn/favicon.ico&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">button</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">script</span><span class="kwrd">&gt;</span>
        document.getElementById(<span class="str">&quot;test&quot;</span>).onclick=<span class="kwrd">function</span>(e){
            <span class="kwrd">if</span> (!e) {
                e = window.<span class="kwrd">event</span>;
            }
            <span class="kwrd">if</span> (!e.target &amp;&amp; e.srcElement) {
                e.target = e.srcElement;
            }
            alert(e.target.tagName);
        }
    <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span></pre>
<p>运行的时候先显示一个小图标：</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/11/image_thumb23.png" width="41" height="46" /> </p>
<p>点击此按钮（无论你点在哪，图标上，还是Button上），那么触发源是什么呢？直观的来看，点正中央的话应该是IMG吧，点图标边缘Button的部分触发源应该是Button吧。</p>
<p>可是在IE各个版本上（使用IETester可以测试不同版本IE的兼容性）和Firefox、Opera上测试的结果均是BUTTON。</p>
<p><img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="http://www.imkevinyang.com/wp-content/uploads/2009/11/image_thumb24.png" width="244" height="129" /> </p>
<p>本来以为这样就完事了，以后记住就行了，后来发现，Chrome和Safari（它们核心是一样的）上的行为和正常的期望是一致的，也就是说点中央的话，触发源是IMG，点边缘的话触发源是BUTTON。</p>
<p>又测试了Button内包含其他HTML标签，行为和IMG一样。不知道为什么要这样实现。真希望某一天所有不合标准的浏览器，特别是IE6彻底毁灭了，这样Web开发人员就可以少头疼一下了。</p>
<p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/button" title="Button" rel="tag">Button</a>, <a href="http://www.imkevinyang.com/tags/html" title="HTML" rel="tag">HTML</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%85%bc%e5%ae%b9%e6%80%a7" title="兼容性" rel="tag">兼容性</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/pre%e6%a0%87%e7%ad%be%e5%86%85%e6%96%87%e5%ad%97%e8%87%aa%e5%8a%a8%e6%8d%a2%e8%a1%8c%ef%bc%88%e5%85%bc%e5%ae%b9%e5%a4%9a%e6%95%b0%e4%b8%bb%e6%b5%81%e6%b5%8f%e8%a7%88%e5%99%a8%ef%bc%89.html" title="Pre标签内文字自动换行（兼容多数主流浏览器） (2009/04/09)">Pre标签内文字自动换行（兼容多数主流浏览器）</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/10/wordpress%e8%af%84%e8%ae%ba%e4%b8%ad%e4%bf%9d%e7%95%99html%e4%bb%a3%e7%a0%81.html" title="WordPress评论中保留Html代码 (2009/10/31)">WordPress评论中保留Html代码</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用相对Url无缝切换HTTP-HTTPS</title>
		<link>http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html</link>
		<comments>http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html#comments</comments>
		<pubDate>Thu, 17 Sep 2009 18:05:40 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[技术随笔]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[HTTPS]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Scheme省略]]></category>
		<category><![CDATA[URI]]></category>
		<category><![CDATA[Url]]></category>
		<category><![CDATA[相对URL]]></category>
		<category><![CDATA[相对路径]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html</guid>
		<description><![CDATA[概述
<p>在HTTPS的网站下，如果要访问HTTP资源，那么一般浏览器会弹出窗口询问用户是否允许加载不安全内容，云云。为了避免出现这样干扰用户的情况，所有网页下请求的资源都都必须是HTTPS资源。如果你的站点支持HTTP和HTTPS两种方式访问，而实际网站只有一份的话，这种情况下，你可以使用相对Url的方&#8230;</p>]]></description>
			<content:encoded><![CDATA[<h2>概述</h2>
<p>在HTTPS的网站下，如果要访问HTTP资源，那么一般浏览器会弹出窗口询问用户是否允许加载不安全内容，云云。为了避免出现这样干扰用户的情况，所有网页下请求的资源都都必须是HTTPS资源。如果你的站点支持HTTP和HTTPS两种方式访问，而实际网站只有一份的话，这种情况下，你可以使用相对Url的方式改写网页内资源的请求Url。</p>
<h2>省略Scheme的相对Url语法</h2>
<p>Url相对路径我们并不陌生，下面这样的写法非常常见。</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">img</span> <span class="attr">src</span><span class="kwrd">='/images/myphoto.jpg'</span> <span class="kwrd">/&gt;</span>
<span class="kwrd">&lt;</span><span class="html">img</span> <span class="attr">src</span><span class="kwrd">='myphoto.jpg'</span> <span class="kwrd">/&gt;</span></pre>
<p>如果该HTML代码放在http://myexample.com/myblog/index.html上，那么第一幅图片的实际完整地址就是http://myexample.com/images/myphoto.jpg，而第二幅图片的实际地址是http://myexample.com/myblog/myphoto.jpg。</p>
<p>但是省略Url中的Scheme部分这样的相对路径写法却比较少见。例如：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">img</span> <span class="attr">src</span><span class="kwrd">='//myimagehosting.com/images/myphoto.jpg'</span> <span class="kwrd">/&gt;</span></pre>
<p>这行代码如果放在HTTP的网页上，那么请求的资源就是HTTP:<span class="kwrd">//myimagehosting.com/images/myphoto.jpg，如果放在HTTPS上，则访问的资源就是HTTPS的。这样一来我们就无需为HTTP和HTTPS各自准备不同的网页了。</span></p>
<h2><span class="kwrd">标准规范</span></h2>
<p><span class="kwrd"></span></p>
<p><span class="kwrd"></span></p>
<p>RFC1808文档是专门针对相对URI的，其中提到，除了URI中的Scheme部分，其他部分均可以做适当的省略。也就是说，这样的写法是不符合规范。RFC1808文档是95年的时候定稿的。后来的RFC3986文档对URI做出了更为详细的规范，废弃了RFC1808对相对URI引用的建议规范（4.2 Relative Reference一节）。</p>
<p><strong><font color="#008000"></p>
<p>以Scheme:开头的（如http:、file:、ftp:）均为绝对URI引用。否则为相对URI引用。</p>
<p>相对路径 = 相对部分 [ &quot;?&quot; 查询参数] [ &quot;#&quot; 锚点]</p>
<p>  </font></strong></p>
<p>其中相对部分可以有以下几种情况：</p>
<p>1. //主机域 绝对路径或者留空</p>
<p>2. 绝对路径</p>
<p>3. 相对路径</p>
<p>4. 留空</p>
<p>也就是说，以下几种情况均是合法的相对URI引用：</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">src</span><span class="kwrd">='//myscript.com/script.js?cid=abcd'</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
&lt;script src=<span class="str">'//myscript.com?cid=abcd'</span>&gt;&lt;/script&gt;
&lt;script src=<span class="str">'/script.js?cid=abcd'</span>&gt;&lt;/script&gt;
&lt;script src=<span class="str">'../script.js?cid=abcd'</span>&gt;<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<h2>总结</h2>
<p>以上这种省略Scheme部分的相对路径的写法在IE7、IE8、Firefox、Chrome、Opera以及Safari中均测试通过。pconline上面就有用到这样的写法。使用这个特性，可以降低代码的复杂性。Google Analytics在生成代码的时候会检测当前协议来决定加载http还是https的脚本，然后动态插入一段脚本。不知道为什么它不使用这样的方式来实现自适应。</p>
<p>参考文档：</p>
<p><a href="http://nedbatchelder.com/blog/200710/httphttps_transitions_and_relative_urls.html">Http-https transitions and relative URLs</a></p>
<p><a title="RFC3986 Uniform Resource Identifier" href="http://www.ietf.org/rfc/rfc3986.txt" target="_blank">RFC3986</a></p>
<p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/http" title="HTTP" rel="tag">HTTP</a>, <a href="http://www.imkevinyang.com/tags/https" title="HTTPS" rel="tag">HTTPS</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/scheme%e7%9c%81%e7%95%a5" title="Scheme省略" rel="tag">Scheme省略</a>, <a href="http://www.imkevinyang.com/tags/uri" title="URI" rel="tag">URI</a>, <a href="http://www.imkevinyang.com/tags/url" title="Url" rel="tag">Url</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/categories/techarticles" title="技术随笔" rel="tag">技术随笔</a>, <a href="http://www.imkevinyang.com/tags/%e7%9b%b8%e5%af%b9url" title="相对URL" rel="tag">相对URL</a>, <a href="http://www.imkevinyang.com/tags/%e7%9b%b8%e5%af%b9%e8%b7%af%e5%be%84" title="相对路径" rel="tag">相对路径</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2010/05/64%e4%bd%8d%e7%b3%bb%e7%bb%9f%e4%b8%8biis7-isapi%e5%a4%84%e7%90%86%e5%99%a8%e5%8a%a0%e8%bd%bd%e5%a4%b1%e8%b4%a5.html" title="64位系统下IIS7 ISAPI处理器加载失败 (2010/05/05)">64位系统下IIS7 ISAPI处理器加载失败</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/02/silverlight%e5%90%af%e7%94%a8assembly-caching%e4%b9%8b%e5%90%8e%e9%93%81%e9%80%9a%e7%94%a8%e6%88%b7%e6%97%a0%e6%b3%95%e8%ae%bf%e9%97%ae.html" title="Silverlight启用Assembly Caching之后铁通用户无法访问 (2010/02/13)">Silverlight启用Assembly Caching之后铁通用户无法访问</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/%e3%80%90%e6%8e%a8%e8%8d%90%e3%80%91%e4%b8%a4%e6%ac%behttp%e6%b5%81%e9%87%8f%e5%88%86%e6%9e%90%e5%b7%a5%e5%85%b7%e7%9a%84%e6%af%94%e8%be%83.html" title="【推荐】两款HTTP流量分析工具的比较 (2009/11/08)">【推荐】两款HTTP流量分析工具的比较</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>详解Javascript中的Url编码/解码</title>
		<link>http://www.imkevinyang.com/2009/08/%e8%af%a6%e8%a7%a3javascript%e4%b8%ad%e7%9a%84url%e7%bc%96%e8%a7%a3%e7%a0%81.html</link>
		<comments>http://www.imkevinyang.com/2009/08/%e8%af%a6%e8%a7%a3javascript%e4%b8%ad%e7%9a%84url%e7%bc%96%e8%a7%a3%e7%a0%81.html#comments</comments>
		<pubDate>Tue, 18 Aug 2009 17:21:35 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[RFC文档]]></category>
		<category><![CDATA[UrlEncode]]></category>
		<category><![CDATA[Url编码]]></category>
		<category><![CDATA[字符集]]></category>
		<category><![CDATA[编解码]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/08/%e8%af%a6%e8%a7%a3javascript%e4%b8%ad%e7%9a%84url%e7%bc%96%e8%a7%a3%e7%a0%81.html</guid>
		<description><![CDATA[摘要
<p>本文主要针对URI编解码的相关问题做了介绍，对Url编码中哪些字符需要编码、为什么需要编码做了详细的说明，并对比分析了Javascript中和编解码相关的几对函数escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURICom&#8230;</p>]]></description>
			<content:encoded><![CDATA[<h2>摘要</h2>
<p>本文主要针对URI编解码的相关问题做了介绍，对Url编码中哪些字符需要编码、为什么需要编码做了详细的说明，并对比分析了Javascript中和编解码相关的几对函数escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURIComponent。</p>
<h2>预备知识</h2>
<p>&#160;&#160; foo://example.com:8042/over/there?name=ferret#nose&#160; <br />&#160;&#160; \_/&#160; \______________/ \________/\_________/ \__/     <br />&#160;&#160;&#160;&#160; |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; |     <br />scheme&#160;&#160;&#160;&#160; authority&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; path&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; query&#160;&#160;&#160;&#160;&#160; fragment</p>
<p>URI是统一资源标识的意思，通常我们所说的Url只是URI的一种。典型Url的格式如上面所示。下面提到的Url编码，实际上应该指的是URI编码。</p>
<h2>为什么需要Url编码</h2>
<p>通常如果一样东西需要编码，说明这样东西并不适合传输。原因多种多样，如Size过大，包含隐私数据，<strong><font color="#008000">对于Url来说，之所以要进行编码，是因为Url中有些字符会引起歧义</font></strong>。</p>
<p>例如Url参数字符串中使用key=value键值对这样的形式来传参，键值对之间以&amp;符号分隔，如/s?q=abc&amp;ie=utf-8。如果你的value字符串中包含了=或者&amp;，那么势必会造成接收Url的服务器解析错误，因此必须将引起歧义的&amp;和=符号进行转义，也就是对其进行编码。</p>
<p>又如，Url的编码格式采用的是ASCII码，而不是Unicode，这也就是说你不能在Url中包含任何非ASCII字符，例如中文。否则如果客户端浏览器和服务端浏览器支持的字符集不同的情况下，中文可能会造成问题。</p>
<p><strong><font color="#008000">Url编码的原则就是使用安全的字符（没有特殊用途或者特殊意义的可打印字符）去表示那些不安全的字符。</font></strong></p>
<h2>哪些字符需要编码</h2>
<blockquote><p>RFC3986文档规定，Url中只允许包含英文字母（a-zA-Z）、数字（0-9）、-_.~4个特殊字符以及所有保留字符。</p>
</blockquote>
<p>RFC3986文档对Url的编解码问题做出了详细的建议，指出了哪些字符需要被编码才不会引起Url语义的转变，以及对为什么这些字符需要编码做出了相应的解释。</p>
<h3>US-ASCII字符集中没有对应的可打印字符</h3>
<p>Url中只允许使用可打印字符。US-ASCII码中的10-7F字节全都表示控制字符，这些字符都不能直接出现在Url中。同时，对于80-FF字节（ISO-8859-1），由于已经超出了US-ACII定义的字节范围，因此也不可以放在Url中。</p>
<h3>保留字符</h3>
<p>Url可以划分成若干个组件，协议、主机、路径等。有一些字符（:/?#[]@）是用作分隔不同组件的。例如:冒号用于分隔协议和主机，/用于分隔主机和路径，?用于分隔路径和查询参数，等等。还有一些字符（!$&amp;'()*+,;=）用于在每个组件中起到分隔作用的，如=用于表示查询参数中的键值对，&amp;符号用于分隔查询多个键值对。当组件中的普通数据包含这些特殊字符时，需要对其进行编码。</p>
<p>RFC3986中指定了以下字符为保留字符：</p>
<table border="1" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td title="Exclamation mark">!</td>
<td title="Asterisk">*</td>
<td title="Apostrophe (mark)">'</td>
<td title="Bracket">(</td>
<td title="Bracket">)</td>
<td title="Semicolon">;</td>
<td title="Colon (punctuation)">:</td>
<td title="@">@</td>
<td title="Ampersand">&amp;</td>
<td title="Equal sign">=</td>
<td title="Plus sign">+</td>
<td title="Dollar sign">$</td>
<td title="Comma (punctuation)">,</td>
<td title="Slash (punctuation)">/</td>
<td title="Question mark">?</td>
<td title="Number sign">#</td>
<td title="Bracket">[</td>
<td title="Bracket">]</td>
</tr>
</tbody>
</table>
<h3>不安全字符</h3>
<p>还有一些字符，当他们直接放在Url中的时候，可能会引起解析程序的歧义。这些字符被视为不安全字符，原因有很多。</p>
<table border="1" cellspacing="0" cellpadding="2" width="575">
<tbody>
<tr>
<td valign="top" width="72">空格</td>
<td valign="top" width="501">Url在传输的过程，或者用户在排版的过程，或者文本处理程序在处理Url的过程，都有可能引入无关紧要的空格，或者将那些有意义的空格给去掉</td>
</tr>
<tr>
<td valign="top" width="72">引号以及&lt;&gt;</td>
<td valign="top" width="501">引号和尖括号通常用于在普通文本中起到分隔Url的作用</td>
</tr>
<tr>
<td valign="top" width="72">#</td>
<td valign="top" width="501">通常用于表示书签或者锚点</td>
</tr>
<tr>
<td valign="top" width="72">%</td>
<td valign="top" width="501">百分号本身用作对不安全字符进行编码时使用的特殊字符，因此本身需要编码</td>
</tr>
<tr>
<td valign="top" width="72">{}|\^[]`~</td>
<td valign="top" width="501">某一些网关或者传输代理会篡改这些字符</td>
</tr>
</tbody>
</table>
<p>&#160;</p>
<p><strong><font color="#008000">需要注意的是，对于Url中的合法字符，编码和不编码是等价的，但是对于上面提到的这些字符，如果不经过编码，那么它们有可能会造成Url语义的不同。因此对于Url而言，只有普通英文字符和数字，特殊字符$-_.+!*'()还有保留字符，才能出现在未经编码的Url之中</font></strong>。其他字符均需要经过编码之后才能出现在Url中。</p>
<p>但是由于历史原因，目前尚存在一些不标准的编码实现。例如对于~符号，虽然RFC3986文档规定，对于波浪符号~，不需要进行Url编码，但是还是有很多老的网关或者传输代理会</p>
<h2>如何对Url中的非法字符进行编码</h2>
<p>Url编码通常也被称为百分号编码（Url Encoding，also known as percent-encoding），是因为它的编码方式非常简单，使用%百分号加上两位的字符——0123456789ABCDEF——代表一个字节的十六进制形式。Url编码默认使用的字符集是US-ASCII。例如a在US-ASCII码中对应的字节是0x61，那么Url编码之后得到的就是%61，我们在地址栏上输入http://g.cn/search?q=%61%62%63，实际上就等同于在google上搜索abc了。又如@符号在ASCII字符集中对应的字节为0x40，经过Url编码之后得到的是%40。</p>
<p>常见字符的Url编码列表：</p>
<table border="1" cellspacing="0" cellpadding="6">
<caption>保留字符的Url编码</caption>
<tbody>
<tr>
<td>!</td>
<td>*</td>
<td>&quot;</td>
<td>'</td>
<td>(</td>
<td>)</td>
<td>;</td>
<td>:</td>
<td>@</td>
<td>&amp;</td>
</tr>
<tr>
<td><code>%21</code></td>
<td><code>%2A</code></td>
<td><code>%22</code></td>
<td><code>%27</code></td>
<td><code>%28</code></td>
<td><code>%29</code></td>
<td><code>%3B</code></td>
<td><code>%3A</code></td>
<td><code>%40</code></td>
<td><code>%26</code></td>
</tr>
<tr>
<td>=</td>
<td>+</td>
<td>$</td>
<td>,</td>
<td>/</td>
<td>?</td>
<td>%</td>
<td>#</td>
<td>[</td>
<td>]</td>
</tr>
<tr>
<td><code>%3D</code></td>
<td><code>%2B</code></td>
<td><code>%24</code></td>
<td><code>%2C</code></td>
<td><code>%2F</code></td>
<td><code>%3F</code></td>
<td><code>%25</code></td>
<td><code>%23</code></td>
<td><code>%5B</code></td>
<td><code>%5D</code></td>
</tr>
</tbody>
</table>
<p><strong><font color="#008000">对于非ASCII字符，需要使用ASCII字符集的超集进行编码得到相应的字节，然后对每个字节执行百分号编码</font></strong>。对于Unicode字符，RFC文档建议使用utf-8对其进行编码得到相应的字节，然后对每个字节执行百分号编码。如“中文”使用UTF-8字符集得到的字节为0xE4 0xB8 0xAD 0xE6 0x96 0x87，经过Url编码之后得到“%E4%B8%AD%E6%96%87”。</p>
<p><strong><font color="#008000">如果某个字节对应着ASCII字符集中的某个非保留字符，则此字节无需使用百分号表示</font></strong>。例如“Url编码”，使用UTF-8编码得到的字节是0x55 0x72 0x6C 0xE7 0xBC 0x96 0xE7 0xA0 0x81，由于前三个字节对应着ASCII中的非保留字符“Url”，因此这三个字节可以用非保留字符“Url”表示。最终的Url编码可以简化成“Url%E7%BC%96%E7%A0%81” ，当然，如果你用&quot;%55%72%6C%E7%BC%96%E7%A0%81”也是可以的。</p>
<p>由于历史的原因，有一些Url编码实现并不完全遵循这样的原则，下面会提到。</p>
<h2>Javascript中的escape,encodeURI和encodeURIComponent的区别</h2>
<p>Javascript中提供了3对函数用来对Url编码以得到合法的Url，它们分别是escape / unescape,encodeURI / decodeURI和encodeURIComponent / decodeURIComponent。由于解码和编码的过程是可逆的，因此这里只解释编码的过程。</p>
<p>这三个编码的函数——escape，encodeURI，encodeURIComponent——都是用于将不安全不合法的Url字符转换为合法的Url字符表示，它们有以下几个不同点。</p>
<h3>安全字符不同</h3>
<p>下面的表格列出了这三个函数的安全字符（即函数不会对这些字符进行编码）</p>
<table border="1" cellspacing="0" cellpadding="2" width="531">
<tbody>
<tr>
<td valign="top" width="214">&#160;</td>
<td valign="top" width="315">安全字符</td>
</tr>
<tr>
<td valign="top" width="214">escape（69个）</td>
<td valign="top" width="315">*/@+<font color="#000080">-._0-9a-zA-Z</font></td>
</tr>
<tr>
<td valign="top" width="214">encodeURI（82个）</td>
<td valign="top" width="315">!#$&amp;'()*+,/:;=?@<font color="#000080">-._~0-9a-zA-Z </font></td>
</tr>
<tr>
<td valign="top" width="214">encodeURIComponent（71个）</td>
<td valign="top" width="315">!'()*<font color="#000080">-._~0-9a-zA-Z</font></td>
</tr>
</tbody>
</table>
<h3>兼容性不同</h3>
<p>escape函数是从Javascript1.0的时候就存在了，其他两个函数是在Javascript1.5才引入的。但是由于Javascript1.5已经非常普及了，所以实际上使用encodeURI和encodeURIComponent并不会有什么兼容性问题。</p>
<h3>对Unicode字符的编码方式不同</h3>
<p>这三个函数对于ASCII字符的编码方式相同，均是使用百分号+两位十六进制字符来表示。但是对于Unicode字符，escape的编码方式是%u<i>xxxx</i>，其中的xxxx是用来表示unicode字符的4位十六进制字符。这种方式已经被W3C废弃了。但是在ECMA-262标准中仍然保留着escape的这种编码语法。<strong><font color="#008000">encodeURI和encodeURIComponent则使用UTF-8对非ASCII字符进行编码，然后再进行百分号编码</font></strong>。这是RFC推荐的。因此建议尽可能的使用这两个函数替代escape进行编码。</p>
<h3>适用场合不同</h3>
<p>encodeURI被用作对一个完整的URI进行编码，而encodeURIComponent被用作对URI的一个组件进行编码。</p>
<p>从上面提到的安全字符范围表格来看，我们会发现，encodeURIComponent编码的字符范围要比encodeURI的大。我们上面提到过，保留字符一般是用来分隔URI组件（一个URI可以被切割成多个组件，参考预备知识一节）或者子组件（如URI中查询参数的分隔符），如:号用于分隔scheme和主机，?号用于分隔主机和路径。由于encodeURI操纵的对象是一个完整的的URI，这些字符在URI中本来就有特殊用途，因此这些保留字符不会被encodeURI编码，否则意义就变了。</p>
<p>组件内部有自己的数据表示格式，但是这些数据内部不能包含有分隔组件的保留字符，否则就会导致整个URI中组件的分隔混乱。因此对于单个组件使用encodeURIComponent，需要编码的字符就更多了。</p>
<h2>表单提交</h2>
<p>当Html的表单被提交时，每个表单域都会被Url编码之后才在被发送。由于历史的原因，表单使用的Url编码实现并不符合最新的标准。例如对于空格使用的编码并不是%20，而是+号，如果表单使用的是Post方法提交的，我们可以在HTTP头中看到有一个Content-Type的header，值为application/x-www-form-urlencoded。大部分应用程序均能处理这种非标准实现的Url编码，但是在客户端Javascript中，并没有一个函数能够将+号解码成空格，只能自己写转换函数。还有，对于非ASCII字符，使用的编码字符集取决于当前文档使用的字符集。例如我们在Html头部加上</p>
<pre class="csharpcode"><span class="kwrd">&lt;</span><span class="html">meta</span> <span class="attr">http-equiv</span><span class="kwrd">=&quot;Content-Type&quot;</span> <span class="attr">content</span><span class="kwrd">=&quot;text/html; charset=gb2312&quot;</span> <span class="kwrd">/&gt;</span></pre>
<p>这样浏览器就会使用gb2312去渲染此文档（注意，当HTML文档中没有设置此meta标签，则浏览器会根据当前用户喜好去自动选择字符集，用户也可以强制当前网站使用某个指定的字符集）。当提交表单时，Url编码使用的字符集就是gb2312。</p>
<h2>文档字符集会影响encodeURI吗？</h2>
<p>之前在使用Aptana（为什么专指aptana下面会提到）遇到一个很迷惑的问题，就是在使用encodeURI的时候，发现它编码得到的结果和我想的很不一样。下面是我的示例代码：</p>
<pre class="csharpcode">

<span class="kwrd">&lt;!</span><span class="html">DOCTYPE</span> <span class="attr">html</span> <span class="attr">PUBLIC</span> <span class="kwrd">&quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot;</span> <span class="kwrd">&quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">html</span> <span class="attr">xmlns</span><span class="kwrd">=&quot;http://www.w3.org/1999/xhtml&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">head</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">meta</span> <span class="attr">http-equiv</span><span class="kwrd">=&quot;Content-Type&quot;</span> <span class="attr">content</span><span class="kwrd">=&quot;text/html; charset=gb2312&quot;</span> <span class="kwrd">/&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">head</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;</span><span class="html">body</span><span class="kwrd">&gt;</span>
        <span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
            document.write(encodeURI(<span class="str">&quot;中文&quot;</span>));
        <span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
    <span class="kwrd">&lt;/</span><span class="html">body</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;/</span><span class="html">html</span><span class="kwrd">&gt;</span>

<span class="kwrd"></span>&#160;
</pre>
<p>运行结果输出%E6%B6%93%EE%85%9F%E6%9E%83。显然这并不是使用UTF-8字符集进行Url编码得到的结果（在Google上搜索“中文”，Url中显示的是%E4%B8%AD%E6%96%87）。</p>
<p>所以我当时就很质疑，难道encodeURI还跟页面编码有关，但是我发现，正常情况下，如果你使用gb2312进行Url编码也不会得到这个结果的才是。后来终于被我发现，原来是<strong><font color="#008000">页面文件存储使用的字符集和Meta标签中指定的字符集不一致导致的问题</font></strong>。Aptana的编辑器默认情况下使用UTF-8字符集。也就是说这个文件实际存储的时候使用的是UTF-8字符集。但是由于Meta标签中指定了gb2312，这个时候，浏览器就会按照gb2312去解析这个文档，那么自然在“中文”这个字符串这里就会出错，因为“中文”字符串用UTF-8编码过后得到的字节是0xE4 0xB8 0xAD 0xE6 0x96 0x87，这6个字节又被浏览器拿gb2312去解码，那么就会得到另外三个汉字“涓枃”（GBK中一个汉字占两个字节），这三个汉字在传入encodeURI函数之后得到的结果就是%E6%B6%93%EE%85%9F%E6%9E%83。因此，encodeURI使用的还是UTF-8，并不会受到页面字符集的影响。</p>
<h2>其他和Url编码相关的问题</h2>
<p>对于包含中文的Url的处理问题，不同浏览器有不同的表现。例如对于IE，如果你勾选了高级设置“总是以UTF-8发送Url”，那么Url中的路径部分的中文会使用UTF-8进行Url编码之后发送给服务端，而查询参数中的中文部分使用系统默认字符集进行Url编码。为了保证最大互操作性，建议所有放到Url中的组件全部显式指定某个字符集进行Url编码，而不依赖于浏览器的默认实现。</p>
<p>另外，很多HTTP监视工具或者浏览器地址栏等在显示Url的时候会自动将Url进行一次解码（使用UTF-8字符集），这就是为什么当你在Firefox中访问Google搜索中文的时候，地址栏显示的Url包含中文的缘故。但实际上发送给服务端的原始Url还是经过编码的。你可以在地址栏上使用Javascript访问location.href就可以看出来了。在研究Url编解码的时候千万别被这些假象给迷惑了。</p>
<p align="right">——<a href="http://www.imkevinyang.com/"><em><strong>Kevin Yang</strong></em></a></p>

	标签：<a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/rfc%e6%96%87%e6%a1%a3" title="RFC文档" rel="tag">RFC文档</a>, <a href="http://www.imkevinyang.com/tags/urlencode" title="UrlEncode" rel="tag">UrlEncode</a>, <a href="http://www.imkevinyang.com/tags/url%e7%bc%96%e7%a0%81" title="Url编码" rel="tag">Url编码</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%ad%97%e7%ac%a6%e9%9b%86" title="字符集" rel="tag">字符集</a>, <a href="http://www.imkevinyang.com/tags/%e7%bc%96%e8%a7%a3%e7%a0%81" title="编解码" rel="tag">编解码</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/asp-net%e9%a1%b5%e9%9d%a2%e7%9a%84%e7%bc%96%e7%a0%81%e9%97%ae%e9%a2%98.html" title="Asp.Net页面的编码问题 (2009/11/27)">Asp.Net页面的编码问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/excel%e4%b8%ad%e4%bd%bf%e7%94%a8vba%e8%87%aa%e5%ae%9a%e4%b9%89%e5%87%bd%e6%95%b0%e5%af%b9%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%bb%a7%e7%bb%adurl%e7%bc%96%e7%a0%81.html" title="Excel中使用VBA自定义函数对字符串进行Url编码（UTF-8） (2009/04/28)">Excel中使用VBA自定义函数对字符串进行Url编码（UTF-8）</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html" title="Javascript 中的false,零值,null,undefined和空字符串对象 (2009/07/07)">Javascript 中的false,零值,null,undefined和空字符串对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/08/%e8%af%a6%e8%a7%a3javascript%e4%b8%ad%e7%9a%84url%e7%bc%96%e8%a7%a3%e7%a0%81.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Javascript 中的false,零值,null,undefined和空字符串对象</title>
		<link>http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html</link>
		<comments>http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html#comments</comments>
		<pubDate>Tue, 07 Jul 2009 12:08:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[技术随笔]]></category>
		<category><![CDATA[false]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[null]]></category>
		<category><![CDATA[undefined]]></category>
		<category><![CDATA[假值]]></category>
		<category><![CDATA[空值]]></category>
		<category><![CDATA[空字符串]]></category>
		<category><![CDATA[零值]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e3%80%810%e3%80%81null%e3%80%81undefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html</guid>
		<description><![CDATA[<p>在Javascript中，我们经常会接触到题目中提到的这5个比较特别的对象--false、0、空字符串、null和undefined。这几个对象很容易用错，因此在使用时必须得小心。</p>
类型检测
<p>我们下来看看他们的类型分别是什么：</p>
<pre class="csharpcode">
<span class="kwrd">&#60;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&#62;</span>
    ale&#8230;</pre>]]></description>
			<content:encoded><![CDATA[<p>在Javascript中，我们经常会接触到题目中提到的这5个比较特别的对象--false、0、空字符串、null和undefined。这几个对象很容易用错，因此在使用时必须得小心。</p>
<h2>类型检测</h2>
<p>我们下来看看他们的类型分别是什么：</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    alert(<span class="kwrd">typeof</span>(<span class="kwrd">false</span>) === <span class="str">'boolean'</span>);
    alert(<span class="kwrd">typeof</span>(0) === <span class="str">'number'</span>);
    alert(<span class="kwrd">typeof</span>(<span class="str">""</span>) === <span class="str">'string'</span>);
    alert(<span class="kwrd">typeof</span>(<span class="kwrd">null</span>) === <span class="str">'object'</span>);
    alert(<span class="kwrd">typeof</span> undefined === <span class="str">'undefined'</span>);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<p>运行上述代码，弹出的对话框应该显示的都是true。也就是说，false是布尔类型对象，0是数字类型对象，空字符串是字符串类型对象，null是object对象，undefined类型还是undefined。</p>
<h2>互等性</h2>
<p>当你用==操作符将false对象和其他对象进行比较的时候，你会发现， <strong><span style="COLOR: #008000">只有0和空字符串等于false；undefined和null对象并不等于false对象，而null和undefined是相等的</span></strong></p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span><span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    alert(<span class="kwrd">false</span> == undefined);
    alert(<span class="kwrd">false</span> == <span class="kwrd">null</span>);
    alert(<span class="kwrd">false</span> == 0);
    alert(<span class="kwrd">false</span> == <span class="str">""</span>);
    alert(<span class="kwrd">null</span> == undefined);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<p>我们可以把0、空字符串和false归为一类，称为"假值"；把null和undefined归为一类，称为"空值"。假值还算一个有效的对象，因此可以对其使用toString等类型相关的方法，而空值则不行。下面的代码将会抛出异常：</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span><span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    alert(<span class="kwrd">false</span>.toString());    <span class="rem">// "false"</span>
    alert(<span class="str">""</span>.charAt(0));        <span class="rem">// ""</span>
    alert((0).toExponential(10));  <span class="rem">// 0.0000000e+0</span>
    alert(undefined.toString());    <span class="rem">// throw exception "undefined has no properties"</span>
    alert(<span class="kwrd">null</span>.toString());             <span class="rem">// "null has no properties"</span>
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<h2>字符串表示</h2>
<p>虽然空值不能调用toString方法，但是却可以使用String构造函数进行构造。 <strong><span style="COLOR: #008000">像decodeURI这样的函数，如果传入的是undefined或者null，返回的是"undefined"和"null"字符串</span></strong> 。这点很容易用错。</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span> <span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    alert(String(<span class="kwrd">false</span>));    <span class="rem">// "false"</span>
    alert(String(<span class="str">""</span>));        <span class="rem">// ""</span>
    alert(String(0));  <span class="rem">// 0.0000000e+0</span>
    alert(String(undefined));    <span class="rem">// "undefined"</span>
    alert(String(<span class="kwrd">null</span>));             <span class="rem">// "null"</span>

    alert(decodeURI(undefined));<span class="rem">// "undefined"</span>
    alert(decodeURI(<span class="kwrd">null</span>));<span class="rem">// "null"</span>
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<h2>假值和空值作为if条件分支</h2>
<p>假值和空值有一个共性，那就是在 <strong><span style="COLOR: #008000"><strong><span style="COLOR: #008000">作为if的条件分支时，均被视为false</span></strong> ；应用"!"操作之后得到的均为true</span></strong> 。如下示例代码：</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span><span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> ar = [undefined,<span class="kwrd">false</span>,0,<span class="str">""</span>,<span class="kwrd">null</span>];
    <span class="kwrd">for</span>(<span class="kwrd">var</span> i = 0,len = ar.length; i &lt; len; i++){
        <span class="kwrd">if</span>(ar[i]){
            alert(<span class="str">"你不应该看到此对话框!"</span>);
        }
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<p>这是因为，这几个对象均被视为各自类型中的无效值或空值。因此if分支中这些对象均被视为false对待。</p>
<h2>null和undefined的区别</h2>
<p>这两个空值的区别也是容易混淆的。</p>
<p><strong><span style="COLOR: #008000">undefined和null对象无非是两个特殊对象，undefined表示无效对象，null表示空对象。如果变量显式或者隐式（由Javascript引擎进行赋值）地被赋予了undefined，那么代表了此变量未被定义，如果被赋予null值，则代表此变量被初始化为空值。</span></strong></p>
<p>在Javascript中，变量是通过var声明，=赋值符进行定义（初始化变量所指向的对象）。当然，如果声明一个全局变量（作为window属性）可以不使用var关键字。变量可以在声明的同时进行定义。</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span><span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> undefinedVariable,nullVariable = <span class="kwrd">null</span>;
    alert(undefinedVariable); <span class="rem">// "undefined"</span>
    alert(window.undefinedVariable);        <span class="rem">// "undefined"</span>
    alert(window.abcd);        <span class="rem">// "undefined"</span>
    alert(nullVariable);          <span class="rem">// "null"</span>
    alert(abcd);                    <span class="rem">// throw exception "abcd is not defined"</span>
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<p>其实， <strong><span style="COLOR: #008000">变量如果声明了但是没有初始化，那么Javascript引擎会将此变量自动指向undefined对象。</span></strong></p>
<p>这里需要注意，我们在上面引用window.abcd时，弹出的是undefined；而直接引用abcd变量时，却抛出了一个异常。这是由于Javascript引擎对于没有显式指定对象链的变量，会尝试从最近的作用域开始查找变量，查找失败，则退到父级作用链进行查找。如果均查找失败，则抛出"变量未定义"的异常。</p>
<p>这两个值在进行数字运算的时候也有不同。</p>
<pre class="csharpcode">
<span class="kwrd">&lt;</span><span class="html">script</span><span class="attr">type</span><span class="kwrd">="text/javascript"</span><span class="kwrd">&gt;</span>
    alert(1+undefined);    <span class="rem">// "NaN"</span>
    alert(1+<span class="kwrd">null</span>);             <span class="rem">// "1"</span>
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
</pre>
<p>从null和undefined的意义上来说，这是很好理解的。</p>

	标签：<a href="http://www.imkevinyang.com/tags/false" title="false" rel="tag">false</a>, <a href="http://www.imkevinyang.com/tags/javascript" title="Javascript" rel="tag">Javascript</a>, <a href="http://www.imkevinyang.com/tags/null" title="null" rel="tag">null</a>, <a href="http://www.imkevinyang.com/tags/undefined" title="undefined" rel="tag">undefined</a>, <a href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af" title="Web传统技术" rel="tag">Web传统技术</a>, <a href="http://www.imkevinyang.com/tags/%e5%81%87%e5%80%bc" title="假值" rel="tag">假值</a>, <a href="http://www.imkevinyang.com/categories/techarticles" title="技术随笔" rel="tag">技术随笔</a>, <a href="http://www.imkevinyang.com/tags/%e7%a9%ba%e5%80%bc" title="空值" rel="tag">空值</a>, <a href="http://www.imkevinyang.com/tags/%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2" title="空字符串" rel="tag">空字符串</a>, <a href="http://www.imkevinyang.com/tags/%e9%9b%b6%e5%80%bc" title="零值" rel="tag">零值</a><br />

	<h4 style="background-color:#3B3B3B;border-bottom:2px groove gray;color:#F2F2F2;margin-top:20px;padding:6px 6px 6px 15px;margin:20px 0px 0px 0px">你可能对下面的文章感兴趣</h4>
	<ul class="st-related-posts">
	<li><a href="http://www.imkevinyang.com/2009/11/button%e6%a0%87%e7%ad%be%e9%bc%a0%e6%a0%87%e7%82%b9%e5%87%bb%e4%ba%8b%e4%bb%b6%e7%9a%84%e8%a7%a6%e5%8f%91%e6%ba%90%e9%97%ae%e9%a2%98.html" title="Button标签鼠标点击事件的触发源问题 (2009/11/27)">Button标签鼠标点击事件的触发源问题</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/01/document-referrer%e4%b8%a2%e5%a4%b1%e7%9a%84%e5%87%a0%e4%b8%aa%e5%8e%9f%e5%9b%a0.html" title="Document.Referrer丢失的几个原因 (2010/01/18)">Document.Referrer丢失的几个原因</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/03/ie%e4%b8%ad%e4%bd%bf%e7%94%a8windowopen%e6%89%93%e5%bc%80%e6%96%b0%e7%aa%97%e5%8f%a3%e6%97%b6%e6%97%a0%e6%b3%95%e8%8e%b7%e5%8f%96referrer%e5%af%b9%e8%b1%a1.html" title="IE中使用window.open打开新窗口时无法获取Referrer对象 (2009/03/07)">IE中使用window.open打开新窗口时无法获取Referrer对象</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/javajs%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e5%8c%b9%e9%85%8d%e5%b5%8c%e5%a5%97html%e6%a0%87%e7%ad%be.html" title="Java/Js如何使用正则表达式匹配嵌套Html标签 (2010/07/30)">Java/Js如何使用正则表达式匹配嵌套Html标签</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/05/javascript%e4%b8%ad%e8%8e%b7%e5%8f%96%e5%87%ba%e9%94%99%e4%bb%a3%e7%a0%81%e6%89%80%e5%9c%a8%e6%96%87%e4%bb%b6%e5%8f%8a%e8%a1%8c%e6%95%b0.html" title="Javascript中获取出错代码所在文件及行数 (2009/05/18)">Javascript中获取出错代码所在文件及行数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/04/javascript%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%93%88%e5%b8%8c%e5%87%bd%e6%95%b0.html" title="Javascript字符串哈希函数 (2009/04/11)">Javascript字符串哈希函数</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html" title="Javascript操纵Cookie (2009/06/11)">Javascript操纵Cookie</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/05/%e4%b8%ba%e4%bb%80%e4%b9%88iis77-5%e7%9a%84gzip%e4%b8%8d%e8%b5%b7%e4%bd%9c%e7%94%a8.html" title="为什么IIS7/7.5的Gzip不起作用 (2010/05/08)">为什么IIS7/7.5的Gzip不起作用</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/09/%e4%bd%bf%e7%94%a8%e7%9b%b8%e5%af%b9url%e6%97%a0%e7%bc%9d%e5%88%87%e6%8d%a2http-https.html" title="使用相对Url无缝切换HTTP-HTTPS (2009/09/18)">使用相对Url无缝切换HTTP-HTTPS</a> </li>
	<li><a href="http://www.imkevinyang.com/2010/07/%e5%87%a0%e4%b8%aa%e6%9c%89%e8%b6%a3%e7%9a%84javascript-hack.html" title="几个有趣的Javascript Hack (2010/07/23)">几个有趣的Javascript Hack</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/07/javascript-%e4%b8%ad%e7%9a%84false%e9%9b%b6%e5%80%bcnullundefined%e5%92%8c%e7%a9%ba%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%af%b9%e8%b1%a1.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Page Caching using disk: enhanced

Served from: www.imkevinyang.com @ 2012-02-08 17:57:59 -->
