<?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; Web传统技术</title>
	<atom:link href="http://www.imkevinyang.com/categories/techarticles/web%e4%bc%a0%e7%bb%9f%e6%8a%80%e6%9c%af/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>几个有趣的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>当前日期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>文档字符集导致的脚本错误</title>
		<link>http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html</link>
		<comments>http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html#comments</comments>
		<pubDate>Tue, 18 Aug 2009 18:01:25 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[charset]]></category>
		<category><![CDATA[字符集]]></category>
		<category><![CDATA[引用外部脚本]]></category>
		<category><![CDATA[文档字符集]]></category>
		<category><![CDATA[编解码]]></category>
		<category><![CDATA[脚本]]></category>
		<category><![CDATA[脚本异常]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html</guid>
		<description><![CDATA[<p>Html页面中可以通过meta标签指定页面文档使用的字符集，这样浏览器就会根据此标签使用指定的字符集去解析文档流，而不用靠“猜”了。</p>
<pre class="csharpcode"><span class="kwrd">&#60;</span><span class="html">meta</span> <span class="attr">http-equiv</span><span class="kwrd">=&#34;Content-Type&#34;</span> <span class="attr">content</span><span class="kwrd">=&#34;text/html; charset=utf-8&#038;quo&#8230;</span></pre>]]></description>
			<content:encoded><![CDATA[<p>Html页面中可以通过meta标签指定页面文档使用的字符集，这样浏览器就会根据此标签使用指定的字符集去解析文档流，而不用靠“猜”了。</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=utf-8&quot;</span> <span class="kwrd">/&gt;</span></pre>
<p>文档字符集需要对应文件实际存储使用的字符集，否则会引发很多意料不到而又难以调试的Bug。</p>
<h2>问题1——页面显示乱码</h2>
<p>如果文档中指定的字符集和文件实际存储的字符集不一致，那么就会造成页面的非ASCII字符显示为乱码。如下面的HTML页面（文件的实际存储格式为UTF-8）：</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">div</span><span class="kwrd">&gt;</span>中文<span class="kwrd">&lt;/</span><span class="html">div</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>“中文”会变成“涓枃”。</p>
<h2>问题2——脚本执行结果不正确</h2>
<p>问题1实际上还是比较容易发现的，因为一看到乱码就可以猜到和字符集相关了。但是如果假设你在上面这个页面的基础上写了如下Javascript代码：</p>
<pre class="csharpcode"><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>
    location.href = <span class="str">&quot;http://www.example.com/search?q=&quot;</span> + encodeURI(<span class="str">&quot;中文&quot;</span>);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>你期望将用户重定向到一个特定的页面，你直接在页面中使用了Unicode字符串，并期望encodeURI会使用UTF-8对其进行Url编码。但是实际上你获得的Url却是：</p>
<p>http://www.example.com/search?q=%E6%B6%93%EE%85%9F%E6%9E%83</p>
<p>后台在解析这个Url参数的时候无论使用何种字符集进行Url解码，都无法得到“中文”这个字符串。原因和文章开头提到的乱码问题实际上是同一个问题。<strong><font color="#008000">如果你的文档字符集和页面存储字符集不一致，那么你在使用非ASCII码字符作字面量（就是直接写在代码里面的字符串）的时候就会出现意料不到的各种问题</font></strong>。</p>
<h2>问题3——脚本抛出异常</h2>
<p>在问题2举的例子中，脚本执行的时候没有抛出异常，但是其执行的结果却不是我们所期望的。在下面这个例子中，脚本的执行过程甚至会抛出莫名其妙的异常。</p>
<pre class="csharpcode"><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>
    alert(<span class="str">&quot;对象初始化&quot;</span>);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p><img style="border-right-width: 0px; margin: 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/08/image_thumb9.png" width="565" height="93" /></p>
<p>如果你真到第8行去看那段脚本，你会发现，你死活就是看不出问题来，直到你把中文替换成英文之后你才可能会恍然大悟。</p>
<h2>问题4——引用外部脚本导致的异常</h2>
<p>现在我们把页面存储成gb2312，再运行问题3中的示例代码，这个时候就没有问题了。为了Html页面的纯洁性，我们将脚本移到一个独立的Js文件中去，并在Html中引用这个脚本文件。如下：</p>
<pre class="csharpcode">

页面index.html
<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="attr">src</span><span class="kwrd">=&quot;script/test.js&quot;</span><span class="kwrd">&gt;&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>

脚本script/test.js
alert(&quot;对象初始化&quot;);

&#160;
</pre>
<p>这个时候再查看index.html页面的时候，我们发现，脚本又抛出问题3的异常来了。这是为什么呢？</p>
<p>这是因为，当Html页面在引用一个外部资源的时候，使用的字符集就是当前文档字符集。因此test.js文件会被浏览器使用gb2312字符集去解析，而我在Aptana中建此文件的时候，默认的文件存储格式就是utf-8，因此还是回归到了文档字符集和存储字符集不一致的问题上来。</p>
<p>这个问题，我们可以通过在引用外部资源的时候显式指定charset属性来解决。</p>
<pre class="csharpcode"><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="attr">src</span><span class="kwrd">=&quot;script/test.js&quot;</span> <span class="attr">charset</span><span class="kwrd">=&quot;utf-8&quot;</span><span class="kwrd">&gt;&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>&#160;</p>
<p><font color="#ff0000"><em><strong>update:</strong></em></font></p>
<p>以上试验提到的UTF-8均指UTF-8 without BOM，即不带标记的UTF-8。IE、Chrome、Opera和Safari均能支持BOM标记，这就意味着，如果你的文件本身是以UTF-8 with BOM编码的，那么无需指定charset，浏览器也能正确解析。此优先级最高。Firefox则无法正确识别BOM标记，因此总会以页面中指定的charset或者HTTP响应中的charset来解析文档。</p>
<p align="right">&#160;</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/charset" title="charset" rel="tag">charset</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/%e5%bc%95%e7%94%a8%e5%a4%96%e9%83%a8%e8%84%9a%e6%9c%ac" title="引用外部脚本" rel="tag">引用外部脚本</a>, <a href="http://www.imkevinyang.com/tags/%e6%96%87%e6%a1%a3%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>, <a href="http://www.imkevinyang.com/tags/%e8%84%9a%e6%9c%ac" title="脚本" rel="tag">脚本</a>, <a href="http://www.imkevinyang.com/tags/%e8%84%9a%e6%9c%ac%e5%bc%82%e5%b8%b8" 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/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/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/2010/06/%e5%85%b3%e4%ba%8e%e5%ad%97%e7%ac%a6%e7%bc%96%e7%a0%81%ef%bc%8c%e4%bd%a0%e6%89%80%e9%9c%80%e8%a6%81%e7%9f%a5%e9%81%93%e7%9a%84.html" title="关于字符编码，你所需要知道的（ASCII,Unicode,Utf-8,GB2312&#8230;） (2010/06/18)">关于字符编码，你所需要知道的（ASCII,Unicode,Utf-8,GB2312&#8230;）</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/02/%e5%ad%97%e7%ac%a6%e7%bc%96%e8%a7%a3%e7%a0%81%e7%9a%84%e6%95%85%e4%ba%8b%ef%bc%88ascii%ef%bc%8cansi%ef%bc%8cunicode%ef%bc%8cutf-8%e5%8c%ba%e5%88%ab%ef%bc%89.html" title="字符编解码的故事（ASCII，ANSI，Unicode，Utf-8区别） (2009/02/28)">字符编解码的故事（ASCII，ANSI，Unicode，Utf-8区别）</a> </li>
	<li><a href="http://www.imkevinyang.com/2009/11/%e5%ad%97%e7%ac%a6%ef%bc%8c%e5%ad%97%e8%8a%82%e5%92%8c%e7%bc%96%e7%a0%81.html" title="字符，字节和编码 (2009/11/27)">字符，字节和编码</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>
	<li><a href="http://www.imkevinyang.com/2009/09/%e8%a7%a3%e5%86%b3xaml%e4%b8%ad%e5%8c%85%e5%90%ab%e4%b8%ad%e6%96%87%e5%af%bc%e8%87%b4%e6%97%a0%e6%b3%95%e7%bc%96%e8%af%91%e7%9a%84%e9%97%ae%e9%a2%98.html" title="解决Xaml中包含中文导致无法编译的问题 (2009/09/29)">解决Xaml中包含中文导致无法编译的问题</a> </li>
	<li><a href="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" title="详解Javascript中的Url编码/解码 (2009/08/19)">详解Javascript中的Url编码/解码</a> </li>
</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.imkevinyang.com/2009/08/%e6%96%87%e6%a1%a3%e5%ad%97%e7%ac%a6%e9%9b%86%e5%af%bc%e8%87%b4%e7%9a%84%e8%84%9a%e6%9c%ac%e9%94%99%e8%af%af.html/feed</wfw:commentRss>
		<slash:comments>1</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>
		<item>
		<title>详解Javascript 中的this指针</title>
		<link>http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html</link>
		<comments>http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html#comments</comments>
		<pubDate>Sun, 05 Jul 2009 11:31:05 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[技术随笔]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Javascript高级特性]]></category>
		<category><![CDATA[this指针]]></category>
		<category><![CDATA[函数对象传参]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/07/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html</guid>
		<description><![CDATA[前言
<p>Javascript是一门基于对象的动态语言，也就是说，所有东西都是对象，一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程，其中this “指针”就是实现面向对象的一个很重要的特性。但是this也是Javascript中一个非常容易理解错，&#8230;</p>]]></description>
			<content:encoded><![CDATA[<h2>前言</h2>
<p>Javascript是一门基于对象的动态语言，也就是说，所有东西都是对象，一个很典型的例子就是函数也被视为普通的对象。Javascript可以通过一定的设计模式来实现面向对象的编程，其中this “指针”就是实现面向对象的一个很重要的特性。但是this也是Javascript中一个非常容易理解错，进而用错的特性。特别是对于接触静态语言比较久了的同志来说更是如此。</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">=&quot;text/javascript&quot;</span><span class="kwrd">&gt;</span>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + name);
    }
    sayHi();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码很简单，我们定义了一个全局字符串对象name和函数对象sayHi。运行会弹出一个打招呼的对话框，“你好，我的名字叫Kevin Yang”。</p>
<p>我们把这段代码稍微改一改：</p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    sayHi();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码和上段代码的区别就在于sayHi函数在使用name的时候加上了this.前缀。运行结果和上面一摸一样。这说明this.name引用的也还是全局的name对象。</p>
<p>开头我们不是说了，函数也是普通的对象，可以将其当作一个普通变量使用。我们再把上面的代码改一改：</p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">var</span> person = {};
    person.sayHello = sayHi;
    person.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这一次，我们又创建了一个全局对象person，并将sayHi函数对象赋给person对象的sayHello属性。运行结果如下：</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/07/image-thumb.png" width="243" height="148" /> </p>
<p>这一次打招呼的内容就有点无厘头了，我们发现this.name已经变成undefined了。这说明，在sayHello函数内部执行时已经找不着this.name对象了。如果我们重新定义person对象，在其上面加上一个name属性又会怎么样呢？</p>
<pre class="csharpcode"><span class="kwrd">var</span> person = {name:<span class="str">&quot;Marry&quot;</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/07/image-thumb1.png" width="216" height="160" /> </p>
<p>是不是看出点道道了呢？</p>
<h2>判别this指针的指导性原则</h2>
<blockquote>
<p><strong>在Javascript里面，this指针代表的是执行当前代码的对象的<font color="#008000">所有者</font>。</strong></p>
</blockquote>
<p>在上面的示例中我们可以看到，第一次，我们定义了一个全局函数对象sayHi并执行了这个函数，函数内部使用了this关键字，那么执行this这行代码的对象是sayHi（一切皆对象的体现），sayHi是被定义在全局作用域中，因此sayHi的所有权是window对象的。其实在Javascript中所谓的全局对象，无非是定义在window这个根对象下的一个属性而已。也就是说，在全局作用域下，你可以通过直接使用name去引用这个对象，你也可以通过window.name去引用同一个对象。因而<strong><font color="#008000">this.name就可以翻译为window.name</font></strong>了。</p>
<p>再来看第二个this的示例。我们定义了一个person的对象，并定义了它的sayHello属性，使其指向sayHi全局对象。那么这个时候，当我们运行person.sayHello的时候，this所在的代码所属对象就是sayHello了（其实准确来说，sayHi和sayHello是只不过类似两个指针，指向的对象实际上是同一个），而sayHello对象的所有者就是person了。第一次，person里面没有name属性，因此弹出的对话框就是this.name引用的就是undefined对象（<font color="#008000"><strong>Javascript中所有只声明而没有定义的变量全都指向undefined对象</strong></font>）；而第二次我们在定义person的时候加了name属性了，那么this.name指向的自然就是我们定义的字符串了。</p>
<p>理解了上面所说的之后，我们将上面最后一段示例改造成面向对象式的代码。</p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">function</span> Person(name){
        <span class="kwrd">this</span>.name = name;
    }
    Person.prototype.sayHello = sayHi;
    <span class="kwrd">var</span> marry = <span class="kwrd">new</span> Person(<span class="str">&quot;Marry&quot;</span>);
    marry.sayHello();
    <span class="kwrd">var</span> kevin = <span class="kwrd">new</span> Person(<span class="str">&quot;Kevin&quot;</span>);
    kevin.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>在上面这段代码中，我们定义了一个Person的“类”（实际上还是一个对象），然后在这个类的原型（<strong><font color="#008000">类原型相当于C++中的静态成员变量的概念</font></strong>）中定义了sayHello属性，使其指向全局的sayHi对象。运行代码我们可以看到，marry和kevin都成功的向我们打了声“招呼”。</p>
<p>在这段代码中有两点需要思考的，一个是new我们很熟悉，但是在这里new到底做了什么操作呢？另外一个是，这里执行sayHello的时候，this指针为什么能够正确的指向marry和kevin对象呢？</p>
<p>我们来把上面定义“类”和实例化类对象的操作重新“翻译”一下：</p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> name = <span class="str">&quot;Kevin Yang&quot;</span>;
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;你好，我的名字叫&quot;</span> + <span class="kwrd">this</span>.name);
    }
    <span class="kwrd">function</span> Person(name){
        <span class="kwrd">var</span> <span class="kwrd">this</span>;
        <span class="kwrd">this</span>.name = name;
        <span class="kwrd">return</span> <span class="kwrd">this</span>;
    }
    Person.prototype.sayHello = sayHi;
    <span class="kwrd">var</span> marry = Person(<span class="str">&quot;Marry&quot;</span>);
    marry.sayHello();
    <span class="kwrd">var</span> kevin = Person(<span class="str">&quot;Kevin&quot;</span>);
    kevin.sayHello();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>当然这段代码并不能正确执行，但是它可以帮助你更好的理解这个过程。</p>
<p>当我们使用new关键字实例化一个“类”对象的时候，Javascript引擎会在这个对象内部定义一个新的对象并将其存入this指针。所有此对象内部用到this的代码实际上都是指向这个新的对象。如this.name = name，实际上是将参数中的name对象赋值给了这个新创建的对象。函数对象执行完之后Javascript引擎会将此对象返回给你，于是就有marry变量得到的对象的name为“Marry”，而kevin变量得到的对象的name属性确实“Kevin”。在这种情况下，this被强制赋给某个变量（类实例）了。</p>
<h2>显式操纵this指针</h2>
<p>在上面的面向对象式编程实例中，我们看到，在使用new操作符的情况下，看起来this的指向和我们前一节中讲到的指导原则并不相符。this指针并没有指向marry或者kevin的所有者，而是指向marry和kevin变量本身。</p>
<p>实际上，如果你理解什么是指针的话，那么你就会知道，既然是指针，那么当然可以改变其指向的对象。只不过Javascript引擎不允许我们自己写代码来做这样的事情，也就是说，在Javascript中，你不可以直接写this = someObj这样的代码。Javascript引擎通过以下两种方式允许我们显式指定this指针指代的对象：</p>
<p>1. 通过new操作符，Javascript引擎会将this指针返回给被赋值的变量A（对应上面的例子就是marry和kevin变量），这个时候A和this指针引用的就是同一个对象了，即A == this。过程参见上面的伪代码。</p>
<p>2. 通过Function.apply或者Function.call的原型方法，我们可以将this指针指代的对象以参数的形式传入，这个时候，函数内部使用的this指针就是传入的参数。</p>
<p>注意，对于这种显式指定this指针的情况，上一节提到的指导原则不再适用。</p>
<h2>容易误用的情况</h2>
<p>理解了this指针后，我们再来看看一些很容易误用this指针的情况。</p>
<p><strong>示例1——内联式绑定Dom元素的事件处理函数</strong></p>
<pre class="csharpcode"><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>
    <span class="kwrd">function</span> sayHi(){
       alert(<span class="str">&quot;当前点击的元素是&quot;</span> + <span class="kwrd">this</span>.tagName);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">=&quot;btnTest&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;button&quot;</span> <span class="attr">value</span><span class="kwrd">=&quot;点击我&quot;</span> <span class="attr">onclick</span><span class="kwrd">=&quot;sayHi()&quot;</span><span class="kwrd">&gt;</span></pre>
<p>在此例代码中，我们绑定了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/07/image-thumb2.png" width="201" height="129" /> </p>
<p>也就是this指针并不是指向input元素。这是因为当使用内联式绑定Dom元素的事件处理函数时，实际上相当于执行了以下代码：</p>
<pre class="csharpcode"><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.getElementById(<span class="str">&quot;btnTest&quot;</span>).onclick = <span class="kwrd">function</span>(){
        sayHi();
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>在这种情况下<font color="#008000"><strong>sayHi函数对象的所有权并没有发生转移，还是属于window所有。</strong></font>用上面的指导原则一套我们就很好理解为什么this.tagName是undefined了。</p>
<p>那么如果我们要引用元素本身怎么办呢？</p>
<p>我们知道，onclick函数是属于btnTest元素的，那么在此函数内部，this指针正是指向此Dom对象，于是我们只需要把this作为参数传入sayHi即可。</p>
<pre class="csharpcode"><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>
    <span class="kwrd">function</span> sayHi(el){
       alert(<span class="str">&quot;当前点击的元素是&quot;</span> + el.tagName);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span>
<span class="kwrd">&lt;</span><span class="html">input</span> <span class="attr">id</span><span class="kwrd">=&quot;btnTest&quot;</span> <span class="attr">type</span><span class="kwrd">=&quot;button&quot;</span> <span class="attr">value</span><span class="kwrd">=&quot;点击我&quot;</span> <span class="attr">onclick</span><span class="kwrd">=&quot;sayHi(this)&quot;</span><span class="kwrd">&gt;</span></pre>
<p>等价代码如下：</p>
<pre class="csharpcode"><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.getElementById(<span class="str">&quot;btnTest&quot;</span>).onclick = <span class="kwrd">function</span>(){
        sayHi(<span class="kwrd">this</span>);
    }
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p><strong>示例2——临时变量导致的this指针丢失</strong></p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> Utility = {
        decode:<span class="kwrd">function</span>(str){
            <span class="kwrd">return</span> unescape(str);
        },
        getCookie:<span class="kwrd">function</span>(key){
            <span class="rem">// ... 省略提取cookie字符串的代码</span>
            <span class="kwrd">var</span> value = <span class="str">&quot;i%27m%20a%20cookie&quot;</span>;
            <span class="kwrd">return</span> <span class="kwrd">this</span>.decode(value);
        }
    };
    alert(Utility.getCookie(<span class="str">&quot;identity&quot;</span>))
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>我们在写稍微有点规模的Js库的时候，一般都会自己封装一个Utility的类，然后将一些常用的函数作为Utility类的属性，如客户端经常会用到的getCookie函数和解码函数。如果每个函数都是彼此独立的，那么还好办，问题是，函数之间有时候会相互引用。例如上面的getCookie函数，会对从document.cookie中提取到的字符串进行decode之后再返回。如果我们通过Utility.getCookie去调用的话，那么没有问题，我们知道，getCookie内部的this指针指向的还是Utility对象，而Utility对象时包含decode属性的。代码可以成功执行。</p>
<p>但是有个人不小心这样使用Utility对象呢？</p>
<pre class="csharpcode"><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>
    <span class="kwrd">function</span> showUserIdentity(){
        <span class="rem">// 保存getCookie函数到一个局部变量，因为下面会经常用到</span>
        <span class="kwrd">var</span> getCookie = Utility.getCookie;
        alert(getCookie(<span class="str">&quot;identity&quot;</span>));
    }
    showUserIdentity();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这个时候运行代码会抛出异常“this.decode is not a function”。运用上面我们讲到的指导原则，很好理解，因为此时Utility.getCookie对象被赋给了临时变量getCookie，而临时变量是属于window对象的——只不过外界不能直接引用，只对Javascript引擎可见——于是在getCookie函数内部的this指针指向的就是window对象了，而window对象没有定义一个decode的函数对象，因此就会抛出这样的异常来。</p>
<p>这个问题是由于引入了临时变量导致的this指针的转移。解决此问题的办法有几个：</p>
<ul>
<li>不引入临时变量，每次使用均使用Utility.getCookie进行调用 </li>
<li>getCookie函数内部使用Utility.decode显式引用decode对象而不通过this指针隐式引用（如果Utility是一个实例化的对象，也即是通过new生成的，那么此法不可用） </li>
<li>使用Funtion.apply或者Function.call函数指定this指针 </li>
</ul>
<p>前面两种都比较好理解，第三种需要提一下。正是因为this指针的指向很容易被转移丢失，因此Javascript提供了两个类似的函数apply和call来允许函数在调用时重新显式的指定this指针。</p>
<p>修正代码如下：</p>
<pre class="csharpcode"><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>
    <span class="kwrd">function</span> showUserIdentity(){
        <span class="rem">// 保存getCookie函数到一个局部变量，因为下面会经常用到</span>
        <span class="kwrd">var</span> getCookie = Utility.getCookie;
        alert(getCookie.call(Utility,<span class="str">&quot;identity&quot;</span>));
        alert(getCookie.apply(Utility,[<span class="str">&quot;identity&quot;</span>]));
    }
    showUserIdentity();
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>call和apply只有语法上的差异，没有功能上的差别。</p>
<p><strong>示例3——函数传参时导致的this指针丢失</strong></p>
<p>我们先来看一段问题代码：</p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    setTimeout(person.sayHi,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>这段代码期望在访客进入页面5秒钟之后向访客打声招呼。setTimeout函数接收一个函数作为参数，并在指定的触发时刻执行这个函数。可是，当我们等了5秒钟之后，弹出的对话框显示的this.name却是undefined。</p>
<p>其实这个问题和上一个示例中的问题是类似的，都是因为临时变量而导致的问题。当我们执行函数的时候，如果函数带有参数，那么这个时候Javascript引擎会创建一个临时变量，并将传入的参数<strong><font color="#008000">复制（注意，Javascript里面都是值传递的，没有引用传递的概念）</font></strong>给此临时变量。也就是说，整个过程就跟上面我们定义了一个getCookie的临时变量，再将Utility.getCookie赋值给这个临时变量一样。只不过在这个示例中，容易忽视临时变量导致的bug。</p>
<h2>函数对象传参</h2>
<p>对于函数作为参数传递导致的this指针丢失的问题，目前很多框架都已经有方法解决了。</p>
<p><strong>Prototype的解决方案——传参之前使用bind方法将函数封装起来，并返回封装后的对象</strong></p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    <span class="kwrd">var</span> boundFunc = person.sayHi.bind(person);
    setTimeout(boundFunc,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>bind方法的实现其实是用到了Javascript又一个高级特性——闭包。我们来看一下源代码：</p>
<pre class="csharpcode"><span class="kwrd">function</span> bind(){
    <span class="kwrd">if</span> (arguments.length &lt; 2 &amp;&amp; arguments[0] === undefined)
        <span class="kwrd">return</span> <span class="kwrd">this</span>;
    <span class="kwrd">var</span> __method = <span class="kwrd">this</span>, args = $A(arguments), <span class="kwrd">object</span> = args.shift();
    <span class="kwrd">return</span> <span class="kwrd">function</span>(){
        <span class="kwrd">return</span> __method.apply(<span class="kwrd">object</span>, args.concat($A(arguments)));
    }
}</pre>
<style type="text/css">
<p>.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }</style>
<p>首先将this指针存入函数内部临时变量，然后在返回的函数对象中引用此临时变量从而形成闭包。</p>
<p><strong>微软的Ajax库提供的方案——构建委托对象</strong></p>
<pre class="csharpcode"><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>
    <span class="kwrd">var</span> person = {
        name:<span class="str">&quot;Kevin Yang&quot;</span>,
        sayHi:<span class="kwrd">function</span>(){
            alert(<span class="str">&quot;你好，我是&quot;</span>+<span class="kwrd">this</span>.name);
        }
    }
    <span class="kwrd">var</span> boundFunc = Function.createDelegate(person,person.sayHi);
    setTimeout(boundFunc,5000);
<span class="kwrd">&lt;/</span><span class="html">script</span><span class="kwrd">&gt;</span></pre>
<p>其实本质上和prototype的方式是一样的。 </p>
<p>著名的Extjs库的解决方案采用的手法和微软是一样的。</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/javascript%e9%ab%98%e7%ba%a7%e7%89%b9%e6%80%a7" title="Javascript高级特性" rel="tag">Javascript高级特性</a>, <a href="http://www.imkevinyang.com/tags/this%e6%8c%87%e9%92%88" title="this指针" rel="tag">this指针</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%87%bd%e6%95%b0%e5%af%b9%e8%b1%a1%e4%bc%a0%e5%8f%82" title="函数对象传参" rel="tag">函数对象传参</a>, <a href="http://www.imkevinyang.com/categories/techarticles" 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/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/%e8%af%a6%e8%a7%a3javascript-%e4%b8%ad%e7%9a%84this%e6%8c%87%e9%92%88.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Javascript操纵Cookie</title>
		<link>http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html</link>
		<comments>http://www.imkevinyang.com/2009/06/javascript%e6%93%8d%e7%ba%b5cookie.html#comments</comments>
		<pubDate>Thu, 11 Jun 2009 15:18:00 +0000</pubDate>
		<dc:creator>Kevin Yang</dc:creator>
				<category><![CDATA[Web传统技术]]></category>
		<category><![CDATA[代码库]]></category>
		<category><![CDATA[技术随笔]]></category>
		<category><![CDATA[Cookie]]></category>
		<category><![CDATA[Cookie三要素]]></category>
		<category><![CDATA[Cookie常识]]></category>
		<category><![CDATA[Javascript]]></category>

		<guid isPermaLink="false">http://www.imkevinyang.com/2009/05/javascript%e6%93%8d%e7%ba%b5cookie.html</guid>
		<description><![CDATA[<p>在讲如何使用Javascript操纵Cookie时，我们先来了解一下Cookie的基本常识。</p>
<p>Cookie，又称Http Cookie，是存储在客户端本地的一小段信息。我们可以简单地把Cookie理解为客户端浏览器上的一个小硬盘，我们会在上面存取一些信息，通常用作Http状态的维护，现在也经常被用作跟踪&#8230;</p>]]></description>
			<content:encoded><![CDATA[<p>在讲如何使用Javascript操纵Cookie时，我们先来了解一下Cookie的基本常识。</p>
<p>Cookie，又称Http Cookie，是存储在客户端本地的一小段信息。我们可以简单地把Cookie理解为客户端浏览器上的一个小硬盘，我们会在上面存取一些信息，通常用作Http状态的维护，现在也经常被用作跟踪用户行为的一种常见方式。</p>
<h2>Cookie的属性</h2>
<p>每一个Cookie都有如下几个属性：</p>
<ul>
<li>名称&#160;&#160;&#160; </li>
<li>值 </li>
<li>主机域 </li>
<li>路径 </li>
<li>安全级别 </li>
<li>过期时间 </li>
</ul>
<p>其中“名称”、“主机域”，“路径”三者一起唯一标识了一个Cookie。    <br />大多数Cookie在设置的时候都只是显式的设置了Cookie的名称和值，这种情况下，浏览器会自动的使用location.host来设置Cookie的主机域，将路径设置到根目录“/”下。例如，当你在www.<font color="#555555">example</font>.com上面使用document.cookie=&quot;name=value&quot;设置了一个Cookie，那么这个Cookie就拥有了如下属性：</p>
<ul>
<li>名称 —— name </li>
<li>值 —— value </li>
<li>主机域 —— www.example.com </li>
<li>路径 —— / </li>
<li>安全级别 —— No </li>
<li>过期时间 —— 浏览器会话结束（关闭浏览器） </li>
</ul>
<h2>第一方和第三方Cookie的区别</h2>
<p>第一方Cookie指的是设置在当前网站域上面的Cookie，而第三方Cookie指的是设置在其他域上的Cookie。</p>
<p>第一方Cookie比较好理解，我们通常遇到的都是属于第一方Cookie。在客户端Javascript中，我们只能操纵第一方Cookie，也就是说，我们不能在www.example.com主机上，设置www.google.cn的Cookie，这样就乱套了。</p>
<p>第三方Cookie不容易让人注意到。假设我们在公司网站www.example.com上面使用了map.google.com的地图服务，而Google地图在使用时又希望在用户这边设置一些Cookie，就跟用户直接访问自家网站（map.google.com）一样，如Session信息等，那么它会在返回的HTTP Response中包含set-cookie的报头，但由于是第三方域，存在安全问题，所以必须还在响应中包含一个P3P的主机头（P3P头中存的是隐私策略的摘要）来实现Cookie的第三方存取（注意，此时Cookie还是设置在b.com上面的）。IE中可以设置对第三方Cookie存取的限制。</p>
<h2>Javascript操纵Cookie</h2>
<p>在客户端使用Javascript操纵Cookie存在很多的不便之处，例如在读取Cookie的时候，只能通过手动解析document.cookie字符串得到指定cookie的值，不能得到其他任何信息，如设置的主机，路径以及过期时间等。</p>
<pre class="csharpcode"><span class="rem">/**</span>
<span class="rem"> * 查询指定名称的Cookie值</span>
<span class="rem"> * @note 需要注意有可能出现同名cookie的问题</span>
<span class="rem"> * @param {Object} key</span>
<span class="rem"> * @param {Object} 设置当读取不到key时返回的默认值</span>
<span class="rem"> * @return {String} 返回读取到的Cookie的值，</span>
<span class="rem"> * 如果读取不到相应的Cookie，则判断defValue是否有效，有效则返回defValue，否则返回null</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> getCookie(key,defValue){
    <span class="kwrd">var</span> cookie,value;
    <span class="kwrd">if</span>(!key){
        <span class="kwrd">return</span> <span class="kwrd">null</span>;
    }

    cookie = document.cookie;
    <span class="rem">// 所有cookie的key都小写化处理</span>
    key = key.toLowerCase();

    value = find(cookie,key+<span class="str">&quot;=&quot;</span>,<span class="str">&quot;;&quot;</span>,<span class="kwrd">null</span>,<span class="kwrd">false</span>,<span class="kwrd">null</span>);
    <span class="kwrd">return</span> value === <span class="kwrd">null</span> ? defValue : unescape(value);
}
<span class="rem">/**</span>
<span class="rem"> * 设置cookie</span>
<span class="rem"> * @param {String} key</span>
<span class="rem"> * @param {String} value</span>
<span class="rem"> * @param {Number} expires 单位为秒</span>
<span class="rem"> * @param {String} path 路径</span>
<span class="rem"> * @param {String} domain 主机</span>
<span class="rem"> * @param {Boolean} secure 安全级别</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> setCookie(key, value, expires, path,domain,secure){
    <span class="rem">// key无效则不做任何操作</span>
    <span class="kwrd">if</span>(!key){
        <span class="kwrd">return</span>;
    }

    <span class="rem">// 所有cookie的key都小写化处理</span>
    key = key.toLowerCase();

    key = key + <span class="str">'='</span> + escape(value) + <span class="str">&quot;;&quot;</span>;
    expires = expires ? (<span class="str">&quot;expires=&quot;</span> + <span class="kwrd">new</span> Date(<span class="kwrd">new</span> Date().getTime() + expires * 1000).toGMTString()) + <span class="str">&quot;;&quot;</span> : <span class="str">&quot;&quot;</span>;
    path = !!path ? <span class="str">&quot;path=&quot;</span> + path + <span class="str">&quot;;&quot;</span> : <span class="str">&quot;path=/;&quot;</span>;
    domain = domain ? (<span class="str">&quot;domain=&quot;</span> + domain) + <span class="str">&quot;;&quot;</span> : <span class="str">&quot;&quot;</span>;
    secure = secure ? <span class="str">&quot;secure=true;&quot;</span> : <span class="str">&quot;&quot;</span>;
    document.cookie =[key,expires,path,domain,secure].join(<span class="str">&quot;&quot;</span>);
}
<span class="rem">/**</span>
<span class="rem"> * 删除指定Cookie</span>
<span class="rem"> * @param {Object} key</span>
<span class="rem"> * @param {Object} path</span>
<span class="rem"> * @param {Object} domain</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> delCookie(key,path,domain){
    <span class="rem">// 超时设置为过去的时间，cookie会立即失效</span>
    key = key.toLowerCase();
    setCookie(key,<span class="str">&quot;&quot;</span>,-1000,path,domain);
}
<span class="rem">/**</span>
<span class="rem"> * 从字符串中获取夹在指定前缀和后缀之间的值</span>
<span class="rem"> * @example</span>
<span class="rem"> * userAgent = &quot;Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-CN; rv:1.9.0.2) Gecko/2008082714 Firefox/3.0.2&quot;</span>
<span class="rem"> * </span>
<span class="rem"> * prefix=&quot;windows nt&quot;</span>
<span class="rem"> * suffix=&quot;;&quot;</span>
<span class="rem"> * find(userAgent,prefix,suffix) returns &quot; 5.2&quot;;</span>
<span class="rem"> * @param {Object} str 源字符串</span>
<span class="rem"> * @param {Object} prefix 前缀</span>
<span class="rem"> * @param {Object} suffix 结束符，若不指定，则匹配到字符串结尾；如果指定了，但是匹配不到，则同样匹配到字符串结尾。</span>
<span class="rem"> * @param {Boolean} matchFirstOnly 是否找到第一个匹配项,设置为false则查找最后一个匹配项,默认为false</span>
<span class="rem"> * @param {Boolean} ignoreCase     忽略大小写来查找,默认值为true</span>
<span class="rem"> * @param {Boolean} trimBlank 是否删除值首尾的空白符,默认值为true</span>
<span class="rem"> * @return {String} 查找到的字符串，若找不到则返回null</span>
<span class="rem"> */</span>
<span class="kwrd">function</span> find(str,prefix,suffix,matchFirstOnly,ignoreCase,trimBlank){
    <span class="kwrd">var</span> start,end,middle,value=<span class="kwrd">null</span>;
    matchFirstOnly = (matchFirstOnly === <span class="kwrd">true</span>);
    ignoreCase = (ignoreCase !== <span class="kwrd">false</span>);
    trimBlank = (trimBlank !== <span class="kwrd">false</span>);
    <span class="rem">// 如果忽略默认值</span>
    <span class="kwrd">if</span>(ignoreCase){
        str = str.toLowerCase();
        prefix = prefix.toLowerCase();
        suffix = suffix &amp;&amp; suffix.toLowerCase();
    }

    <span class="kwrd">if</span>(matchFirstOnly){
        start = str.indexOf(prefix);
    }<span class="kwrd">else</span>{
        start = str.lastIndexOf(prefix);
    }
    <span class="kwrd">if</span> (start &gt; -1) {
        <span class="rem">// 如果没有指定后缀，则直接匹配到字符串结尾</span>
        middle = start + prefix.length;
        <span class="kwrd">if</span> (!suffix) {
            value = str.substring(middle);
        }
        <span class="kwrd">else</span> {
            end = str.indexOf(suffix, middle);
            <span class="kwrd">if</span> (end &gt; -1) {
                value = str.substring(middle, end);
            }
            <span class="kwrd">else</span> {
                value = str.substring(middle);
            }
        }
        <span class="kwrd">if</span>(trimBlank){
            value = value.replace(/^\s*(.*?)\s*$/, <span class="str">'$1'</span>);
        }
    }

    <span class="kwrd">return</span> value;
}</pre>

	标签：<a href="http://www.imkevinyang.com/tags/cookie" title="Cookie" rel="tag">Cookie</a>, <a href="http://www.imkevinyang.com/tags/cookie%e4%b8%89%e8%a6%81%e7%b4%a0" title="Cookie三要素" rel="tag">Cookie三要素</a>, <a href="http://www.imkevinyang.com/tags/cookie%e5%b8%b8%e8%af%86" title="Cookie常识" rel="tag">Cookie常识</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/categories/techarticles/codebase" title="代码库" rel="tag">代码库</a>, <a href="http://www.imkevinyang.com/categories/techarticles" 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/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/06/javascript%e6%93%8d%e7%ba%b5cookie.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-09 11:17:53 -->
