<?xml version="1.0" encoding="UTF-8"?>
  <feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html"><![CDATA[W3C标准WEB前端DHTML精英俱乐部 - Web Develop]]></title>
  <subtitle type="html"><![CDATA[Javascript和CSS权威专家WEB前端开发指南]]></subtitle>
  <id>http://www.v-ec.com/dh20156/</id>
  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/" /> 
  <link rel="self" type="application/atom+xml" href="http://www.v-ec.com/dh20156/atom.asp" /> 
  <generator uri="http://www.pjhome.net/" version="2.8">PJBlog3</generator> 
  <updated>2010-07-28T21:28:46+08:00</updated>

  <entry>
	  <title type="html"><![CDATA[发送自IPad的日志]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-07-28T21:28:46+08:00</updated>
	  <published>2010-07-28T21:28:46+08:00</published>
		  <summary type="html"><![CDATA[Fck Editer只能在源码模式下输入, File Upload灰色禁用状态，木有办法上传文件的IPad下的liu浏览器不是很好用的说。 ]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=303" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=303</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[JQuery字符串转DOM节点BUG]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-06-22T17:37:07+08:00</updated>
	  <published>2010-06-22T17:37:07+08:00</published>
		  <summary type="html"><![CDATA[<p>在修正一个UI的BUG时发现<strong>JQuery将字符串转DOM节点时会将针对IE6的CSS Hack的样式部分进行转义</strong>，测试代码如下：</p>
<p><strong>1、引入JQuery代码</strong></p>
<p>2、运行如下代码测试：</p>
<p><span style="font-size: 14px;">+function(){<br />
var s = '&lt;h1&gt;&lt;em class=&quot;a_b c&quot; style=&quot;min-height:50px;_height:50px;&quot;&gt;x&lt;/em&gt;&lt;/h1&gt;';<br />
var d = $(s);<br />
alert(d.html());<br />
}();</span></p>
<p><strong>FF中的结果为：</strong></p>
<p>&lt;em class=&quot;a_b c&quot; style=&quot;min-height: 50px;&quot;&gt;x&lt;/em&gt;</p>
<p>&quot;_height:50px;&quot; 部分不见了。</p>
<p><strong>IE下的结果为：</strong></p>
<p>&lt;EM class=&quot;a_b c&quot; style=&quot;MIN-HEIGHT: 50px; HEIGHT: 50px&quot;&gt;x&lt;/EM&gt;</p>
<p>&quot;_&quot; 不见了。</p>
<p>&nbsp;</p>
<p>遇到此BUG的同学可以将inline的style改成className的方式来处理一下。</p>
<p><strong>JQuery Bug Report:</strong> <a href="http://forum.jquery.com/topic/transform-bug-in-html-string" target="_blank">http://forum.jquery.com/topic/transform-bug-in-html-string</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=302" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=302</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[Freemarker风格的JavaScript模板引擎EasyTemplate]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-06-05T16:32:45+08:00</updated>
	  <published>2010-06-05T16:32:45+08:00</published>
		  <summary type="html"><![CDATA[<h2>在前后端分离的解决方案中，模板起到了重要作用！</h2>
<p>在使用Struts或Spring的后端中，使用Freemarker模板作为载体，能够非常有效的实现前后端的分离。</p>
<p>有人或许会认为使用前端模板一样可以实现此效果，而且实现的会更好。</p>
<p>如果单纯从技术和实现的角度去考虑，确实是使用前端模板效果会更好，前后端分离的会更彻底，但如果真的这样做，任何地方都采用前端模板去渲染，那这样的WEB应用将会失去高可靠性及易用性。</p>
<p>我们的建议是，一般的页面由后端模板渲染，页面中的某些特殊模组，可以由前端模板进行渲染，比如，一个具有诸多交互且内容不断变化的数据列表。</p>
<h3>在使用过Freemarker模板后，感觉它的语法比较朴实，平易近人，容易上手，于是决定按它的语法风格实现一个前端的模板引擎，这就有了下面的EasyTemplate!</h3>
<p>EasyTemplate模板的<strong>函数大小为1.34k</strong>（未压缩），暂时只<strong>实现了list，list index，if elseif&nbsp;else</strong>等功能，应该可以满足大部分的使用需求了。</p>
<p>EasyTemplate模板引擎的解析速度测试，渲染1000行数据，在不同的浏览器中，平均速度大约在<strong>30毫秒以内</strong>（测试机器性能较弱）。</p>
<h3>EasyTemplate可用标签：</h3>
<p><span style="background-color: Yellow;">&lt;#et tname dataname&gt; //模板开始标签，tname为此模板的名称，dataname为此模板中用到的数据名称<br />
</span></p>
<p><span style="background-color: Yellow;">&lt;#if (condition)&gt;</span><span style="background-color: Yellow;"><br />
<br />
&lt;#elseif (condition)&gt;<br />
<br />
&lt;#else&gt;<br />
<br />
&lt;/#if&gt;</span></p>
<p><span style="background-color: Yellow;">${x?a:b} //三元表达式，最后不能加分号&quot;；&quot; 注意：在所有的 {} 中都不能出现分号！<br />
</span></p>
<p><span style="background-color: Yellow;">&lt;#list List as list&gt; //遍历一个数组对象<br />
<br />
${list_idx} //在此次遍历中的当前索引<br />
<br />
${list.xxx} //取值<br />
<br />
&lt;/#list&gt; //结束遍历</span></p>
<p><span style="background-color: Yellow;">&lt;/#et&gt; //模板结束标签</span></p>
<p>&nbsp;</p>
<h3>调用方法：</h3>
<p><strong><span style="background-color: Lime;">var x = easyTemplate(sTemplate,oData);</span></strong></p>
<p>&nbsp;</p>
<p>EasyTemplate模板引擎函数下载：<a href="http://www.easyui.org.cn/easyTemplate.js" target="_blank">http://www.easyui.org.cn/easyTemplate.js</a></p>
<p>EasyTemplate模板引擎在线演示：<a href="http://www.easyui.org.cn/easyTemplate.html" target="_blank">http://www.easyui.org.cn/easyTemplate.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=300" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=300</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[离线存储解决方案分析实现]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-13T16:05:31+08:00</updated>
	  <published>2010-05-13T16:05:31+08:00</published>
		  <summary type="html"><![CDATA[<p>随着HTML5的呼声逐渐增大，是时候将其中的<strong>DOM Storage</strong>纳入考量范围了。</p>
<h2>DOM Storage</h2>
<p>类似http session和cookies的两种全新机制：</p>
<p><strong>Session Storage</strong></p>
<ul>
    <li>会话存储是针对用户执行单个事务的方案而设计的。</li>
    <li>应用于用户在同一时间（同一个会话期）跨多窗口运行同一事务的场景。</li>
    <li>来自MDC的说法:它常用于临时存储那些需要保存的数据以便当浏览器不小心刷新时能够恢复它们。</li>
    <li>它含有一个在页面会话有效期内可用的存储区域。</li>
    <li>只要页面没有关闭，一个页面会话就始终保持着，并且当页面被重新载入或恢复时&ldquo;复活&rdquo;。</li>
    <li>打开一个新的标签页或新窗口都会初始化新的会话。</li>
    <li>Internet Explorer 8:不会在浏览器故障得到恢复后继续使用 sessionStorage。</li>
    <li>Firefox也木有实现介个功能，参见：bug 33945 https://bugzilla.mozilla.org/show_bug.cgi?id=339445</li>
</ul>
<p><br />
Cookies不能很实时的处理这些情形：<br />
<em><br />
如，某个用户在某站点购买机票时打开了两个不同的窗口，如果该站点使用cookies来记录用户的购买信息，那么，该用户在一个窗口中&ldquo;已购买&rdquo;的机票信息可能在另一个窗口中就被&ldquo;漏&rdquo;掉了，这将导致该用户在另一个窗口中得不到实时通知的情况下购买两张相同航班的机票。</em><br />
<br />
sessionStorage接口的定义正是为了解决此情形，一个站点可以将它的数据添加到session storage，然后，该站点在某窗口中打开的任何页面都可以访问到此数据。<br />
<br />
<strong>Local Storage</strong></p>
<ul>
    <li>本地存储机制跨多个窗口，且持续范围可超过当前会话。localStorage属性可为域提供持久存储区域。</li>
    <li>它可使得WEB程序能够存储MB级的用户数据，如，存储整个用户签名档或用户的收件箱。</li>
    <li>它也为客户端性能的优化提供了一种解决方案。</li>
</ul>
<p><br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Cookies还是不能很好地处理这些情形，因为它每次请求时都会将值传送给服务器，而且数据会过期。<br />
<br />
<strong>每个站点都会有它们各自的存储区域。</strong><br />
<br />
<strong>Storage对象接口定义</strong><br />
<br />
<strong>constructor:</strong><br />
&nbsp;&nbsp;&nbsp; 返回Storage对象的构造器引用（Object）<br />
<br />
<strong>remainningSpace:</strong><br />
&nbsp;&nbsp;&nbsp; 返回Storage对象中剩余的内存数量（Bytes）<br />
<br />
<strong>length:</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中key/value配对列表的长度，只读，数字类型<br />
<br />
<strong>key(n):</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中key/value配对列表的第N个元素的key值，如果N&gt;=length，则返回null<br />
<br />
<strong>getItem(key):</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中给定的key值（复制的）<br />
<br />
<strong>setItem(key, value):</strong><br />
&nbsp;&nbsp;&nbsp; 复制一份给定的value（不支持包含ImageData的对象，报NOT_SUPPORTED_ERR）<br />
&nbsp;&nbsp;&nbsp; 检测在当前Storage对象list中是否存在指定的key：<br />
&nbsp;&nbsp;&nbsp; 如果不存在，则在该list中插入此key/value的配对。<br />
&nbsp;&nbsp;&nbsp; 如果存在，则更新此key的value。<br />
&nbsp;&nbsp;&nbsp; 如果操作失败，则报空间不足（QUOTA_EXCEEDED_ERR）异常。<br />
<br />
<strong>removeItem(key):</strong><br />
&nbsp;&nbsp;&nbsp; 从当前Storage对象中移除指定的key值<br />
<br />
<strong>clear():</strong><br />
&nbsp;&nbsp;&nbsp; 清空当前Storage对象中所有的key/value<br />
<br />
<strong>sessionStorage对象</strong></p>
<ul>
    <li>sessionStorage作为Storage对象的实例，存在于浏览器全局作用域中，同源共用。</li>
    <li>全局对象，可通过sessionStorage或window.sessionStorage访问。</li>
    <li>生存周期为一个窗口或一个TAB的生存期间所加载的所有同源页面。</li>
    <li>session storage存储的内容只在用户请求的数据被删除或者存储空间不足时才会被设置过期。</li>
    <li>当sessionStorage调用setItem,removeItem或clear方法并成功执行时，所有打开的窗口中的sessionStorage都会</li>
    <li>被指向到相同的存储区域，且都会触发Storage对象的相应事件。</li>
</ul>
<p><br />
<strong>localStorage对象</strong></p>
<ul>
    <li>localStorage对象作为Storage对象的实例，存在于浏览器全局作用域中，同源共用。</li>
    <li>每个域和子域都具有自己单独的本地存储区域。 域可以访问子域的存储区域，而子域也可以访问父域的存储区域。</li>
    <li>注意：http://example.com域无法访问https://example.com中的localStorage数据。</li>
    <li>localStorage['example.com']&nbsp; 可由 example.com 及其任何子域访问。</li>
    <li>子域 localStorage['www.example.com']可由 example.com 访问，但不能由其他子域访问，如 mail.example.com。</li>
    <li>全局对象，可通过localStorage或window.localStorage访问。</li>
    <li>local storage存储的内容只有在用户提出请求或出于安全因素处理时才会被设置过期。</li>
</ul>
<p><br />
<strong>安全提示</strong></p>
<ol>
    <li>当请求违反存储限制时，抛出SECURITY_ERR异常（如用户设置不允许存储数据）。</li>
    <li>磁盘配额限制将施加于设置相应值的页面所在的域，而不是施加于在其中设置相应值的域。 这可防止恶意脚本用尽相关域的存储配额。 同时还可阻止此类脚本使用随机子域来存储无限数量的数据。</li>
    <li>如果来自非同源（源由协议、主机名（或 IP 地址）和域的 URL 的端口号确定）的脚本，抛出SECURITY_ERR异常并忽略其他步骤。</li>
    <li>如果文档来源不属于HTML5源时，抛出SECURITY_ERR异常并忽略其他步骤。</li>
    <li>存储在Storage中的数据未经过任何编码和加密，建议在使用的时候不要将敏感的重要的用户数据存储在Storage中。</li>
</ol>
<p>当浏览器切换到private模式时（如果可以的话），localStorage存储的数据在浏览器模式改变后将被丢弃。</p>
<p>当localStorage调用setItem,removeItem或clear方法并成功执行时，所有打开的窗口中的localStorage都会被指向到相同的存储区域，且都会触发Storage对象的相应事件。<br />
<br />
<strong>Storage事件（实现者）</strong><br />
<br />
当一个存储区域发生改变时，Storage事件即被触发，所有窗口中的Storage对象都将被影响。<br />
<br />
<strong>事件定义</strong><br />
<br />
<strong>initStorageEvent():</strong><br />
&nbsp;&nbsp;&nbsp; 使用类似DOM Events接口的方式初始化事件<br />
<br />
<strong>key:</strong><br />
&nbsp;&nbsp;&nbsp; 表示key被改变<br />
<br />
<strong>oldValue:</strong><br />
&nbsp;&nbsp;&nbsp; key被改变之前的值<br />
<br />
<strong>newValue:</strong><br />
&nbsp;&nbsp;&nbsp; key改变之后的值<br />
<br />
<strong>url:</strong><br />
&nbsp;&nbsp;&nbsp; 表示该地址文档对象中的key被改变<br />
<br />
<strong>storageArea:</strong><br />
&nbsp;&nbsp;&nbsp; 影响到的Storage对象<br />
<br />
<strong>DOM Storage Events（IE8+）</strong><br />
<br />
当更新存储区域中的数据时，Internet Explorer 将触发相应事件，以便在浏览器或选项卡的多个实例之间能够保持信息同步。<br />
<br />
<strong>onstorage</strong></p>
<ul>
    <li>当存储区域发生更改时，document&nbsp; 中将触发&nbsp; onstorage 事件。</li>
    <li>所有共享相同会话上下文的文档，以及当前显示来自相同域或子域（即，本地存储将要提交到的域或子域）的页面的文档，都会接收到该事件。</li>
    <li>如果目标文档对象当前未处于活动状态，则 Internet Explorer 不会触发任何事件。</li>
</ul>
<p><br />
<strong>onstoragecommit</strong></p>
<ul>
    <li>Internet Explorer 使用 XML 文件来存储本地存储数据。 将本地存储数据写入到磁盘上时，将触发&nbsp; onstoragecommit 事件。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp; <br />
<strong>磁盘空间</strong></p>
<p>每个域默认可以存储 <strong>5 MB</strong> 的数据，当超过时，需要提醒用户是否增加空间。<br />
IE8+浏览器默认为 10 MB<br />
<br />
<strong>userData Behavior</strong><br />
<br />
IE5+支持，允许对象存储数据在用户端<br />
<br />
使用条件，<strong>为某对象设置behavior样式</strong><br />
<br />
<strong>html:</strong><br />
&nbsp;&nbsp;&nbsp; &lt;ELEMENT&nbsp; STYLE=&quot;behavior:url('#default#userData')&quot; ID=sID&gt;</p>
<p><strong>scripting:</strong><br />
&nbsp;&nbsp;&nbsp; object.style.behavior = &quot;url('#default#userData')&quot;<br />
&nbsp;&nbsp;&nbsp; object.addBehavior(&quot;#default#userData&quot;)<br />
<br />
<strong>userData对象成员表</strong><br />
<br />
<strong>expires:</strong><br />
&nbsp;&nbsp;&nbsp; 设置或返回userData的到期时间<br />
<br />
<strong>XMLDocument:</strong><br />
&nbsp;&nbsp;&nbsp; 返回一个XML引用<br />
<br />
<strong>load(user):</strong><br />
&nbsp;&nbsp;&nbsp; 加载指定user存储在userData中的数据对象<br />
<br />
<strong>getAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 返回指定attr的值<br />
<br />
<strong>setAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 设置指定attr的值<br />
<br />
<strong>removeAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 移除指定的attr值<br />
<br />
<strong>save(user):</strong><br />
&nbsp;&nbsp;&nbsp; 保存指定user的数据对象到userData中<br />
<br />
<strong>磁盘空间</strong><br />
<br />
<strong>本地：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>局域网：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:512KB，domain limit:10240KB<br />
<strong>可信站点：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>互联网：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>受限站点：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:64KB，domain limit:640KB<br />
<br />
<strong>安全提示</strong></p>
<ol>
    <li>为了安全考虑，userData存储的数据只对相同的目录，且使用相同的协议才能访问。</li>
    <li>存储在userData中的数据未经过任何编码和加密，建议在使用的时候不要将敏感的重要的用户数据存储在userData中。</li>
    <li>将userData行为应用在html,head,title,style等对象上时，使用save和load方法时将会发生错误。</li>
</ol>
<p><br />
<br />
<strong>Adobe Flash Player本地存储</strong><br />
存储空间: 100 KB<br />
<br />
<strong>Cookie</strong><br />
存储空间: 4 KB<br />
<br />
<a href="http://www.easyui.org.cn/domStorage.html" target="_blank">简单实现一个兼容新老浏览器的离线存储演示，简单判断是否可用localStorage，否则使用cookie.</a><br />
<br />
在线演示DEMO：<a href="http://www.easyui.org.cn/domStorage.html" target="_blank">http://www.easyui.org.cn/domStorage.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=299" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=299</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[客户端环境诊断为解决用户遇到的问题做好准备]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-11T11:15:53+08:00</updated>
	  <published>2010-05-11T11:15:53+08:00</published>
		  <summary type="html"><![CDATA[<p>记得以前和<em><strong> <a href="http://www.blogjava.net/emu/" target="_blank">EMU</a></strong></em>  同学聊天的时候，他提到最多的话题就是如何处理用户咨询和投诉，从而较好的解决他们遇到的问题。</p>
<p>当一个产品的用户数量达到一个很大 的数量级时，这种情况确实会经常发生，若不能有效的解决，的确让产品工程师们很困扰。</p>
<p>在<a href="http://www.baiduux.com/" target="_blank"><em><strong>百 度泛用户体验博客</strong></em></a>中，百度有啊的同学分享了他们是怎么来处理这种情况的，那就是，提供一个客户端环境诊断的小工具 （页面），让用户配合工程师一起进行诊断，为处理用户遇到的问题提供较有价值，较全面的资料。</p>
<p>原文如下：</p>
<p><span class="author">作者：<a title="由 Miller
发表" href="http://www.baiduux.com/blog/author/chenminliang/">Miller</a></span></p>
<p><a target="_blank" href="http://co.youa.baidu.com/content/qmrIO0W0Ep43TjA/weddiagnose/index.html">有啊网页诊断工具</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>&nbsp;</p>
<h3>一、Javascript版本检测</h3>
<p>对于Javascript版本的检测似乎显得不是那么必要，因为通常都可以根据浏览器的版本找到对应关系，不过作为浏览器环境的一部分，还是把该功  能加了进来。具体的实现原理：在页面中嵌入各个版本的script标签，并在每个标签中都给同一个全局变量赋值，最后根据变量的值得到版本号：</p>
<pre><!--mce:0--> &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.0');&nbsp;&nbsp;&nbsp;&nbsp;

 &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.1');&nbsp;&nbsp;&nbsp;&nbsp;

 &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.2');&nbsp;&nbsp;&nbsp;&nbsp;

      ......
      ......
 <!--mce:3-->&nbsp;&nbsp; &nbsp;
 JS_VERSION=('1.3');&nbsp;&nbsp; &nbsp;

 &nbsp;&nbsp; &nbsp;
 window.onload = function(){
 if( typeof JS_VERSION != 'undefined' )
 document.getElementById('test').innerHTML = JS_VERSION;
 }&nbsp;&nbsp; &nbsp;
  <!--mce:4-->
</pre>
<p>根据W3C规范，script的language属性已经被废弃了，不过经测试该属性的兼容性较好，并能得到比较准确的结果。如果使用type=  &ldquo;text/javascriptN&rdquo;则在很多浏览器下得不到正确的版本，因此在此依然使用了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>&nbsp;</td>
            <td>2.0</td>
            <td>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.1</td>
            <td>August 1996</td>
            <td>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.2</td>
            <td>June 1997</td>
            <td>&nbsp;</td>
            <td>4.0-4.05</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</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>&nbsp;</td>
            <td>4.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.4</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Netscape<br />
            Server</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</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>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.6</td>
            <td>November 2005</td>
            <td>1.5 + Array extras + Array and String generics + E4X</td>
            <td>&nbsp;</td>
            <td>1.5</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>3.0, 3.1</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.7</td>
            <td>October 2006</td>
            <td>1.6 + Pythonic generators + Iterators + let</td>
            <td>&nbsp;</td>
            <td>2.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</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>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.8.1</td>
            <td>&nbsp;</td>
            <td>1.8 + Native JSON support + Minor Updates</td>
            <td>&nbsp;</td>
            <td>3.5</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.8.2</td>
            <td>&nbsp;</td>
            <td>1.8.1 + Minor updates</td>
            <td>&nbsp;</td>
            <td>3.6</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.9</td>
            <td>&nbsp;</td>
            <td>1.8.1 + <a href="http://en.wikipedia.org/wiki/ECMAScript" title="ECMAScript"><span style="color: rgb(0, 0, 0);">ECMAScript</span></a> 5 Compliance</td>
            <td>&nbsp;</td>
            <td>4</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</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(&ldquo;checkFlash&rdquo;,checkFlash);在swf加载完成后通过 JavaScript访问checkFlash方法，如 果存在该方法则说明Flash访问正常，否则Flash可能被拦截了。</p>
<p>以上两步的代码实现大致如下：</p>
<p>HTML代码</p>
<pre>
&nbsp;</pre>
<p>Javascript代码</p>
<pre>
    //获取Flash版本号，如果version为-1则可能未安装Flash或者Flash被禁用
    var version = GetSwfVer();
    if( version != -1 ){
         var isIE = navigator.appVersion.indexOf(&quot;MSIE&quot;) != -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>&nbsp;</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){&nbsp;&nbsp; &nbsp;
 times = times || 1;
 //已完成请求
 var completedImg = 0,
 res = [],
 timer = null,
 done = false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 for( var i = 0; i &lt; times; i++){
 (function( index ){
 setTimeout(function(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 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 + '?t=' + (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);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 me.isOver = true;&nbsp;&nbsp; &nbsp;
 }
 });</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>&nbsp;</p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=298" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=298</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[在WEB开发中怎样的代码才是可维护性高的代码]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-05T09:59:33+08:00</updated>
	  <published>2010-05-05T09:59:33+08:00</published>
		  <summary type="html"><![CDATA[<h2>&ldquo;大道至简，返璞归真&quot;</h2>
<p>在看到<a href="http://www.nczonline.net/" target="_blank">Nicholas C. Zakas</a>提出的<strong>可维护性的代码</strong>的观点后，这种感觉越发的强烈！</p>
<p>原文出处：</p>
<p><a href="http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/" target="_blank">http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/</a></p>
<h3>可维护的Javascript代码</h3>
<p>当我们在开发WEB程序时，如何保证代码的可维护性？很简单，<strong>不要修改不是自己定义的对象</strong>。</p>
<h3>为什么不可以去修改不属于自己定义的对象？</h3>
<p>当我们去修改一个已有的并非我们自己定义的对象时，将发生多么糟糕的事情：</p>
<ul>
    <li><strong>不可信任，导致混乱</strong><br />
    <br />
    这样的修改不可信任，很有可能之前使用过此对象的地方发生BUG<br />
    &nbsp;</li>
    <li><strong>不兼容</strong><br />
    <br />
    在修改这些对象时，我们很可能会将一些新的方法添加进去，而没有考虑到这个对象很可能被应用在并没有实现这些方法的环境中<br />
    &nbsp;</li>
    <li><strong>维护的梦魇</strong><br />
    <br />
    试想，当这种情形发生在一个大项目，大团队中，对成员间开发的代码维护将会是件多么恐怖的事情。</li>
</ul>
<h3>在WEB开发中，怎样的代码才是可维护性高的代码？</h3>
<p>有一段代码，<strong>当浏览器发生改变时，它并不需要作出任何修改</strong>，这就是可维护性高的代码！</p>
<p>在WEB开发中，这不仅适用于Javascript，同样适用于Css!</p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=297" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=297</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[Ajax History 实现分析]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-04T15:45:32+08:00</updated>
	  <published>2010-05-04T15:45:32+08:00</published>
		  <summary type="html"><![CDATA[<p>最近研究了一下Ajax History的实现，目前多数的实现是用一个Timer去定时check浏览器的hash是否改变，还有一些兼容性不强的unInterval的实现。</p>
<h3>IE：</h3>
<ul>
    <li>链接到一个锚点，如果该锚点在当前页未被定义，则不能产生history</li>
    <li>页面中的iframe，如果改变其hash，href，或重新写入新的HTML内容，都会产生history</li>
    <li>对iframe产生的history进行&ldquo;向前&rdquo;，&ldquo;向后&rdquo;操作时，页面地址栏的值不会改变</li>
    <li>iframe中使用hash change的方式，在操作历史记录时会相应回滚，可以以此作为历史记录改变的触发事件</li>
    <li>页面hash的改变，无法通过location.hash获取</li>
</ul>
<h3>其他浏览器：</h3>
<ul>
    <li>链接到一个锚点，如果该锚点在当前页未被定义，也能产生history</li>
    <li>页面hash的改变，可以通过location.hash获取</li>
    <li>iframe中使用hash change的方式，在操作历史记录时不会相应回滚，没办法以此作为历史记录改变的触发事件</li>
</ul>
<h3>实现方案：</h3>
<ul>
    <li>定时检测hash的变化</li>
</ul>
<p><a target="_blank" href="http://www.easyui.org.cn/ajaxHistory.html">ajax history demo: http://www.easyui.org.cn/ajaxHistory.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=296" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=296</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[hasLayout in Microsoft Internet Explorer]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-04-26T15:36:45+08:00</updated>
	  <published>2010-04-26T15:36:45+08:00</published>
		  <summary type="html"><![CDATA[<h1>hasLayout Property</h1>
<hr size="1" />
<p>Retrieves a value that indicates whether the <span replace="1">object</span>   has layout.</p>
<p class="clsRef">Syntax</p>
<blockquote>
<table class="clsStd">
    <tbody>
        <tr>
            <th><b>HTML</b></th>
            <td>N/A</td>
        </tr>
        <tr>
            <th><b>Scripting</b></th>
            <td>[ <span class="clsRange">sHasLayout</span><b> =</b> ] <i><span class="moreinfo" title="an element from the Applies To list below">object</span></i>.<b>currentStyle.hasLayout</b></td>
        </tr>
    </tbody>
</table>
</blockquote>
<p class="clsRef">Possible Values</p>
<blockquote>
<table class="clsStd">
    <tbody>
        <tr>
            <td><span class="clsRange">sHasLayout</span></td>
            <td><b>Boolean</b> that receives one of the following  values.
            <table class="clsStd">
                <tbody>
                    <tr>
                        <td nowrap="nowrap"><span class="clsDefValue">false</span></td>
                        <td>Default. Object does not have layout.</td>
                    </tr>
                    <tr>
                        <td nowrap="nowrap"><span class="clsLiteral">true</span></td>
                        <td>Object has layout.</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>The property is read-only. The property has a default value of <span class="clsDefValue">false</span>. The Microsoft Cascading Style Sheets  (CSS)  extension is not inherited.</p>
</blockquote>
<p class="clsRef">Remarks</p>
<blockquote>
<p>The following table shows Cascading Style Sheets (CSS) properties and   corresponding values that, if set, cause an element to have layout.
<table class="clsStd">
    <tbody>
        <tr>
            <th>CSS property</th>
            <th>Value</th>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/display.html">display</a></td>
            <td><span class="clsLiteral">inline-block</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/height_0.html">height</a></td>
            <td>any value</td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/float.html">float</a></td>
            <td><span class="clsLiteral">left</span> or <span class="clsLiteral">right</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/position.html">position</a></td>
            <td><span class="clsLiteral">absolute</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/width_0.html">width</a></td>
            <td>any value</td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/writingmode.html">writing-mode</a></td>
            <td><span class="clsLiteral">tb-rl</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/zoom.html">zoom</a></td>
            <td>any value</td>
        </tr>
    </tbody>
</table>
</p>
<p>As of Microsoft&reg; Internet Explorer 6, when the <a href="http://www.v-ec.com/dh20156/../objects/doctype.html">!DOCTYPE</a> declaration  specifies strict  standards compliance, inline elements will ignore the <b>width</b>  and  <b>height</b> properties, and setting the <b>width</b> and <b>height</b>   properties will not cause the element to have layout.</p>
<p>Setting the <a href="http://www.v-ec.com/dh20156/../properties/contenteditable.html">contentEditable</a>   property to <span class="clsLiteral">true</span> will cause an element  to have  layout.</p>
<p><strong>BODY</strong>, <strong>FIELDSET</strong>, <strong>IMG</strong>,  <strong>INPUT</strong>,  <strong>TABLE</strong> and <strong>TD</strong>  elements always have layout.</p>
<p>&nbsp;</p>
</blockquote>
<p><strong>当hasLayout为false的元素中包含了hasLayout为true的元素时，该子元素在应 用position类型的样式时将会遇到兼容问题。</strong></p>
<p>&nbsp;</p>
<p><strong>当 hasLayout为false的元素应用position类型的样式时，将会遇到兼容问题。</strong></p>
<p>&nbsp;</p>
<p>See  also:</p>
<p><a href="http://blog.doyoe.com/article.asp?id=165" target="_blank"><strong>background与 border的恩怨情仇</strong></a></p>
<p><a href="http://www.jslab.org.cn/?tag=hasLayoutBug" target="_blank"><strong>http://www.jslab.org.cn/?tag=hasLayoutBug</strong></a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=295" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=295</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[重温High Performance Web Sites]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-04-22T14:36:39+08:00</updated>
	  <published>2010-04-22T14:36:39+08:00</published>
		  <summary type="html"><![CDATA[<h2>High Performance Web Sites - yahoo14条</h2>
<p><strong>由谁提出的</strong><br />
&nbsp;&nbsp;&nbsp;  来自Yahoo! Exceptional Performance team<br />
<br />
<strong>什么时候开始发起的</strong><br />
&nbsp;&nbsp;&nbsp;  2004年开始研究，2007年4月开始，陆续发布,(5月,7月,9月)<br />
<br />
<strong>为什么</strong><br />
&nbsp;&nbsp;&nbsp;  Yahoo希望对自己的产品性能做出一些测量和改善<br />
<br />
<strong>成绩</strong><br />
&nbsp;&nbsp;&nbsp;  总结出14条提升WEB产品性能的准则（后续21条）</p>
<p>&nbsp;</p>
<h3>第一条：最小化HTTP请求(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  将CSS文件和JS文件合并（可行性不高）<br />
&nbsp;&nbsp;&nbsp; CSS Sprites<br />
&nbsp;&nbsp;&nbsp; Image  Maps(很久以前经常使用的&ldquo;热区&rdquo;)<br />
&nbsp;&nbsp;&nbsp; Inline Images,data:URL（浏览器兼容问题）<br />
<br />
&nbsp;&nbsp;&nbsp;  每天大概有40-60%的访问者去到我们的站点的时候都是empty cache，所以，<br />
&nbsp;&nbsp;&nbsp;  我们如果能够使得他们在第一次访问时速度更快，那对他们来说将获得很好的体验。</p>
<p>&nbsp;</p>
<h3>第二条：使用内容分发网络 (Server)</h3>
<p>&nbsp;&nbsp;&nbsp; 将静态文件分发到其他独立的服务器上。<br />
&nbsp;&nbsp;&nbsp;  目的：使得用户可以就近获取到静态文件，从而解决动态内容站点网络拥挤的状况，提高用户访问网站的响应速度。<br />
&nbsp;&nbsp;&nbsp; Performance  Golden Rule:<br />
&nbsp;&nbsp;&nbsp; 80-90%的用户响应时间都花费在了下载某个页面上的组件上，<br />
&nbsp;&nbsp;&nbsp;  如：images,stylesheets,scripts,flash等等，而这些文件都是静态的，完全可以分发出去。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;  CDN很昂贵，可以租用，也可以退而求其次，采用部署多台Server进行反向代理</p>
<p>&nbsp;</p>
<h3>第三条：设置一个 Expires头(Server)</h3>
<p>&nbsp;&nbsp;&nbsp; 静态文件：永不过期<br />
&nbsp;&nbsp;&nbsp;  动态文件：适当设置&quot;Cache-Control&quot;头<br />
<br />
&nbsp;&nbsp;&nbsp;  现在的WEB页面设计越来越丰富，这也意味着页面上会有越来越多的script,stylesheets,images,flash等等<br />
&nbsp;&nbsp;&nbsp;  用户在第一次访问我们的站点时，会发出若干请求，但再次访问时或者继续访问其他页面时，<br />
&nbsp;&nbsp;&nbsp;  如果这些文件设置了Expires头，就可以避免再次为它们发出新的HTTP请求，<br />
&nbsp;&nbsp;&nbsp;  从而提高页面加载速度，减轻服务器压力，提升用户体验。</p>
<p>&nbsp;</p>
<h3>第四条：Gzip压缩静态文件(Server)</h3>
<p>&nbsp;&nbsp;&nbsp;  为所有静态文件开启GZip<br />
&nbsp;&nbsp;&nbsp; 压缩文件，节约带宽，提高下载速度</p>
<h3>第五条：将样式表放置在源文件的顶部 (Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp; 将所有样式文件放置在接近源文件顶部的&lt;head&gt;标签内<br />
<br />
&nbsp;&nbsp;&nbsp;  页面按加载进度逐步渲染，给予访问者视觉上的反馈，尤其是内容较大，网速较慢的访问者，尤为明显。</p>
<p>&nbsp;</p>
<h3>第六 条：将Script脚本放置在源文件底部(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  在第二条中提到浏览器在同一主机上平行下载的进程是有限制的，HTTP/1.1规范中指定的是两个。<br />
&nbsp;&nbsp;&nbsp;  如果在页面下载进程中遇到了Scripts的下载，则它会将这种平行下载阻断，导致页面加载更慢。</p>
<p>&nbsp;</p>
<h3>第七 条：避免使用CSS表达式(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp; 不兼容<br />
&nbsp;&nbsp;&nbsp;  监听评估导致页面性能低下，移动一次鼠标可能导致超过10,000次的评估。<br />
<br />
第八条：将JavaScript和CSS全部放置到外部文件 进行调用(Frontend)<br />
&nbsp;&nbsp;&nbsp; 减小主文件大小，加快page加载速度<br />
&nbsp;&nbsp;&nbsp; 对XHTML进行兼容<br />
&nbsp;&nbsp;&nbsp;  可作为静态文件分发到CDN<br />
&nbsp;&nbsp;&nbsp; 可缓存<br />
&nbsp;&nbsp;&nbsp; 可共用</p>
<p>&nbsp;</p>
<h3>第九条：减少DNS查询 （Frontend）</h3>
<p>&nbsp;&nbsp;&nbsp; Domain Name System，域名系统，它将主机映射到某个IP地址。<br />
&nbsp;&nbsp;&nbsp;  当我们输入一个网址的时候，DNS会分析该网址，然后转换到具体的IP，这个过程大概会花20-120毫秒<br />
&nbsp;&nbsp;&nbsp;  显然，如果DNS的查找能够进行缓存，将会提高站点的访问速度。<br />
&nbsp;&nbsp;&nbsp;  当我们访问一个页面时，该页的URL，images,script,stylesheet,flash等等都会有一个DNS查询的过程<br />
&nbsp;&nbsp;&nbsp;  如果我们能够减少该页面上出现多个不同的主机地址，就可以减少DNS的查询<br />
&nbsp;&nbsp;&nbsp;  这样就会和之前讲到的平行下载有冲突，减少DNS查询会减少页面响应时间，<br />
&nbsp;&nbsp;&nbsp; 但是降低了平行下载数量，则会增大页面响应时间，<br />
&nbsp;&nbsp;&nbsp;  平衡的做法是，将所有静态文件分离到至少1个独立的主机，最多不超过4个。</p>
<p>&nbsp;</p>
<h3>第十条：最小化 JavaScript和CSS</h3>
<p>&nbsp;&nbsp;&nbsp; 将JavaScript和CSS中任何多余的字符移除，如：注释，换行，排版用的空格等等<br />
&nbsp;&nbsp;&nbsp;  减少文件大小，加速下载进度。</p>
<p>&nbsp;</p>
<h3>第十一条：避免重定向(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  重定向将导致用户响应时间增加<br />
&nbsp;&nbsp;&nbsp; 使用具体的URL<br />
&nbsp;&nbsp;&nbsp; 如果一定要重定向，可使用标准的3xx HTTP状态码</p>
<p>&nbsp;</p>
<h3>第 十二条：移除重复的脚本</h3>
<p>&nbsp;&nbsp;&nbsp; 使用外部脚本文件<br />
&nbsp;&nbsp;&nbsp; 引入这些脚本文件时给文件名加上版本号<br />
&nbsp;&nbsp;&nbsp;  &lt;script type=&quot;text/javascript&quot;  src=&quot;menu_1.0.17.js&quot;&gt;&lt;/script&gt;<br />
&nbsp;&nbsp;&nbsp; 养成提取公共方法，公共类的习惯<br />
&nbsp;&nbsp;&nbsp;  在编码的过程中，如果发现某段代码至少有两个地方用到，而且代码量挺大的，<br />
&nbsp;&nbsp;&nbsp;  就可以考虑将这部分代码提取成为公共的方法，在编写CSS的时候同样适用。</p>
<p>&nbsp;</p>
<h3>第十三条：配置ETag</h3>
<p>&nbsp;&nbsp;&nbsp;  ETag，Entity tags的简称，<br />
&nbsp;&nbsp;&nbsp;  它用来确定在浏览器向服务端请求一个组件时判断缓存的组件与服务器上的是否仍然还是同一份（即没有更改过）。<br />
&nbsp;&nbsp;&nbsp;  Entity，其实就是&ldquo;组件&rdquo;的另一种说法，也就是images,scripts,stylesheets等等这些东西。&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;  ETag的值由 INode（索引节点）, Size和MTime（最后修改时间）决定。<br />
&nbsp;&nbsp;&nbsp;  由于这个INode在不同的服务器上是不同的，所以导致同一个组件会有不同的ETag，<br />
&nbsp;&nbsp;&nbsp;  这就使得该组件不能发送304的状态，没有办法被用户缓存<br />
&nbsp;&nbsp;&nbsp; 由于这个原因，在大型多服务器的站点，一般建议将ETag配置关闭<br />
&nbsp;&nbsp;&nbsp;  如果可以保证各服务器对同一组件生成相同的ETag，则完全可以使用。</p>
<h3>第十四条：缓存AJAX请求</h3>
<p>&nbsp;&nbsp;&nbsp;  根据业务类型，为处理AJAX请求的Action文件的设置合适的到期时间<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;  动态更新AJAX请求的URL，如，给这个URL后面加上一个更新时间，如：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;  &amp;t=1190241612，只在请求的数据发生变化时动态修改该URL地址。</p>
<p>后续二十一条下次再过一遍! ^_^</p>
<p>&nbsp;</p>
<p><a target="_blank" href="http://www.w3cgroup.com/attachments/month_1004/High Performance Websites.ppt">High Performance Web Sites.ppt</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=294" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=294</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[ECMA262深入浅出]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-04-11T13:02:21+08:00</updated>
	  <published>2010-04-11T13:02:21+08:00</published>
		  <summary type="html"><![CDATA[<div>
<h2>ECMA262深入浅出</h2>
<h3>ECMA-262简述</h3>
<h3>ECMAScript语言概述</h3>
<h3>ECMAScript对象概述(原型链Prototype Chain)</h3>
<h3>ECMA-262主要术语</h3>
<h3>ECMAScript执行环境(作用域链Scope Chain，闭包机制)</h3>
<h3>ECMAScript函数(new原理)</h3>
<h3>ECMAScript内部属性(参考)</h3>
<h3>ECMAScript执行环境作用域链图示</h3>
<h3>ECMA-262参考资料</h3>
</div>
<div>&nbsp;</div>
<div><strong>ECMA-262简述</strong></div>
<div>&nbsp;</div>
<div>ECMA(European Computer Manufacturers Association)</div>
<div>&nbsp;</div>
<div>ECMA-262标准的最初的版本是基于Brendan Eich创造的JavaScript语言来制定的，它是ECMAScript脚本语言的规范及标准。该标准在1998年4 月通过快速通道提交到ISO/IEC JTC 1并被采纳为国际标准ISO/IEC 16262，所以之后一直简称为ECMA-262，该标准发展到现在已经到了第5版。 <br />
<br />
<br />
所有遵循ECMA-262标准实现的脚本都可以称之为ECMAScript，如JavaScript, JScript, ActionScript等等。</div>
<div>&nbsp;</div>
<div>注意：ECMA-262是从ECMAScript脚本引擎实现的角度去描述的。</div>
<div>&nbsp;</div>
<div>我们目前所使用的大部分浏览器中的脚本引擎多数都是基于ECMA-262标准第3版的实现，参见下图：</div>
<div>&nbsp;</div>
<div>&nbsp;<img alt="ECMA262 3rd edition实现引擎列表" src="http://www.w3cgroup.com/attachments/month_1004/62010411125812.png" /></div>
<div>&nbsp;</div>
<div><strong>ECMAScript语言概述</strong></div>
<div>&nbsp;</div>
<div>ECMAScript最初的设计是一种网页脚本语言。<br />
<br />
&nbsp;</div>
<div>脚本语言是一种编程语言，可用来操作、自定义、自动化现有系统中的设备。</div>
<div>在某些系统中，一些可用的功能是可以通过用户接口来使用的。而脚本语言，就是将这些功能暴露给编程人员进行控制的机制。这样的系统，我们可以说，它们为我们提供了一个运行脚本语言的宿主环境。脚本语言是专门给专业和非专业的编程人员使用的，为了适应非专业的程序员，有些方面多少有些不太严格。<br />
<br />
脚本语言与宿主环境是两个不同的主体，比如，浏览器就为ECMAScript提供了一个宿主环境，BOM和DOM则都是浏览器提供的功能，而各种基于ECMA262实现的脚本语言，如JavaScript,Jscript等，都可以为我们提供对BOM和DOM的操作方法。因为宿主环境的不同，它们提供的功能也不尽相同，这也是我们知道的，不同的浏览器中会有不同的BOM和DOM的属性和方法。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>ECMAScript是基于对象(object-based)的编程语言，在宿主环境中执行计算或操作对象。ECMAScript程序就是一个对象间交互通信的聚合。&nbsp;在ECMAScript中，&ldquo;对象&rdquo;(object)的properties是一个无序的集合，properties 是一个容器，可以包含其他的对象，原始值(primitive&nbsp;values)或方法(methods)。<br />
<br />
原始值属于下列&ldquo;内置类型&rdquo;(built-in types)中的一员：Undefined, Null, Boolean, Number和String,&ldquo;对象 &rdquo;则是内置类型：Object,&ldquo;方法&rdquo;是一个透过property关联到对象的函数。<br />
<br />
&nbsp;</div>
<div>ECMAScript定义了&ldquo;内置对象&rdquo;(built-in objects)，以使ECMAScript实体更为完善。这些内置对象包括：Global对象，Object对象， Function对象，Array对象，String对象，Boolean对象，Number对象，Math对象，Date对象， RegExp对象和错误对象： Error,EvalError,RangeError,ReferenceError,SyntaxError,TypeError,URIError。<br />
<br />
&nbsp;</div>
<div>ECMAScript还定义了&ldquo;内置操作符&rdquo;或者说是&ldquo;函数&rdquo;或&ldquo;方法&rdquo;。ECMAScript操作符包括了各种一元运算符、乘除运算符、加减法运算符、位移运算符、关系运算符、相等运算符、二元运算符、二元逻辑运算符、分配运算符和逗号运算符。<br />
<br />
&nbsp;</div>
<div>ECMAScript的语法类似Java的语法。ECMAScript语法宽松是为了使它能够成为更容易使用的脚本语言。比如，变量不需要申明类型也不需要为properties指定类型，函数定义也可以不需要出现在它们的调用语句之前。</div>
<div>&nbsp;</div>
<div><strong>ECMAScript对象概述</strong></div>
<div>&nbsp;</div>
<div>ECMAScript没有像C++，Smalltalk，Java等语言中的真正的类，但是它支持构造器(constructors)。它在代码执行时创建对象，为对象分配内存并初始化它们全部或部分初始值和properties。所有的构造器都是对象，但不是所有对象都是构造器。每个构造器都有一个Prototype属性用于实现基于原型的继承(prototype-based inheritance)和属性共享(shared properties)。</div>
<div>&nbsp;</div>
<div>对象在对构造器使用new表达式时被创建，比如，new String(&ldquo;A String&rdquo;)创建了一个新的字符串对象。不用new表达式直接去调用一个构造器，其结果将依赖于这个构造器的具体实现，如，String(&quot;A String&quot;) 产生一个原始值String，而不是一个对象。<br />
<br />
&nbsp;</div>
<div>ECMAScript支持基于原型的继承。所有构造器都有一个相关联的原型，所有由构造器创建的对象都隐含一个指向到该原型的引用（称为对象原型），此外，一个原型可能有一个非空的、隐含的引用，指向到它的原型，所以，这又被称为是：原型链(prototype chain)</div>
<div>&nbsp;</div>
<div><img alt="ECMAScript Prototype Chain原型链" src="http://www.w3cgroup.com/attachments/month_1004/a2010411125916.png" /></div>
<div>&nbsp;</div>
<div>当一个引用来自一个对象时，它会去该对象和它的原型(链)中查找与该property同名的属性，换句话说，会先直接从该对象中检测是否存在这个同名的引用，如果有则返回，否则再从该对象的原型(链)中去检测是否存在该引用。(DEMO)</div>
<div>&nbsp;</div>
<div>DEMO:</div>
<div>&lt;script type=&quot;text/javascript&quot;&gt;</div>
<div>Object.prototype.hi = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert('object.prototype.hi');</span></div>
<div>};</div>
<div>Object.prototype.greetings = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert('object.prototype.greetings');</span></div>
<div>};</div>
<div>&nbsp;</div>
<div>Function.prototype.greetings = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert('function.prototype.greetings');</span></div>
<div>};</div>
<div>&nbsp;</div>
<div>var CF = function(){};</div>
<div>CF.prototype.hello = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert('CF.prototype.hello');</span></div>
<div>};</div>
<div>CF.prototype.bye = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert('CF.prototype.bye');</span></div>
<div>};</div>
<div>&nbsp;</div>
<div>var o = new CF();</div>
<div>o.hello = function(){alert('o.hello');};</div>
<div>&nbsp;</div>
<div>o.hello();</div>
<div>o.bye();</div>
<div>o.hi();</div>
<div>o.greetings();</div>
<div>&nbsp;</div>
<div>CF.hi();</div>
<div>CF.greetings();</div>
<div>&lt;/script&gt;</div>
<div>&nbsp;</div>
<div><br />
在基于类的面向对象语言里,通常,状态由实例持有，方法由类持有，继承只有结构和行为。在ECMAScript中，状态和方法由对象持有，结构、行为和状态都可以被继承。</div>
<div>&nbsp;<br />
对象通常都不会直接包含那些由原型包含共享的属性和值。描述见下图：</div>
<div>&nbsp;</div>
<div>&nbsp;<img alt="ECMAScript prototype原型" src="http://www.w3cgroup.com/attachments/month_1004/82010411125948.png" /></div>
<div>&nbsp;</div>
<div>CF是一个构造函数（同时也是一个对象）。通过对它进行new表达式创建了5个实例对象：cf1,cf2,cf3,cf4,cf5。每个实例对象都包含有q1 和q2两个属性。(DEMO)<br />
<br />
例如，Cfp是cf3的原型(虚线，表示隐含的原型关系)，构造函数CF自己有两个属性P1和P2，它们对 Cfp,cf1,cf2,cf3,cf4,cf5都不可见。Cfp的属性CFP1对cf1,cf2,cf3,cf4,cf5可见（但不包括CF），还有那些在Cfp的隐含的原型链中找到的 property name(非q1,q2或者CFP1的其他属性)。注意，CF和Cfp之间并非隐含的原型联系。</div>
<div>与基于类的对象语言不同，ECMAScript对象的属性可以通过给对象赋值的方式动态地添加到对象上，意思就是，构造函数不需要一个个地为那些由它构造出的对象赋值，如上图，只要为CFp添加一个属性值,即可使得由CF构造出的所有对象：cf1,cf2,cf3,cf4,cf5共享。</div>
<div>&nbsp;</div>
<div>DEMO:</div>
<div>&lt;script type=&quot;text/javascript&quot;&gt;</div>
<div>var CF = function(){};</div>
<div>CF.p1 = 'p1';</div>
<div>CF.p2 = 'p2';</div>
<div>&nbsp;</div>
<div>CF.prototype = {CFP1:'cfp1'};</div>
<div>&nbsp;</div>
<div>var cf1 = new CF(),cf2 = new CF(),cf3 = new CF(),cf4 = new CF(),cf5 = new CF();</div>
<div>&nbsp;</div>
<div>alert(cf1.p1+','+cf2.p2);//构造函数自身的属性对由它构造出的对象不可见</div>
<div>&nbsp;</div>
<div>alert(CF.CFP1);//对CF不可见</div>
<div>alert(cf1.CFP1);//对CF构造的所有对象可见</div>
<div>&nbsp;</div>
<div>cf3.__proto__.CFP2 = 'cfp2';//在构造函数原型上添加属性</div>
<div>//__proto__相当于从cf3到CF.prototype的隐含的原型关系，该属性是SpiderMonkey引擎的私有属性，仅限在SpiderMonkey引擎中访问</div>
<div>&nbsp;</div>
<div>alert(cf1.CFP2);//即可对所有该构造函数构造的对象进行共享</div>
<div>&lt;/script&gt;</div>
<div>&nbsp;</div>
<div><strong>ECMA-262主要术语</strong></div>
<div>&nbsp;</div>
<div>以下是ECMAScript中主要术语的非正式定义。</div>
<div>&nbsp;</div>
<div>Type<br />
数据值的集合</div>
<div>Primitive Value<br />
原始值包括Undefined,Null,Boolean,Number,String这些类型成员。原始值是语言实现中底层可以直接表示的数据。</div>
<div>Object<br />
每个对象都是Object类型的成员。它包含的所有属性成员，如原始值、对象或者函数，是一个无序的集合。对象属性成员放置的函数又被称为方法。</div>
<div>Constructor<br />
构造器是一个函数对象，用来创建和初始化对象。每个构造器都有一个关联的原型对象用来实现属性成员的继承和共享。</div>
<div>&nbsp;</div>
<div>Prototype <br />
ECMAScript中的原型用来实现对象结构、状态和行为的继承。当一个构造器构造了一个对象，这个对象会隐含地引用到该构造器关联的原型去解析属性的引用。构造器关联的原型可以通过程序表达式constructor.prototype 来引用。在某个共享对象的原型上添加的属性值，通过继承，可以被所有其他对象共享。</div>
<div>Native Object <br />
原生对象是由ECMAScript的实现提供的，独立于宿主环境。有些原生对像同时又是内置对象，其他的则可能会在执行一个 ECMAScript程序时产生。</div>
<div>Built-in Object <br />
内置对象是由ECMAScript的实现提供的，独立于宿主环境，它们出现在ECMAScript程序开始执行的时候。所有的内置对象都是原生对象。</div>
<div>Host Object<br />
宿主对象由为ECMAScript提供完整执行环境的宿主环境提供的。任何对象，不是原生对象，就是宿主对象。</div>
<div>&nbsp;</div>
<div>Undefined Value<br />
Undefined值是一个原始值，当一个变量没有被分配值的时候使用。</div>
<div>Undefined Type<br />
Undefined类型只有一个值，undefined。</div>
<div>Null Value<br />
Null值是一个原始值，它表示空的，没有的，或不存在的引用。</div>
<div>Null Type<br />
Null类型有一个值，null。</div>
<div>Boolean Value<br />
Boolean值是Boolean类型的成员，它只能是两个值中的一个，true或false。</div>
<div>Boolean Type<br />
Boolean类型表示一个逻辑实体，由两个唯一值组成，一个是true，另一个是false。</div>
<div>&nbsp;</div>
<div>Boolean Object <br />
Boolean对象是Object类型的成员，它是内置对象Boolean的实例。意思是，一个Boolean对象是通过Boolean构造器的 new表 达式创建，提供一个boolean参数。结果对象有一个隐含的（未命名）原型boolean。一个Boolean对象支配一个 Boolean值。</div>
<div>String Value <br />
String值是String类型的成员，它是一个有限的有序的，0到16位无符号整数长度的值。注意：尽管每个值通常都表示一个单独的16位的UTF-16文本的单元，但该语言不会做出任何限制和要求当这个值不是16位无符号整数的情况时。</div>
<div>String Type <br />
String类型是所有字符串值的集合。</div>
<div>String Object <br />
String对象是Object类型的成员，它是内置对象String的实例。</div>
<div>&nbsp;</div>
<div>Number Value <br />
Number值是Number类型的成员，它是一个直接表示的数字。</div>
<div>Number Type <br />
Number类型是表示数字的值的集合。在ECMAScript中，该集合表示IEEE754的64位双精度运算格式的值，包含一个特殊值&quot;Not-a-&nbsp;Number&quot;(NaN)，正无穷大和负无穷大。</div>
<div>Number Object <br />
Number对象是Object类型的成员，它是内置对象Number的实例。</div>
<div>Infinity <br />
原始值Infinity表示一个正无穷大的数字，Number类型成员。</div>
<div>NaN<br />
原始值NaN表示IEEE标准&quot;Not-a-Number&quot;值的集合，Number类型成员。</div>
<div>&nbsp;</div>
<div><strong>ECMAScript执行环境</strong></div>
<div>&nbsp;</div>
<div>什么是执行环境?<br />
<br />
想象一下，假设你就是一个ECMAScript引擎。<br />
<br />
当你接收到一条语句：<br />
<br />
this.x = y;<br />
<br />
你能确定该做什么吗？<br />
<br />
很明显， 我们不知道该做些什么，因为我们既不知道this是什么，也不清楚y是什么。<br />
<br />
所以，如果要正确执行这条语句，我们需要一个上下文，用以确定this和y到底是什么，这个上下文，就是执行环境。</div>
<div>&nbsp;</div>
<div><strong>执行环境</strong></div>
<div><br />
当控制器转到ECMAScript可执行代码时，即会进入到一个执行环境中。活动的执行环境会在逻辑上形成一个堆栈，在这个堆栈的顶端存放的是运行时的执行环境。</div>
<div>&nbsp;</div>
<div><strong>函数对象</strong>(两种类型)<br />
通过在源文件中透过函数声明、函数表达式或内置Function对象来定义的函数对象。<br />
内部函数对象，它们属于内置对象，如parseInt, Math.exp等等。</div>
<div>&nbsp;</div>
<div><strong>可执行代码</strong> (三种ECMAScript可执行代码类型)<br />
Global代码<br />
Eval代码<br />
Function代码</div>
<div>&nbsp;</div>
<div><strong>变量实例</strong></div>
<div><br />
每个执行环境都会与一个&ldquo;变量对象&rdquo;关联。在源文件中定义的的变量和函数都会作为properties添加到该对象中去。例如函数的代码，参数将作为properties添加到该函数执行环境的变量对象中去。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>在进入一个执行环境时，&ldquo;变量对象&rdquo;绑定properties的顺序如下</strong>：(DEMO)</div>
<div><br />
<strong>针对函数代码</strong>：为每一个在参数列表中定义的形参，创建一个同名的标识符作为property添加到&ldquo;变量对象&rdquo;中，其值由调用[[call]]时以参数的形式提供。如果调用者提供的参数值少于形参数量，其他的形参值将为undefined。如果遇到多个同名的形参，最后一个同名形参的值将被保留，如果这最后一个形参也未被提供值，同样会是undefined。</div>
<div><br />
<strong>针对函数声明</strong>：在&ldquo;变量对象&rdquo;中创建一个以它们的名字作为标识符的property，其值为创建后的函数对象。如果&ldquo;变量对象&rdquo;中已经有一个同名的property，则将它替换掉。</div>
<div><br />
<strong>针对变量声明</strong>：在&ldquo;变量对象&rdquo;中创建一个以它们的名字作为标识符的property，其值为undefined，如果之前已有这个property,则其值不变。</div>
<div>&nbsp;</div>
<div>DEMO:</div>
<div>&lt;script type=&quot;text/javascript&quot;&gt;</div>
<div>/*-------------函数代码------------*/</div>
<div>function x(a,a,b){alert(a);alert(b);};</div>
<div>x(1,2,3);</div>
<div>x(1);</div>
<div>/*-------------函数声明------------*/</div>
<div>function a(){alert(1);};</div>
<div>alert(a);</div>
<div>function a(){alert(2)};</div>
<div>alert(a);</div>
<div>/*-------------变量声明------------*/</div>
<div>var b;</div>
<div>alert(b); //其值为undefined</div>
<div>&lt;/script&gt;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>作用域链与标识符查找</strong></div>
<div><br />
所有的执行环境都与一个作用域链(scope chain)相关联。作用域链是一个用来查找标识符的对象列表。当控制器进入到一个执行环境中的时候，作用域链被创建并放置了一个初始的对象集合。在一个执行环境运行的时候，它的作用域链只受with语句和catch子句影响。在执行的时候，标识符查找的方法如下：</div>
<div><br />
1. 获取Scope Chain的下一个对象。如果没有对象了，则转到第5步 <br />
2. 调用Result(1)的[[HasProperty]]方法, 传递Identifier作为参数&nbsp;<br />
3. 如果Result(2)是true, 则返回一个Reference(引用)类型的值，它的base object是Result(1)，而它的property name是Identifier<br />
4. 跳到第1步<br />
5. 返回一个Reference类型，它的base object是null，它的property name是Identifier<br />
<br />
标识符查找的结果通常是一个名字为标识符字符串的引用值。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>全局对象(Global Object)</strong></div>
<div><br />
在控制器进入任何执行环境之前，会创建一个唯一的全局对象，初始化的全局对象包括以下属性：<br />
<br />
<strong>内置对象</strong>，如 Math,String,Date,parseInt等等，它们都是不可枚举的(DontEnum)。<br />
<br />
<strong>宿主属性</strong>，它自己可能会包含一个值为全局对象的属性，比如，在HTML 的DOM中，全局对象中的window属性，就是全局对象自己。<br />
<br />
当控制器进入了执行环境，ECMAScript运行的时候，全局对象可能还会被添加上一些额外的属性，一些之前已有的属性也有可能被改变。</div>
<div>&nbsp;</div>
<div><strong>This</strong></div>
<div><br />
所有活动的执行环境都会有一个this值，它依赖并取决于代码执行时的caller。<br />
<br />
同一个执行环境中的this值是不变的。<br />
&nbsp;</div>
<div>&nbsp;</div>
<div><strong>Arguments对象</strong></div>
<div><br />
当控制器进入到一个函数的执行环境中时，会创建一个arguments对象,初始过程如下：<br />
<br />
arguments对象的内部属性[[prototype]]，是原生对象prototype，初始值是Object.prototype<br />
<br />
创建callee属性，不可枚举(DontEnum)，其值为正在执行的函数对象，这使得匿名函数也可以进行递归。<br />
<br />
创建length属性，不可枚举(DontEnum)，其值为caller提供的实际参数数量。<br />
<br />
按少于length的正整数数量创建ToString(arg)属性，不可枚举(DontEnum)，第一个实际参数值对应为arg = 0，第二个对应为arg = 1，依此类推。当实际参数少于形参时，该属性会在活动对象中相应地共享它的值。意思就是说，改变此属性将改变活动对象中的属性值，反之亦然。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>进入一个执行环境时发生的那些事儿</strong></div>
<div><br />
每次调用函数或构造器都会进入一个新的执行环境，即使在一个函数递归地调用自己的时候亦是如此。每次return，都会退出这个执行环境。一个未捕捉的异常也可能退出一个或多个执行环境。<br />
<br />
当控制器进入到一个执行环境中时，作用域链即被创建和初始化，变量实例化也开始进行，this值也被确定下来。</div>
<div>&nbsp;</div>
<div><strong>Global代码</strong><br />
<br />
作用域链创建并初始，仅包含global对象。<br />
<br />
变量实例化进行的时候以global对象作为变量对象，属性为不可删除(DontDelete) 。<br />
<br />
This值为global对象。</div>
<div><br />
<strong>Eval代码</strong><br />
<br />
当控制器进入到eval代码的执行环境中时，先前活动的执行环境，引用到调用环境*，用来决定作用域链，变量对象和this值。如果没有调用环境，则所有这些都以全局代码形式进行处理。<br />
<br />
作用域链初始化时包含一个与调用环境相同的对象，并保持相同的顺序。这包含了通过with语句和catch子句添加到调用环境作用域链上的对象。<br />
<br />
变量实例化时使用调用环境下的变量对象。<br />
<br />
This值与调用环境下的this值一致。<br />
<br />
* 调用函数语句执行时的execution context就是calling context</div>
<div><br />
<strong>Function代码</strong><br />
<br />
作用域链初始化时先添加活动对象，然后再添加该函数对象[[Scope]]属性中存储的其他对象。* 闭包机制<br />
<br />
变量实例化执行时使用活动对象作为变量对象，属性为不可删除(DontDelete)。<br />
<br />
This的值为Caller，如果caller不是对象(或者是null)，则this值为global对象。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>With语句</strong><br />
<br />
with语句会在当前执行环境中的作用域链顶端添加一个计算对象，在这个扩展的作用域链执行完语句之后，随机复原之前的作用域链。<br />
<br />
With(表达式)语句的执行过程如下：<br />
<br />
1.评估表达式<br />
2.调用GetValue(Result(1))<br />
3.调用ToObject(Result(2))<br />
4.将Result(3)添加到 作用域链的顶端<br />
5.用第4步扩展的作用域链来评估语句<br />
6.使C=Result(5)，如果在第5步时有异常抛出，则C=(throw,V,empty)，V是这个异常（执行现在当作没有异常抛出继续进行）<br />
7.在作用域链中移除Result(3)<br />
8.返回C<br />
<br />
注意：当控制器离开该&ldquo;嵌入&rdquo;的语句时，无论是正常还是异常，作用域链都将被恢复。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>Catch子句</strong><br />
<br />
catch(标识符)块的执行过程如下：<br />
<br />
1.使C为通过catch传递进来的参数<br />
2.像new Object()一样创建一个新的对象<br />
3.在Result(2) 的那个对象上创建一个property，名字是标识符，值是C，不可删除<br />
4.将Result(2)添加到作用域链的顶端<br />
5.评估这个块语句<br />
6.将Result(2) 从作用域链中移除<br />
7.返回Result(5)</div>
<div>&nbsp;</div>
<div><strong>函数声明</strong><br />
<br />
function Identifier(FormalParameterList opt){FunctionBody}<br />
<br />
函数声明的解析过程如下：<br />
<br />
1.创建一个new Function对象， FormalParameterList指定参数，FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。<br />
<br />
2.为当前的变量对象 创建一个名为Identifier的属性，值为Result(1)。</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>匿名函数表达式</strong><br />
<br />
function(FormalParameterList opt){FunctionBody}<br />
<br />
匿名函数表达式的解析过程如下：<br />
<br />
1.创建一个new Function对象， FormalParameterList指定参数，FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。<br />
<br />
2.返回Result(1)。</div>
<div>&nbsp;</div>
<div><strong>具名函数表达式</strong><br />
<br />
function Identifier(FormalParameterList opt){FunctionBody}<br />
<br />
具名函数表达式的解析过程如下：<br />
<br />
1.创建一个new&nbsp;Object对象<br />
2.将Result(1)添加到作用域链的顶端<br />
3.创建一个new Function对象，FormalParameterList指定参数，FunctionBody指定函数体。将当前正在运行的执行环境中的作用域链作为它的作用域。<br />
4.为Result(1)创建一个名为Identifier的属性，其值为Result(3)，只读，不可删除<br />
5.从作用域链中移除Result(1)<br />
6.返回Result(3)</div>
<div>&nbsp;</div>
<div><strong>创建函数对象</strong><br />
<br />
函数对象构造过程如下：<br />
<br />
<span style="color: #c0c0c0">1.如果已有对象E，它已有FunctionBody，且与现在给到的FunctionBody相等，则跳转到第13步<br />
</span>2. 创建一个新的ECMAScript native对象F<br />
3.设置F的[[Class]]为&ldquo;Function&rdquo;<br />
4.设置F的[[Prototype]]为原始的Function prototype对象<br />
5.设 置F的[[Call]](参见之后的Slide)<br />
6.设置F的[[Construct]]（参见之后的Slide）<br />
7.设置F的[[Scope]]为一个新的作用域链，它和当前作用域包含相同的对象<br />
8.设置F的lengeh属性值为形参数量，如果未定义参数，则为0。9.以new Object()表达式方式创建一个新的对象<br />
10.设置F的 constructor属性值为Result(9)<br />
11.设置F的prototype属性值为Result(9)<br />
12.返回F<br />
<span style="color: #c0c0c0">13.酌情（由实现者决定）跳转到第2步或第14步<br />
14.创建 一个新的ECMAScript native对象F，连接到 E，复制所有E和F的非内部属性*以使得它们与E和F的保持一致。<br />
15.设置F的[[Class]]属性值为&ldquo; Function&rdquo;<br />
16.设置F的[[Prototype]]属性值为原始的Function prototype对象<br />
17.设置F的[[Call]]属性<br />
18.设置F的[[Construct]]属性<br />
19. 设置F的[[Scope]]属性值为一个新的作用域链，它和当前作用域包含相同的对象<br />
20.返回F<br />
</span><br />
* 内部属性指的是所有以[[]]书写的属性</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>创建函数对象</strong><br />
<br />
注意：<br />
<br />
每个function都会自动创建一个prototype属性，以使得它们可以当作构造器来使用。<br />
<br />
<span style="color: #c0c0c0">第1步，使得类似函数A中嵌套了一个不依赖于A的函数B的这种情况进行优化。在这种情形的实现中，允许在A每次被调用的时候，重用B这个对象。<br />
<br />
第13步决定是否执行此 优化。如果在某个实现中选择不，则会跳转到第2步。</span></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>创建函数对象</strong><br />
<br />
连接对象(很多引擎都未去做这个实现) <br />
<br />
<span style="color: #c0c0c0">当两个或更多的Function对象连接时，它们具有如下特殊的行为：<br />
<br />
1.任何时候，对 象O创建或设置一个非内部属性时，通信机制会立即在其他所有与O连接的对象上做相同的操作。<br />
<br />
2.任何时候，对象O删除一个非内部属性，&nbsp;通信机制会立即在其他所有与O连接的对象上做相同的操作。<br />
<br />
3.如果对象O与P相连，它们可以通过==和===来进行比较。<br />
<br />
4.当对象O与P相连 ，且对象P与Q相连，则O与Q也会自动相连。<br />
<br />
注意：相连的对象除了它们各自不同的内部属性外，是很难进行区别的。而这些内部属性可能也只有[[Scope]]会不同。</span></div>
<div>&nbsp;</div>
<div><strong>调用函数对象</strong><br />
<br />
[[Call]]<br />
<br />
当函数对象F调用了[[Call]]属性，将执行以下步骤：<br />
<br />
1.将F的形参表、传递的参数列表，和this植入到一个新的执行环境<br />
<br />
2.评估F的FunctionBody<br />
<br />
3.退出在第1步植入的执行环境，恢复之前的执行环境<br />
<br />
4.如果Result(2).type是 throw,抛出Result (2).value<br />
<br />
5.如果Result(2).type是return，返回Result(2).value<br />
<br />
6.Result(2).type默认情况下，返回undefined</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>new操作原理</strong><br />
<br />
[[Construct]]<br />
<br />
当函数对象F调用了[[Construct]]属性，将执行以下步骤：<br />
<br />
1.创建一个新的ECMAScript native对象<br />
2.将 Result(1)的[[Class]]属性值设为&ldquo;Object&rdquo;<br />
3.取得F的prototype属性值<br />
4.如果Result(3)是一个对象，将Result(1)的[[Prototype]]属性值设置为Result(3)<br />
5.如果Result(3)不是一个对象，将Result(1)的[[Prototype]]属性值设置为原始的Object prototype对象<br />
6.调用F的 [[Call]]属性，将Result(1)设置为this值，将[[Construct]]传递的参数当作参数列表<br />
7.如果Type(Result(6))是一个对象，返回Result(6) <br />
8.返回Result(1)</div>
<div>&nbsp;</div>
<div>DEMO:</div>
<div>&lt;script type=&quot;text/javascript&quot;&gt;</div>
<div>/*new操作原理（spiderMonkey引擎下测试）*/</div>
<div>&nbsp;</div>
<div>var a = function(sA,sH){</div>
<div><span>&nbsp;&nbsp;&nbsp; var x = &quot;x&quot;;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; this.a = sA;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; this.h = sH;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; this.say = function(){alert(this.a+','+x)}</span></div>
<div>}</div>
<div>a.prototype.hi = function(){alert(this.h)}</div>
<div>&nbsp;</div>
<div>var createInstance = function(source){</div>
<div><span>&nbsp;&nbsp;&nbsp; var p = {}</span></div>
<div><span>&nbsp;&nbsp;&nbsp; var args = Array.prototype.slice.call(arguments,1);</span></div>
<div><span>&nbsp;&nbsp;&nbsp; p.__proto__ = source.prototype;</span></div>
<div><span>&nbsp;&nbsp;&nbsp; source.apply(p,args);</span></div>
<div><span>&nbsp;&nbsp;&nbsp; return p;</span></div>
<div>}</div>
<div>&nbsp;</div>
<div>var A = createInstance(a,&quot;A&quot;,&quot;hi A&quot;);</div>
<div>A.say();</div>
<div>A.hi();</div>
<div>&lt;/script&gt;</div>
<div>&nbsp;</div>
<div><strong>ECMAScript内部属性</strong></div>
<div>&nbsp;</div>
<div>[[Prototype]]<br />
This对象的原型，该属性值只会是一个object或null，所有的[[Prototype]] chain最终都都会通向到null。</div>
<div>[[Class]]<br />
指明This对象类别的字符串值</div>
<div>[[Value]]<br />
与This对象关联的内部状态信息</div>
<div>[[Get]](PropertyName)<br />
返回指定属性的值</div>
<div>[[Put]](PropertyName Value)<br />
设置指定的属性值</div>
<div>[[CanPut]](PropertyName)<br />
返回是否可以执行[[Put]]指定属性的操作的Boolean值</div>
<div>[[HasProperty]](PropertyName)<br />
返回对象是否存在指定的属性名的Boolean值</div>
<div>[[Delete]](PropertyName)<br />
移除对象指定的属性</div>
<div>[[DefaultValue]](Hint)<br />
返回对象的默认值，只能是原始值，不允许对象和引用。</div>
<div>[[Construct]] a list of argument values provied by the caller<br />
通过调用new操作符构造一个对象。</div>
<div>[[Call]] a list of argument values provied by the caller<br />
通过函数调用表达式执行与对象关联的代码。</div>
<div>[[HasInstance]](Value)<br />
返回一个Boolean值，表示This对象是否存在指定的委派（实例），仅对ECMAScript native中的Function对象实现。</div>
<div>[[Scope]] <br />
作用域链，用于表示一个函数对象执行时的环境。</div>
<div>[[Match]](String,Index)<br />
为正则表达式匹配和返回一个MatchResult的值。</div>
<div>&nbsp;</div>
<div><strong>ECMAScript Execution Context and Scope Chain</strong></div>
<div>&nbsp;</div>
<div><strong><img alt="ECMAScript Execution Context and Scope Chain" src="http://www.w3cgroup.com/attachments/month_1004/k201041113028.png" /></strong></div>
<div>&nbsp;</div>
<div>Scope Chain DEMO:</div>
<div>&lt;script type=&quot;text/javascript&quot;&gt;</div>
<div>var v = 'global';</div>
<div>&nbsp;</div>
<div>var x = function(v){</div>
<div>&nbsp;alert(v);</div>
<div>&nbsp;with({}){</div>
<div><span>&nbsp;&nbsp;&nbsp; v = 'w';</span></div>
<div>&nbsp;}</div>
<div>&nbsp;try{alert(me);}catch(e){}</div>
<div>};</div>
<div>&nbsp;</div>
<div>var y = function(){</div>
<div>&nbsp;alert(v);</div>
<div>};</div>
<div>&nbsp;</div>
<div>var z = function(){</div>
<div>&nbsp;var v = 'z';</div>
<div>&nbsp;y();</div>
<div>&nbsp;alert(v);</div>
<div>};</div>
<div>&nbsp;</div>
<div>var n = function(){</div>
<div>&nbsp;var i = 0;</div>
<div>&nbsp;var inner = function(){</div>
<div><span>&nbsp;&nbsp;&nbsp; alert(++i);</span></div>
<div>&nbsp;};</div>
<div>&nbsp;return inner;</div>
<div>};</div>
<div>&nbsp;</div>
<div>x();</div>
<div>&nbsp;</div>
<div>z();</div>
<div>&nbsp;</div>
<div>var fn = n();</div>
<div>&nbsp;</div>
<div>fn();</div>
<div>&lt;/script&gt;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong>ECMA-262参考资料</strong></div>
<div>ECMA-262 3rd Edition<br />
http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,% 20December%201999.pdf</div>
<div>&nbsp;</div>
<div>ECMA-262 5th Edition<br />
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf</div>
<div>&nbsp;</div>
<div>What is Ecma International<br />
http://www.ecma-international.org/memento/index.html</div>
<div>&nbsp;</div>
<div><a target="_blank" href="http://www.w3cgroup.com/attachments/month_1003/ECMAScript概述.ppt">PPT下载：ECMAScript概述.ppt</a></div>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=293" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=293</id>
  </entry>	
		
</feed>
