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

<channel>
	<title>百度泛用户体验 &#187; Miller</title>
	<atom:link href="http://www.baiduux.com/blog/author/chenminliang/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.baiduux.com/blog</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 22 Dec 2011 03:47:11 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Web Storage全解析</title>
		<link>http://www.baiduux.com/blog/2010/06/21/web-storage%e5%85%a8%e8%a7%a3%e6%9e%90/</link>
		<comments>http://www.baiduux.com/blog/2010/06/21/web-storage%e5%85%a8%e8%a7%a3%e6%9e%90/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 05:08:59 +0000</pubDate>
		<dc:creator>Miller</dc:creator>
				<category><![CDATA[HTML/CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[前端技术]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[web storage]]></category>

		<guid isPermaLink="false">http://www.baiduux.com/blog/?p=363</guid>
		<description><![CDATA[Web应用的发展，使得客户端存储使用得也越来越多，而实现客户端存储的方式则是多种多样。最简单而且兼容性最佳的方案是Cookie，但是作为真正的客户端存储，Cookie则存在很多致命伤。]]></description>
			<content:encoded><![CDATA[<p>Web应用的发展，使得客户端存储使用得也越来越多，而实现客户端存储的方式则是多种多样。最简单而且兼容性最佳的方案是Cookie，但是作为真正的客户端存储，Cookie则存在很多致命伤。此外，在IE6及以上版本中还可以使用<a href="http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx" target="_blank">userData Behavior</a>、在Firefox下可以使用<a href="https://developer.mozilla.org/en/dom/storage" target="_blank">globalStorage</a>、在有Flash插件的环境中可以使用<a href="http://www.macromedia.com/support/documentation/en/flashplayer/help/help02.html">Flash Local Storage</a>，但是这几种方式都存在兼容性方面的局限性，因此真正使用起来并不理想。针对以上情况，HTML5中给出了更加理想的解决方案：假如你需要存储复杂的数据则可以使用<a href="http://dev.w3.org/html5/webdatabase/" target="_blank">Web Database</a>，可以像客户端程序一样使用SQL（不过Web Database标准当前正陷于僵局之中，而且目前已经实现的浏览器很有限）；假如你需要存储的只是简单的用key/value对即可解决的数据则可以使用<a href="http://dev.w3.org/html5/webstorage/" target="_blank">Web Storage</a>。 本文主要从各个方面介绍一下Web Storage的具体情况。</p>
<p> <span id="more-363"></span></p>
<h2><strong>sessionStorage与localStorage</strong></h2>
<p>Web Storage实际上由两部分组成：sessionStorage与localStorage。</p>
<p>sessionStorage用于本地存储一个会话（session）中的数据，这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储，仅仅是会话级别的存储。</p>
<p>localStorage用于持久化的本地存储，除非主动删除数据，否则数据是永远不会过期的。</p>
<h2><strong>为什么选择Web Storage而不是Cookie？</strong></h2>
<p>与Cookie相比，Web Storage存在不少的优势，概括为以下几点：</p>
<p>1. 存储空间更大：IE8下每个独立的存储空间为10M，其他浏览器实现略有不同，但都比Cookie要大很多。</p>
<p>2. 存储内容不会发送到服务器：当设置了Cookie后，Cookie的内容会随着请求一并发送的服务器，这对于本地存储的数据是一种带宽浪费。而Web Storage中的数据则仅仅是存在本地，不会与服务器发生任何交互。</p>
<p>3. 更多丰富易用的接口：Web Storage提供了一套更为丰富的接口，使得数据操作更为简便。</p>
<p>4. 独立的存储空间：每个域（包括子域）有独立的存储空间，各个存储空间是完全独立的，因此不会造成数据混乱。</p>
<h2><strong>兼容性如何？</strong></h2>
<p>接下来的各种测试是在以下浏览器中进行的：IE8、Firefox3.6、Chrome5、Safari4、Opera10，事实证明各个浏览器在API方面的实现基本上一致，存在一定的兼容性问题，但不影响正常的使用。</p>
<h2><strong>sessionStorage测试</strong></h2>
<p>本节主要针对sessionStorage的一些特性进行了测试，测试的重点在于各个浏览器对于session的定义以及跨域情况。测试方法很简单：打开<a href="http://varnow.org/pages/html5/web_storage/session/sessionStorage_A.html" target="_blank">页面A</a>，在页面A中写入当前的session数据，然后通过页面A中的链接或按钮使用不同的方式进入下页面B，如果页面B中能够访问到页面A中的数据则说明浏览器将当前情况的页面A、B视为同一个session。测试的具体结果如表1：</p>
<p align="center">表1 sessionStorage兼容性测试</p>
<table style="border-collapse: collapse" border="0" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">&#160;</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">原窗口</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">target=&quot;_blank&quot;</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">window.open</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">ctrl + click</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">跨域访问</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">IE8</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Firefox3.6</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否（null)</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Chrome5</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否（undefined)</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Safari4</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否（undefined)</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Opera10</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否（undefined)</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">否</td>
</tr>
</tbody>
</table>
<p>从表1中可以看出，处于安全性考虑所有浏览器下session数据都是不允许跨域访问的，包括跨子域也是不允许的。其他方面主流浏览器中的实现较为一致。</p>
<h2><strong>API测试</strong></h2>
<p>方法包括以下几个：</p>
<p>setItem(key,value)、removeItem(key)、getItem(key)、clear()、key(index)；</p>
<p>属性包括length、remainingSpace(非标准)。不过存储数据时可以简单的使用localStorage.key=value的方式。</p>
<p>测试地址为：<a title="http://varnow.org/pages/html5/web_storage/local/localStorage.html" href="http://varnow.org/pages/html5/web_storage/local/localStorage.html">http://varnow.org/pages/html5/web_storage/local/localStorage.html</a></p>
<p>测试结果另人满意，标准中定义的接口在各个浏览器中都已实现，此外IE8下新增了一个非标准的remainingSpace属性，用于获取存储空间中剩余的空间。结果如表2：</p>
<p align="center">表2 API测试</p>
<table style="border-collapse: collapse" border="0" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">&#160;</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">setItem</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">removeItem</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">getItem</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">clear</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">key</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">length</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">remainingSpace</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">IE8</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60"> 是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">是</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">Firefox3.6</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">Chrome5</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">Safari4</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">否</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="48">Opera10</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="74">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="65">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="57">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="70">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="81">是</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="145">否</td>
</tr>
</tbody>
</table>
<p>此外关于setItem(key,value)方法中的value类型，理论上可以是任意类型，不过实际上浏览器会调用value的toString方法来获取其字符串值并存储到本地，因此如果是自定义的类型则需要自己定义有意义的toString方法。</p>
<h2><strong>事件</strong></h2>
<p>标准的事件为onstorage，当存储空间中的数据发生变化时触发。此外，IE8中新增了一个onstoragecommit事件，当数据写入的时候触发。onstorage事件中的事件对象应该支持以下属性：</p>
<blockquote><p>The key attribute represents the key being changed.      <br />The oldValue attribute represents the old value of the key being changed.       <br />The newValue attribute represents the new value of the key being changed.       <br />The url attribute represents the address of the document whose key changed.       <br />The storageArea attribute represents the Storage object that was affected. </p>
</blockquote>
<p>对于这一标准的实现，webkit内核的浏览器（Chrome、Safari）以及Opera是完全遵循标准的，IE8则只实现了url，Firefox下则均未实现。</p>
<p>测试地址为：<a href="http://varnow.org/pages/html5/web_storage/local/event.html">http://varnow.org/pages/html5/web_storage/local/event.html</a></p>
<p>具体结果见表3。</p>
<p align="center">表3 onStorage事件对象属性测试</p>
<table style="border-collapse: collapse" border="0" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">&#160;</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">key</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">oldValue</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">newValue</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">url</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">storageArea</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">IE8</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Firefox3.6</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">无</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Chrome5</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Safari4</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="60">Opera10</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="140">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="100">有</td>
</tr>
</tbody>
</table>
<p>此外，不同的浏览器事件注册的方式以及对象也不一致，具体如表4。</p>
<p align="center">表4 onStorage事件注册对象</p>
<table style="border-collapse: collapse" border="0" cellspacing="0" cellpadding="2" width="600">
<tbody>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">&#160;</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">事件注册对象</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">备注</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">IE8</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">document</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">&#160;</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">Firefox3.6</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">document</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">必须使用document.addEventListener注册，否则无效。</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">Chrome5</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">window</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">&#160;</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">Safari4</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">body</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">&#160;</td>
</tr>
<tr>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="67">Opera10</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="111">window</td>
<td style="border:1px solid #ccc;padding:2px 4px" valign="top" width="422">&#160;</td>
</tr>
</tbody>
</table>
<h2><strong>&#160;</strong></h2>
<h2><strong>缺陷与不足</strong></h2>
<p>Web Storage的缺陷主要集中在其安全性方面，具体体现在以下两点：</p>
<p>1. 浏览器会为每个域分配独立的存储空间，即脚本在域A中是无法访问到域B中的存储空间的，但是浏览器却不会检查脚本所在的域与当前域是否相同。即在域B中嵌入域A中的脚本依然可以访问域B中的数据。测试地址：<a title="http://varnow.org/pages/html5/web_storage/local/corss_domain_js_access.html" href="http://varnow.org/pages/html5/web_storage/local/corss_domain_js_access.html">http://varnow.org/pages/html5/web_storage/local/corss_domain_js_access.html</a></p>
<p>2. 存储在本地的数据未加密而且永远不会过期，极易造成隐私泄漏。也许需要像保存密码一样询问用户是在用私人电脑还是公共电脑来决定是否将数据保存在本地。</p>
<h2><strong>跨页面通讯示例</strong></h2>
<p>示例地址：<a href="http://varnow.org/pages/html5/web_storage/app/play.html">http://varnow.org/pages/html5/web_storage/app/play.html</a></p>
<p align="center"><a href="http://varnow.org/wordpress/wp-content/uploads/2010/05/ndimension.jpg"><img style="border-bottom: 0px;border-left: 0px;border-top: 0px;border-right: 0px" border="0" alt="N-Dimension" src="http://varnow.org/wordpress/wp-content/uploads/2010/05/ndimension-thumb.jpg" width="244" height="235" /></a> </p>
<p>玩法很简单：选择 打开多个窗口，页面会自动打开并定位4个新窗口，小球会在多个窗口间运动，在小球运动的过程中可以拖动窗口或者打开新的窗口来控制小球进入新的区域。</p>
<p>实现原理：每个新打开的窗口会将自己的坐标以及大小写入localStorage，小球在运动到窗口边界时会检测小球将要进入的下一个窗口，如果找到该窗口则将小球坐标写入并通知新窗口接收小球。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.baiduux.com/blog/2010/06/21/web-storage%e5%85%a8%e8%a7%a3%e6%9e%90/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>HTML优化</title>
		<link>http://www.baiduux.com/blog/2010/03/15/html%e4%bc%98%e5%8c%96-2/</link>
		<comments>http://www.baiduux.com/blog/2010/03/15/html%e4%bc%98%e5%8c%96-2/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 07:39:24 +0000</pubDate>
		<dc:creator>Miller</dc:creator>
				<category><![CDATA[前端探索]]></category>
		<category><![CDATA[前端优化]]></category>

		<guid isPermaLink="false">http://www.baiduux.com/blog/?p=256</guid>
		<description><![CDATA[在前段领域中，对Javascript和CSS的优化一直是大家关注的焦点，相应的压缩优化工具也非常丰富，相对而言对HTML优化的关注则显得有些冷淡。在Steve Souders的大作《Even Faster Web Sites》中谈到非常多有效的前端优化方法，例如Javascript的加载、CSS选择符、图片优化、gzip、iframe问题等，唯独没有细说HTML优化。在整个前端的构成中，HTML是必不可少的一部分，而且是真正的展示“前端”。虽然与动辄十几K的Javascript相比，HTML的大小在整个页面资源中一般不会占太多的比重，而且还有Gzip，但是事实表明，大多数页面都有较大的压缩余地，即使是Gzip过后仍然能减小可观的体积，这一事实在后续的文章中会给出，本文主要讨论HTML优化的一些可行和看上去不那么可行的途径。

对于各种优化途径，如果一定要我给一个分类的话，我会用颜色来区分。对于那些在各种页面中都适用而且无害的方法，我将它们归为绿色。相对而言，只有在某些具体的情况下才适用或者有违标准的方法归为橙色。
绿色方法
1. 使用相对URL
对于页面中的各种URL，例如链接、外链CSS的href、外链Javascript的src、图片src、iframe src等，如果能够确定它们与当前页面是处于同一域名下的话，则可以使用相对URL，这样每一个URL都能够节省至少一个域名的长度。
2. 删除HTTP或HTTPS
绝对URL都以HTTP或HTTPS等协议头开始，如果能确定URL的协议与当前页面URL的协议是一致的，或者说该URL在多种协议下均是可用的，则可以考虑删除这个协议头。这样做虽然有些非主流，但事实证明是可行的，而且也有理论依据(见http://www.ietf.org/rfc/rfc2396.txt 第5.2节描述)。Nexus One的这个页面中有些资源URL就删除了协议头，虽然并不是出于节省资源的目的，但至少证明删除协议头是可行的。
对于CSS，如果删除协议头在IE7、IE8下会造成CSS下载两次，这个是需要注意的问题。
3. 删除注释
与CSS、Javascript一样，也可以通过删除HTML中的注释来实现优化。然而，这一点对于HTML来说却要复杂一些，因为在HTML中存在某些特殊作用的注释是不能删除的。
(a). IE条件注释

&#60;!--[if expression]&#62; HTML &#60;![endif]—&#62;

诸如这样的语法，只有符合expression的浏览器才能识别其中的内容。
(b). CDATA注释

/*  */

CDATA本身是XHTML中才需要的，在CDATA中的内容不需要对特殊字符进行转义，不过为了兼容老版本的浏览器，需要加上注释，以免出错。不过，对于这个注释，如果你的页面并没有真正的使用XHTML标准则可以大胆的删除掉。使用XHTML标准不是简单的声明DTD就可以办到的，除此之外还需要服务器能够派application/xhtml+xml这样的内容格式，另外还需要浏览器支持，目前IE并不支持XHTML格式。因此，目前你的页面可能是按照XHTML规范来写的，也能通过HTML验证，但想要兼容IE则一定还是以HTML方式来展示的。这样一来，很多为了遵循标准而增加的内容则可以删除，具体的在后文的橙色部分详述。
(c). 自定义注释
产品中自定义的一些具有特定功能的注释，例如统计。
4. 压缩空白符
在HTML中的大多数标签中，多个空白符都会被压缩成一个来显示，于是可以通过删除多余的空白符来减小HTML体积。不过需要注意的是并不是所有的空白符都可以这样做，例如pre、textarea中的空白符是按原样显示的，标签属性中的属性值也是按原样显示的，例如title、value等。
5. 压缩inline css &#38; Javascript
不管inline还是external，都需要压缩，这是减小体积的最直接的方式。
6. CSS&#38;Javascript尽量外链
外链CSS和Javascript，不仅仅是减小HTML本身的体积，而且还可以充分利用浏览器的缓存机制，所以当CSS、Javascript的代码量超过一定体积时，尽量外链。除此之外，尽量避免在页面中使用onmouseover=&#8221;xxxx&#8221;的方式来注册事件，既不利于维护也容易产生不必要的冗余代码。
7. 删除元素默认属性
在HTML规范中，很多HTML元素的属性是有默认值的，对于这些默认值可以抹去不写，下面是不完全统计。



标签
属性
默认值


style
media
screen


link
media
screen


form
method
get


form




input
type
text



橙色方法
橙色方法是指那些有违标准，或者会导致页面出现无法预料的问题的一类方法，算是一类非常规的方法，因此也仅仅适用于一些非常规的页面，例如搜索引擎首页。
1. 删除或替换
DOCTYPE对于页面展现非常重要，浏览器会根据具体的DOCTYPE来决定如何显示页面，除非你对删除DOCTYPE后的页面展示十分有把握，否则不要轻易删除。另外一种可行的方式是采用HTML5中的写法，即，大多数浏览器能够将这种doctype写法解析为标准或准标准(Almost Standard)模式，不过依然会造成一些问题，具体见这里。目前百度、Google都是这么做的。
2. 删除标签属性值的引号
引号不是必须的，删之。此处也需要考虑一些特殊情况，例如属性值中包含引号等。
（提醒：不符合XHTML规范）
3. 省略某些属性值
例如disabled、checked、multiple等的值都可以省略。
（提醒：不符合XHTML规范）
4. 删除可选的闭合标签
例如body、p、tr等标签是允许没有闭合标签的，具体的参考此处。
（提醒：不符合XHTML规范）
5. 删除自动闭合标签的&#8221;/&#8221;
（提醒：不符合XHTML规范）
工具
HTML优化工具目前比较理想的是Absolute HTML Compressor，另外，PageSpeed1.6中也引入了HTML压缩功能，不过目前只有四个简单的策略，尚处于实验性阶段。随着大家对前端性能越来越高的关注度，HTML优化及压缩方面也一定会有所发展的。
总结
1. HTML优化及压缩的发展滞后于前端其他资源，不过目前也已经引起大家越来越多的关注。
2. 绿色规则中的很多都是在写码过程中就可以注意和遵循的，如果能把这个优化融入到编码中，效果应该更好。
3. 橙色规则由于违背某些规范，只适用于某些特定的页面，使用时务必谨慎。
参考资料
HTML minify – to be or not to be?
Optimizing HTML
Optimizing Optimizing HTML
]]></description>
			<content:encoded><![CDATA[<p>在前段领域中，对Javascript和CSS的优化一直是大家关注的焦点，相应的压缩优化工具也非常丰富，相对而言对HTML优化的关注则显得有些冷淡。在<a href="http://www.stevesouders.com/blog/" target="_blank">Steve Souders</a>的大作《Even Faster Web Sites》中谈到非常多有效的前端优化方法，例如Javascript的加载、CSS选择符、图片优化、gzip、iframe问题等，唯独没有细说HTML优化。在整个前端的构成中，HTML是必不可少的一部分，而且是真正的展示“前端”。虽然与动辄十几K的Javascript相比，HTML的大小在整个页面资源中一般不会占太多的比重，而且还有Gzip，但是事实表明，大多数页面都有较大的压缩余地，即使是Gzip过后仍然能减小可观的体积，这一事实在后续的文章中会给出，本文主要讨论HTML优化的一些可行和看上去不那么可行的途径。</p>
<p><span id="more-256"></span></p>
<p>对于各种优化途径，如果一定要我给一个分类的话，我会用颜色来区分。对于那些在各种页面中都适用而且无害的方法，我将它们归为<strong><span style="color: #49ad44">绿色</span></strong>。相对而言，只有在某些具体的情况下才适用或者有违标准的方法归为<strong><span style="color: #d2aa0b">橙色</span></strong>。</p>
<h4><strong><span style="color: #49ad44">绿色方法</span></strong></h4>
<p>1. 使用相对URL</p>
<p>对于页面中的各种URL，例如链接、外链CSS的href、外链Javascript的src、图片src、iframe src等，如果能够确定它们与当前页面是处于同一域名下的话，则可以使用相对URL，这样每一个URL都能够节省至少一个域名的长度。</p>
<p>2. 删除HTTP或HTTPS</p>
<p>绝对URL都以HTTP或HTTPS等协议头开始，如果能确定URL的协议与当前页面URL的协议是一致的，或者说该URL在多种协议下均是可用的，则可以考虑删除这个协议头。这样做虽然有些非主流，但事实证明是可行的，而且也有理论依据(见<a href="http://www.ietf.org/rfc/rfc2396.txt">http://www.ietf.org/rfc/rfc2396.txt</a> 第5.2节描述)。<a href="http://www.google.com/phone/" target="_blank">Nexus One</a>的这个页面中有些资源URL就删除了协议头，虽然并不是出于节省资源的<a href="http://blog.httpwatch.com/2010/02/10/using-protocol-relative-urls-to-switch-between-http-and-https/" target="_blank">目的</a>，但至少证明删除协议头是可行的。</p>
<p>对于CSS，如果删除协议头<a href="http://www.stevesouders.com/blog/2010/02/10/5a-missing-schema-double-download/" target="_blank">在IE7、IE8下会造成CSS下载两次</a>，这个是需要注意的问题。</p>
<p>3. 删除注释</p>
<p>与CSS、Javascript一样，也可以通过删除HTML中的注释来实现优化。然而，这一点对于HTML来说却要复杂一些，因为在HTML中存在某些特殊作用的注释是不能删除的。</p>
<p>(a). <a href="http://msdn.microsoft.com/en-us/library/ms537512%28VS.85%29.aspx" target="_blank">IE条件注释</a></p>
<pre>
<div class="codecolorer-container html4strict default" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!--[if expression]&gt; HTML &lt;![endif]—&gt;</span></div></div>
</pre>
<p>诸如这样的语法，只有符合expression的浏览器才能识别其中的内容。</p>
<p>(b). <a href="http://javascript.about.com/library/blxhtml.htm" target="_blank">CDATA注释</a></p>
<pre>
/*  */
</pre>
<p>CDATA本身是XHTML中才需要的，在CDATA中的内容不需要对特殊字符进行转义，不过为了兼容老版本的浏览器，需要加上注释，以免出错。不过，对于这个注释，如果你的页面并没有真正的使用XHTML标准则可以大胆的删除掉。使用XHTML标准不是简单的声明DTD就可以办到的，除此之外还需要服务器能够派application/xhtml+xml这样的内容格式，另外还需要浏览器支持，目前IE并不支持XHTML格式。因此，目前你的页面可能是按照XHTML规范来写的，也能通过HTML验证，但想要兼容IE则一定还是以HTML方式来展示的。这样一来，很多为了遵循标准而增加的内容则可以删除，具体的在后文的橙色部分详述。</p>
<p>(c). 自定义注释</p>
<p>产品中自定义的一些具有特定功能的注释，例如统计。</p>
<p>4. 压缩空白符</p>
<p>在HTML中的大多数标签中，多个空白符都会被压缩成一个来显示，于是可以通过删除多余的空白符来减小HTML体积。不过需要注意的是并不是所有的空白符都可以这样做，例如pre、textarea中的空白符是按原样显示的，标签属性中的属性值也是按原样显示的，例如title、value等。</p>
<p>5. 压缩inline css &amp; Javascript</p>
<p>不管inline还是external，都需要压缩，这是减小体积的最直接的方式。</p>
<p>6. CSS&amp;Javascript尽量外链</p>
<p>外链CSS和Javascript，不仅仅是减小HTML本身的体积，而且还可以充分利用浏览器的缓存机制，所以当CSS、Javascript的代码量超过一定体积时，尽量外链。除此之外，尽量避免在页面中使用<span style="border-right: #ccc 1px solid;border-top: #ccc 1px solid;border-left: #ccc 1px solid;border-bottom: #ccc 1px solid;background-color: #eee">onmouseover=&#8221;xxxx&#8221;</span>的方式来注册事件，既不利于维护也容易产生不必要的冗余代码。</p>
<p>7. 删除元素默认属性</p>
<p>在<a href="http://www.w3.org/TR/html401/" target="_blank">HTML规范</a>中，很多HTML元素的属性是有默认值的，对于这些默认值可以抹去不写，下面是不完全统计。</p>
<table style="margin: auto;width: 400px" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td width="133" valign="top"><strong>标签</strong></td>
<td width="133" valign="top"><strong>属性</strong></td>
<td width="133" valign="top"><strong>默认值</strong></td>
</tr>
<tr>
<td width="133" valign="top">style</td>
<td width="133" valign="top">media</td>
<td width="133" valign="top">screen</td>
</tr>
<tr>
<td width="133" valign="top">link</td>
<td width="133" valign="top">media</td>
<td width="133" valign="top">screen</td>
</tr>
<tr>
<td width="133" valign="top">form</td>
<td width="133" valign="top">method</td>
<td width="133" valign="top">get</td>
</tr>
<tr>
<td width="133" valign="top">form</td>
<td width="133" valign="top"><a name="adef-enctype"></a></td>
<td width="133" valign="top"><a name="idx-applicationx-www-form-urlencoded-1"></a></td>
</tr>
<tr>
<td width="133" valign="top">input</td>
<td width="133" valign="top">type</td>
<td width="133" valign="top">text</td>
</tr>
</tbody>
</table>
<h4><strong><span style="color: #bf930d">橙色方法</span></strong></h4>
<p>橙色方法是指那些有违标准，或者会导致页面出现无法预料的问题的一类方法，算是一类非常规的方法，因此也仅仅适用于一些非常规的页面，例如搜索引擎首页。</p>
<p>1. 删除或替换</p>
<p>DOCTYPE对于页面展现非常重要，浏览器会根据具体的DOCTYPE来<a href="http://hsivonen.iki.fi/doctype/#handling" target="_blank">决定如何显示页面</a>，除非你对删除DOCTYPE后的页面展示十分有把握，否则不要轻易删除。另外一种可行的方式是采用HTML5中的写法，即<span style="background-color: #eeeeee;border: 1px solid #cccccc"></span>，大多数浏览器能够将这种doctype写法解析为标准或准标准(Almost Standard)模式，不过依然会造成一些问题，具体见<a href="http://blog.silentash.com/2010/01/html5-doctype-and-img-space/" target="_blank">这里</a>。目前<a href="http://www.baidu.com" target="_blank">百度</a>、<a href="http://www.google.com" target="_blank">Google</a>都是这么做的。</p>
<p>2. 删除标签属性值的引号</p>
<p>引号不是必须的，删之。此处也需要考虑一些特殊情况，例如属性值中包含引号等。</p>
<p>（提醒：不符合XHTML规范）</p>
<p>3. 省略某些属性值</p>
<p>例如disabled、checked、multiple等的值都可以省略。</p>
<p>（提醒：不符合XHTML规范）</p>
<p>4. 删除可选的闭合标签</p>
<p>例如body、p、tr等标签是允许没有闭合标签的，具体的参考<a href="http://hikejun.com/blog/?p=525" target="_blank">此处</a>。</p>
<p>（提醒：不符合XHTML规范）</p>
<p>5. 删除自动闭合标签的&#8221;/&#8221;</p>
<p>（提醒：不符合XHTML规范）</p>
<h4>工具</h4>
<p>HTML优化工具目前比较理想的是<a href="http://www.alentum.com/ahc/">Absolute HTML Compressor</a>，另外，<a href="http://code.google.com/speed/page-speed/download.html" target="_blank">PageSpeed1.6</a>中也引入了HTML压缩功能，不过目前只有<a href="http://code.google.com/p/page-speed/wiki/MinifyHtml" target="_blank">四个简单的策略</a>，尚处于实验性阶段。随着大家对前端性能越来越高的关注度，HTML优化及压缩方面也一定会有所发展的。</p>
<h4>总结</h4>
<p>1. HTML优化及压缩的发展滞后于前端其他资源，不过目前也已经引起大家越来越多的关注。</p>
<p>2. 绿色规则中的很多都是在写码过程中就可以注意和遵循的，如果能把这个优化融入到编码中，效果应该更好。</p>
<p>3. 橙色规则由于违背某些规范，只适用于某些特定的页面，使用时务必谨慎。</p>
<p>参考资料</p>
<h4><a href="http://www.speedingupwebsite.com/2010/02/02/html-minify-to-be-or-not-to-be/">HTML minify – to be or not to be?</a></h4>
<h4><a href="http://perfectionkills.com/optimizing-html/" target="_blank">Optimizing HTML</a></h4>
<h4><a href="http://annevankesteren.nl/2010/01/optimizing-html" target="_blank">Optimizing Optimizing HTML</a></h4>
]]></content:encoded>
			<wfw:commentRss>http://www.baiduux.com/blog/2010/03/15/html%e4%bc%98%e5%8c%96-2/feed/</wfw:commentRss>
		<slash:comments>35</slash:comments>
		</item>
		<item>
		<title>有啊网页诊断工具相关总结</title>
		<link>http://www.baiduux.com/blog/2010/02/04/%e6%9c%89%e5%95%8a%e7%bd%91%e9%a1%b5%e8%af%8a%e6%96%ad%e5%b7%a5%e5%85%b7%e7%9b%b8%e5%85%b3%e6%80%bb%e7%bb%93/</link>
		<comments>http://www.baiduux.com/blog/2010/02/04/%e6%9c%89%e5%95%8a%e7%bd%91%e9%a1%b5%e8%af%8a%e6%96%ad%e5%b7%a5%e5%85%b7%e7%9b%b8%e5%85%b3%e6%80%bb%e7%bb%93/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 11:10:46 +0000</pubDate>
		<dc:creator>Miller</dc:creator>
				<category><![CDATA[前端技术]]></category>

		<guid isPermaLink="false">http://www.baiduux.com/blog/?p=199</guid>
		<description><![CDATA[有啊网页诊断工具是一个轻量级的浏览器环境检测工具，基于Javascript以及Flash实现。它的主要功能包括问题检测以及针对某些问题给予提示性的建议，从而帮助用户自助的解决一些简单的问题。此外还能生成简单的检测报告，通过报告开发人员可是获得更为详细的环境信息，为解决问题提供有效的支持。
该工具具体的检测项包括以下几个：
1. Javascript版本信息
 2. Cookie是否开启
 3. 用户的屏幕分辨率
 4. Flash版本号以及浏览器是否开启了Flash拦截功能
 5. 浏览器字体大小是否正常（某些浏览器缩放后会导致页面布局混乱）
 6. 浏览器的Ajax功能是否正常，包括Get方式和Post方式
 7. 浏览器的图片浏览功能是否正常
 8. 用户的网络速度
通过对以上几个问题的检测，开发人员能够比较全面的了解目标浏览器的整体环境。

一、Javascript版本检测
对于Javascript版本的检测似乎显得不是那么必要，因为通常都可以根据浏览器的版本找到对应关系，不过作为浏览器环境的一部分，还是把该功 能加了进来。具体的实现原理：在页面中嵌入各个版本的script标签，并在每个标签中都给同一个全局变量赋值，最后根据变量的值得到版本号：
     
 JS_VERSION=('1.0');    

     
 JS_VERSION=('1.1');    

     
 JS_VERSION=('1.2');    

      ......
      ......
     
 JS_VERSION=('1.3');    

     
 window.onload = function(){
 if( typeof JS_VERSION != 'undefined' )
 document.getElementById('test').innerHTML = JS_VERSION;
 }    
 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://co.youa.baidu.com/content/qmrIO0W0Ep43TjA/weddiagnose/index.html" target="_blank">有啊网页诊断工具</a>是一个轻量级的浏览器环境检测工具，基于Javascript以及Flash实现。它的主要功能包括问题检测以及针对某些问题给予提示性的建议，从而帮助用户自助的解决一些简单的问题。此外还能生成简单的检测报告，通过报告开发人员可是获得更为详细的环境信息，为解决问题提供有效的支持。</p>
<p>该工具具体的检测项包括以下几个：</p>
<p>1. Javascript版本信息<br />
 2. Cookie是否开启<br />
 3. 用户的屏幕分辨率<br />
 4. Flash版本号以及浏览器是否开启了Flash拦截功能<br />
 5. 浏览器字体大小是否正常（某些浏览器缩放后会导致页面布局混乱）<br />
 6. 浏览器的Ajax功能是否正常，包括Get方式和Post方式<br />
 7. 浏览器的图片浏览功能是否正常<br />
 8. 用户的网络速度</p>
<p>通过对以上几个问题的检测，开发人员能够比较全面的了解目标浏览器的整体环境。</p>
<p><span id="more-199"></span></p>
<h3>一、Javascript版本检测</h3>
<p>对于Javascript版本的检测似乎显得不是那么必要，因为通常都可以根据浏览器的版本找到对应关系，不过作为浏览器环境的一部分，还是把该功 能加了进来。具体的实现原理：在页面中嵌入各个版本的script标签，并在每个标签中都给同一个全局变量赋值，最后根据变量的值得到版本号：</p>
<pre><!--mce:0-->     
 JS_VERSION=('1.0');    

     
 JS_VERSION=('1.1');    

     
 JS_VERSION=('1.2');    

      ......
      ......
 <!--mce:3-->    
 JS_VERSION=('1.3');    

     
 window.onload = function(){
 if( typeof JS_VERSION != 'undefined' )
 document.getElementById('test').innerHTML = JS_VERSION;
 }    
  <!--mce:4-->
</pre>
<p>根据W3C规范，script的language属性已经被废弃了，不过经测试该属性的兼容性较好，并能得到比较准确的结果。如果使用type= &#8220;text/javascriptN&#8221;则在很多浏览器下得不到正确的版本，因此在此依然使用了language属性。另外，关于javascript各个版本与浏览器的对应关系可以参考如下表格：</p>
<table border="1">
<tbody>
<tr>
<th>Version</th>
<th>Release date</th>
<th>Equivalent to</th>
<th>Netscape<br />
 Navigator</th>
<th>Mozilla<br />
 Firefox</th>
<th>Internet<br />
 Explorer</th>
<th>Opera</th>
<th>Safari</th>
<th>Google<br />
 Chrome</th>
</tr>
<tr>
<td>1.0</td>
<td>March 1996</td>
<td></td>
<td>2.0</td>
<td></td>
<td>3.0</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.1</td>
<td>August 1996</td>
<td></td>
<td>3.0</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.2</td>
<td>June 1997</td>
<td></td>
<td>4.0-4.05</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.3</td>
<td>October 1998</td>
<td>ECMA-262 1<sup>st</sup> edition / ECMA-262 2<sup>nd</sup> edition</td>
<td>4.06-4.7x</td>
<td></td>
<td>4.0</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.4</td>
<td></td>
<td></td>
<td>Netscape<br />
 Server</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.5</td>
<td>November 2000</td>
<td>ECMA-262 3<sup>rd</sup> edition</td>
<td>6.0</td>
<td>1.0</td>
<td>5.5 (JScript 5.5),<br />
 6 (JScript 5.6),<br />
 7 (JScript 5.7),<br />
 8 (JScript 6)</td>
<td>6.0,<br />
 7.0,<br />
 8.0,<br />
 9.0,<br />
 10.0</td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.6</td>
<td>November 2005</td>
<td>1.5 + Array extras + Array and String generics + E4X</td>
<td></td>
<td>1.5</td>
<td></td>
<td></td>
<td>3.0, 3.1</td>
<td></td>
</tr>
<tr>
<td>1.7</td>
<td>October 2006</td>
<td>1.6 + Pythonic generators + Iterators + let</td>
<td></td>
<td>2.0</td>
<td></td>
<td></td>
<td>3.2, 4.0</td>
<td>1.0</td>
</tr>
<tr>
<td>1.8</td>
<td>June 2008</td>
<td>1.7 + Generator expressions + Expression closures</td>
<td></td>
<td>3.0</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.8.1</td>
<td></td>
<td>1.8 + Native JSON support + Minor Updates</td>
<td></td>
<td>3.5</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.8.2</td>
<td></td>
<td>1.8.1 + Minor updates</td>
<td></td>
<td>3.6</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>1.9</td>
<td></td>
<td>1.8.1 + <a title="ECMAScript" href="http://en.wikipedia.org/wiki/ECMAScript"><span style="color: #000000">ECMAScript</span></a> 5 Compliance</td>
<td></td>
<td>4</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<p><br class="spacer_" /></p>
<p>相关参考资料：</p>
<p><a href="http://www.w3.org/TR/REC-html40/interact/scripts.html">http://www.w3.org/TR/REC-html40/interact/scripts.html</a> W3C 关于script标签的描述</p>
<p><a href="http://en.wikipedia.org/wiki/JavaScript">http://en.wikipedia.org/wiki/JavaScript#Versions</a> 维基百科关于JavaScript中的版本描述</p>
<p><a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/JavaScript_Overview">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/JavaScript_Overview</a> JavaScript Versions and ECMAScript Editions</p>
<p><a href="http://hi.baidu.com/jiaozhenqing/blog/item/d8f026380392f22cb9998fc7.html">http://hi.baidu.com/jiaozhenqing/blog/item/d8f026380392f22cb9998fc7.html</a> JavaScript版本一览</p>
<h3>二、检测Cookie是否开启</h3>
<p>先获取window.navigator['cookieEnabled']的值，如果该值非undefined的话则直接使用该值即可判断(经测 试IE7、Firefox3.5、Safari4、Opera10均能支持)。如果为undefined(即不支持该属性）则使用如下的方式：尝试向 Cookie中写入数据（为避免浪费设置1分钟的有效期），写入后检测document.cookie中是否存在刚才写入的数据，如果有则cookie有 效否则cookie无效：</p>
<pre> var cookie = document.cookie;
 var cookieEnabled = window.navigator['cookieEnabled'];

 if(typeof cookieEnabled == 'undefined'){
    var expireDate = new Date();
    expireDate.setTime(expireDate.getTime() + 1000);//Expired after 1 second
    var time = expireDate*1;
    var regExp = new RegExp(time + '=' + time);
    document.cookie = time + '=' + time + ';expires=' + expireDate.toGMTString();
    if( regExp.test(document.cookie) )
       cookieEnabled = true;
    else
       cookieEnabled = false;
 }
</pre>
<h3>三、Flash版本以及可用性检测</h3>
<p>Flash检测包含两方面的内容：</p>
<h4>1. Flash是否安装、禁用，Flash版本号</h4>
<p>对于Flash的版本检测可以通过在页面中引入AC_OETags.js（包含在Adobe官方的<a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">Flash Player Detection Kit</a>中），然后通过调用其中的GetSwfVer方法获得具体的版本号，如果Flash未安装或者被禁用则 GetSwfVer方法将会返回-1，否则返回正确的版本号。查看GetSwfVer的实现，与浏览器版本检测如出一辙，也是通过navigator信息 得到的，感兴趣的可以直接查看其源码。</p>
<h4>2. 如果Flash已经安装是否被拦截</h4>
<p>做这一步检查的前提是第一步能够获得正确的版本号。具体的检测方法也很简单，在页面中引入一个自定义的swf文件，在该swf文件中只定义 了一个方法checkFlash，并将该方法暴露出来使得JavaScript能够访问到，即 ExternalInterface.addCallback(&#8220;checkFlash&#8221;,checkFlash);在swf加载完成后通过JavaScript访问checkFlash方法，如 果存在该方法则说明Flash访问正常，否则Flash可能被拦截了。</p>
<p>以上两步的代码实现大致如下：</p>
<p>HTML代码</p>
<pre> </pre>
<p>Javascript代码</p>
<pre>    //获取Flash版本号，如果version为-1则可能未安装Flash或者Flash被禁用
    var version = GetSwfVer();
    if( version != -1 ){
         var isIE = navigator.appVersion.indexOf("MSIE") != -1;
         if( isIE )//IE下取Object元素
            var swfObj = document.getElementById('oCheck');
        else//其他浏览器下取embed元素
            var swfObj = document.getElementById('eCheck');
        if( !swfObj.checkFlash ) {
            //被拦截
        }
        else {
           //未拦截
        }
    }
    else{
        //未安装Flash Player或者Flash Player被禁用
    }</pre>
<div>参考资料</div>
<div><a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">http://www.adobe.com/products/flashplayer/download/detection_kit/</a> Flash Player Detection Kit</div>
<p><br class="spacer_" /></p>
<h3>四、Ajax功能检测</h3>
<p>该功能的检测比较直接，即分别构造Ajax Get和Ajax Post请求，在请求过程中详细的记录Ajax的实例类型（ActiveXObject 或 XMLHTTPRequest）、请求的各个阶段的状态以及最终的请求结果。</p>
<h3>五、检测图片是否被禁用</h3>
<p>检测图片是否禁用的原理：新建一个Image对象，并监听其onload事件（IE某些版本中无效，需要监听onreadystatechange 事件）以及onerror事件。</p>
<pre> var img = new Image;
 //监听onload事件，由于在ie的某些版本中onload事件并不会被触发，因此增加onreadystatechange监听器
 img.onload = img.onreadystatechange = function(){
 //加载成功说明图片功能是正常的
 }
 //监听onerr事件
 img.onerror = function(){
 //如果触发了onerror事件，则说明图片功能不正常（在img的src正确的情况下）
 }
 img.src = 'xxx';</pre>
<p>以上的实现中，对于加载事件的监听并没有什么问题，不过对于onerror事件还是存在比较大的兼容性问题：经测试发现，在IE下禁用图片后并不会触发 onerror事件，而在Firefox中禁用图片后则能正常的触发onerror事件，至此的结论是使用onerror来判断图片功能是准确的。取而代 之的是使用超时检测来判断，即假定图片在一定时间内仍未能加载成功则视为失败。</p>
<pre> var img = new Image;
 //监听onload事件，由于在ie的某些版本中onload事件并不会被触发，因此增加onreadystatechange监听器
 img.onload = img.onreadystatechange = function(){
 //加载成功说明图片功能是正常的
 }
 //监听onerr事件
 img.onerror = function(){
 //如果触发了onerror事件，则说明图片功能不正常（在img的src正确的情况下）
 }
 img.src = 'xxx';
 var timer = setTimeout(function(){
 //如果执行到这里则认为图片功能异常
 },TIMEOUT);</pre>
<h3>六、检测网络速度</h3>
<p>实现原理：请求一张已知大小的图片N次，并分别记录每次请求所花费的时间，最后根据图片大小计算出平均的网络速度。这里需要注意的是图片的大小问题，图片如果太小结果会不准确，需要选择一张合适的图片，另外为防止图片被浏览器缓存需要给图片的src添加时间戳。</p>
<pre>/*
 * @param { Integer } times 请求图片的次数
 * @callback { Function } callback 图片请求完成后调用的函数
 */
 function detectNetSpeedWithImage(times,callback){    
 times = times || 1;
 //已完成请求
 var completedImg = 0,
 res = [],
 timer = null,
 done = false;        
 for( var i = 0; i &lt; times; i++){
 (function( index ){
 setTimeout(function(){            
 var img = new Image();
 //开关，在某些浏览器（如IE）会响应两次onreadystatechange
 var loaded = false;
 //请求开始时间
 var tStart = new Date();
 img.onload = img.onreadystatechange = function(){
 if( loaded ) return;
 //请求结束时间
 var tEnd = new Date();
 res.push(tEnd - tStart);
 //已完成请求加1
 completedImg++;
 loaded = true;
 //全部请求完成后调用callback
 if( completedImg == times &amp;&amp; callback ){
 callback.call(null,res);
 if( timer ) clearTimeout(timer);
 }
 }
 img.onerror = function(){
 if( done ) return;
 callback([]);
 done = true;
 clearTimeout(timer);
 }
 img.src = Config.NET_SPEED_DETECT_IMAGE_URL + &#039;?t=&#039; + (new Date())*1;
 },index * Config.NET_SPEED_DETECT_IMAGE_REQUEST_INTERVAL);
 })(i);
 }
 //超时操作
 timer = setTimeout(function(){
 if( completedImg != times &amp;&amp; !done ){
 callback([]);
 }
 },Config.NET_SPEED_DETECT_TIMEOUT + times * Config.NET_SPEED_DETECT_IMAGE_REQUEST_INTERVAL);
 }

 detectNetSpeedWithImage(Config.NET_SPEED_DETECT_TIMES,function(res){
 //失败
 if( res.length &lt; 1 ){
 _handleError();
 }
 //成功
 else{
 var time = 0;
 for( var i = 0,l = res.length; i &lt; l; i++){
 time += res[i] / ( l * 1000 );
 }
 //计算速度
 var speed = Config.NET_SPEED_DETECT_IMAGE_SIZE / time;
 //取小数点后两位
 speed = speed.toFixed(2);        
 me.isOver = true;    
 }
 });</pre>
<h3>七、检测客户端分辨率</h3>
<p>直接获取window.screen的width与height即可。</p>
<h3>八、检测浏览器字体大小是否正常</h3>
<p>在IE6下，当使用px作为单位时，元素（字体大小）无法进行缩放，这在很多情况下都会造成页面混乱。另外，对于目前大多数浏览器，在默认字体设置下，1em恰恰等于16px，于是可以根据这个原理来检测浏览器字体是否正常，具体的方式如下：</p>
<p>1.  创建一个DIV元素1，并设定其高为16px，宽为1px并使用CSS将其定位到可视范围之外（不能通过display或visibility隐藏）</p>
<p>2.  创建另一个DIV元素2，并设置其font-size为medium。在该DIV内部创建一个DIV元素3，并设置其高位1em，宽为1px并使用CSS将其定位到可视范围之外</p>
<p>3. 比较元素1和元素3的高度，如果相等则字体大小正常否则异常</p>
<p>注意，元素3必须包含在元素2中，并且给元素2设置font-size:  medium。因为em是一个相对单位，1em的大小相当于其父元素字体的大小，为了使检测不受其他样式影响，将其放在一个字体大小为浏览器默认值的容器中。</p>
<pre> //隐藏DIV的CSS
 var hideCSS = 'position:absolute;left:-2000px;';

 //以px为宽度单位的元素
 var pxBlock = document.createElement('div');
 pxBlock.style.cssText = 'width:16px;height:1px;' + hideCSS;
 document.body.appendChild(pxBlock);
 //构建一个字体大小为浏览器默认值的容器
 var emBlockWrapper = document.createElement('div');
 emBlockWrapper.style.fontSize = 'medium';

 //以em为字宽度单位的元素
 var emBlock = document.createElement('div');
 emBlock.style.cssText = 'width:1em;height:1px;' + hideCSS;

 emBlockWrapper.appendChild(emBlock);
 document.body.appendChild(emBlockWrapper);

 //获得固定和变化的div宽度
 var pxBlockWidth = pxBlock.offsetWidth;
 var emBlockWidth = emBlock.offsetWidth;

 if(pxBlockWidth == emBlockWidth){
 //字体正常
 }
 else{
 //字体异常
 }</pre>
<p><br class="spacer_" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.baiduux.com/blog/2010/02/04/%e6%9c%89%e5%95%8a%e7%bd%91%e9%a1%b5%e8%af%8a%e6%96%ad%e5%b7%a5%e5%85%b7%e7%9b%b8%e5%85%b3%e6%80%bb%e7%bb%93/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

