<?xml version="1.0" encoding="GBK" ?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dcterms="http://purl.org/dc/terms/">
 <channel>
  	  <title><![CDATA[互联网]]></title>
	  <link>http://blog.163.com/mike_gz</link>
	  <description><![CDATA[互联网研究 关注用户体验、产品策划、交互设计]]></description>
	  <language>zh-CN</language>
	  <pubDate>Thu, 11 Jun 2009 09:17:52 +0800</pubDate>
	  <lastBuildDate>Thu, 11 Jun 2009 09:17:52 +0800</lastBuildDate>
	  <docs>http://blogs.law.harvard.edu/tech/rss</docs>
	  <generator><![CDATA[NetEase Space]]></generator>
	  <managingEditor><![CDATA[mike_gz]]></managingEditor>
	  <webMaster><![CDATA[罗西]]></webMaster>
		  <ttl>120</ttl>
	  <image>
	  	<title><![CDATA[互联网]]></title>
	  	<url>http://ava.bimg.126.net/photo/qBbUMA_e4_vynxfeCOWZzQ==/207447057836214073.jpg</url>
	  	<link>http://blog.163.com/mike_gz</link>
	  </image>
  <item>
  	<title><![CDATA[JavaScript优化细节]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200951191747234</link>
    <description><![CDATA[<div>转<br><br><p>作为一名网站开发WEB前端工程师，对自己开发的网站项目应该尽可能地对其性能进行优化，现在互联网上搜索到的网站性能优化多是翻译转载自
Yahoo14条或34条。Yahoo的优化建议关注在大的方面，下面，W3C
Group为大家呈现WEB前端开发高性能优化部分之JavaScript的优化细节！</p>
<p><strong>一、避免出现脚本失控</strong></p>
<p>不论什么脚本，在任何时间、任何浏览器上执行，都不应该超过100毫秒。如果实际执行的时间长于这个底限，一定要将进程分解成若干更小的代码段。</p>
<p>脚本失控基本上有以下四个方面的原因：</p>
<p><strong>1. 在循环中执行了太多的操作</strong></p>
<p>解决这个问题的诀窍就是用下面这两个问题来评估每个循环：</p>
<ol><li>这个循环必须要同步执行么？</li><li>循环里面的数据，必须要按顺序执行么？</li></ol>
<p>如果1和2都可以否定，那么建议使用setTimeout方式将循环体切分成小块进行异步处理</p>
<p>将循环中的定义变量及初始化操作放到循环外。参见：<a href="http://www.w3cgroup.com/article.asp?id=111" target="_blank">http://www.w3cgroup.com/article.asp?id=111</a></p>
<p><strong>2. 臃肿的函数体</strong></p>
<p>在JavaScript中，我们应该尽可能的用局部变量来代替全局变量!</p>
<p>理解JavaScript作用域链。参见：<a href="http://www.jslab.org.cn/?tag=ScopeChainAndClosure">http://www.jslab.org.cn/?tag=ScopeChainAndClosure</a></p>
<p>理解原型链。参见：<a href="http://www.jslab.org.cn/?tag=prototypeChain">http://www.jslab.org.cn/?tag=prototypeChain</a></p>
<p><strong>3. 过多的递归</strong></p>
<p>使用迭代方式替代递归，采用memoization技术优化递归</p>
<p>斐波那契数列的递归算法优化，参见：<a href="http://www.jslab.org.cn/?tag=Memoization" target="_blank">http://www.jslab.org.cn/?tag=Memoization</a></p><p><br></p><p><strong>4. 过多的DOM调用</strong></p>
<p>在Web开发中，JavaScript的一个很重要的作用就是对DOM进行操作。可你知道么？对DOM的操作是非常昂贵的，因为这会导致浏览器执行回流（reflow）操作。而执行了过多的回流操作，你就会发现自己的网站变得越来越慢了。我们应该尽可能的减少DOM操作。</p>
<p>回流操作主要会发生在几种情况下：</p>
<ul><li>改变窗体大小</li><li>更改字体</li><li>添加移除stylesheet块</li><li>内容改变哪怕是输入框输入文字</li><li>CSS虚类被触发如 :hover</li><li>更改元素的className</li><li>当对DOM节点执行新增或者删除操作或内容更改时。</li><li>动态设置一个style样式时（比如element.style.width="10px"）。</li><li>当获取一个必须经过计算的尺寸值时，比如访问offsetWidth、clientHeight或者其他需要经过计算的CSS值（在兼容DOM的浏览器中，可以通过getComputedStyle函数获取；在IE中，可以通过currentStyle属性获取）。</li></ul>
<p>解决问题的关键，就是限制通过DOM操作所引发回流的次数:</p>
<p>1.在对当前DOM进行操作之前，尽可能多的做一些准备工作，保证N次创建，1次写入。</p>
<p>2.在对DOM操作之前，把要操作的元素，先从当前DOM结构中删除：</p>
<ol><li>通过removeChild()或者replaceChild()实现真正意义上的删除。</li><li>设置该元素的display样式为“none”。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 修改操作完成后，将上面这个过程反转过来，建议使用第2种方式。</li></ol>
<p>3.CSS部分</p>
<p>另外一个经常引起回流操作的情况是通过style属性对元素的外观进行修改，如element.style.backgroundColor = "blue";</p>
<p>每次修改元素的style属性，都肯定会触发回流操作，要解决这个问题可以：</p>
<ol><li>使用更改className的方式替换style.xxx=xxx的方式。</li><li>使用style.cssText = '';一次写入样式。</li><li>避免设置过多的行内样式</li><li>添加的结构外元素尽量设置它们的位置为fixed或absolute</li><li>避免使用表格来布局</li><li>避免在CSS中使用JavaScript expressions(IE only)</li></ol>
<p>4.将获取的DOM数据缓存起来。这种方法，对获取那些会触发回流操作的属性（比如offsetWidth等）尤为重要。</p>
<p>5.当对HTMLCollection对象进行操作时，应该将访问的次数尽可能的降至最低，最简单的，你可以将length属性缓存在一个本地变量中，这样就能大幅度的提高循环的效率。</p><p><br></p><p><strong>二、避免大字符串字面量对象操作，如 字符串.lenth，尽量转换为new String(字符串)后再进行操作</strong></p>
<p><strong>三、在做字符查找替换等操作时善用正则表达式</strong><br>快速掌握ECMAScript正则表达式。参见：<a href="http://www.w3cgroup.com/article.asp?id=202" target="_blank">http://www.w3cgroup.com/article.asp?id=202</a></p>
<p><strong>四、减少语句，利用运算符优先级实现if else表达式，使用三元表达式，使用连续表达式（看情况，将损失程序可读性）</strong></p>
<p>利用运算符优先级实现if else表达式参见：<a href="http://www.w3cgroup.com/article.asp?id=131" target="_blank">http://www.w3cgroup.com/article.asp?id=131</a></p>
<p><strong>五、将CSS，JS文件合并到一个文件</strong>（非BT爱好者还是不要玩了^_^）<br>参见：<a href="http://www.w3cgroup.com/article.asp?id=29" target="_blank">http://www.w3cgroup.com/article.asp?id=29</a></p>
<p><strong>六、避免Javascript事件绑定出现内存泄漏</strong><br>"These memory leaks
often occur as a result of circular references between JavaScript
objects and objects within IE’s DOM (document object model)." Microsoft
GPDE Team Blog</p>
<p>参见：<a href="http://www.w3cgroup.com/article.asp?id=207" target="_blank">http://www.w3cgroup.com/article.asp?id=207</a></p>
<p><strong>七、使用WEB Workers技术（支持html5的浏览器）<br></strong>Web Workers为JavaScript提供了一种能在后台进程中运行的方法，Web Workers进程能够在不影响用户界面的情况下处理任务。</p>
<p>参见：<a href="http://www.w3cgroup.com/article.asp?id=242" target="_blank">http://www.w3cgroup.com/article.asp?id=242</a></p>
<p><strong>八、Y!14条（14 Rules for Faster-Loading Web Sites）</strong></p>
<ul><li>Rule 1 - Make Fewer HTTP Requests</li><li>Rule 2 - Use a Content Delivery Network (Server端)</li><li>Rule 3 - Add an Expires Header (Server端)</li><li>Rule 4 - Gzip Components (Server端)</li><li>Rule 5 - Put Stylesheets at the Top</li><li>Rule 6 - Put Scripts at the Bottom</li><li>Rule 7 - Avoid CSS Expressions</li><li>Rule 8 - Make JavaScript and CSS External</li><li>Rule 9 - Reduce DNS Lookups (Server端)</li><li>Rule 10 - Minify JavaScript</li><li>Rule 11 - Avoid Redirects (Server端)</li><li>&nbsp;Rule 12 - Remove Duplicate Scripts</li><li>Rule 13 - Configure ETags (Server端)</li><li>Rule 14 - Make AJAX Cacheable</li><li>Rule 15 - Use Iframes Wisely</li></ul>
<p>参见：<a href="http://www.w3cgroup.com/article.asp?id=97" target="_blank">http://www.w3cgroup.com/article.asp?id=97</a></p>
<p><strong>九、微软早期的DHTML优化建议</strong></p>
<ul><li>使用数组push替代字符串累加</li></ul>
<p>出处<a href="http://www.w3cgroup.com/article.asp?id=255" target="_blank">http://www.w3cgroup.com/article.asp?id=255</a></p><br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200951191747234</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200951191747234</guid>
    <pubDate>Thu, 11 Jun 2009 09:17:47 +0800</pubDate>
    <dcterms:modified>2009-06-11T09:17:47+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Javascript面向对象基础以及接口和继承类的实现]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200922744437409</link>
    <description><![CDATA[<div><p>在开始设计模式的书写之前，有必要对Javascript面向对象的概念先做个介绍，那么这篇文章就以面向对象基础作为起点吧。</p>
<p><strong>理论知识</strong></p>
<p>1. 首先Javascript是弱类型语言，它定义变量时不必声明类型，如var Person = new
Person()，它的变量类型为“var”，现在的C#
3.0也引进了这种匿名类型的概念，弱类型的变量产生了极大的灵活性，因为Javascript会根据需要来进行类型转换。所以这也决定了它采用了晚绑定
的方法，即在运行后才知道变量的类型；</p>
<p>2. 面向对象概念不必多说，封装，继承，多态；</p>
<p>3. Javascript对象的类型主要分为三种：本地对象，如String，Array，Date等；内置对象，如Global，Math等；宿主对象，是指传统面向对象程序设计中的作用域，如公有，保护，私有，静态等等。</p>
<p><strong>主要内容</strong></p>
<p>1. 现在让我们来看看Javascript怎样创建对象的：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>function Man() {<br>   //  <br>}<br>Man.prototype.getNickName = function() {<br>    return "Leepy";<br>}; <br><br>var man = new Man();<br>var name = man.getNickName(); <br></pre></td></tr></tbody></table>
<p>这样就创建了最简单的类和对象，其中我们可以把function Man() {}
看作是Man类的构造函数，getNickName()看作是Man类的方法，准确说可以“当作”是Man类的公共方法；为什么要说是当作呢？那是因为其
实Javascript实际上并没有一个私有共有的划分，因此开发者们自己指定了这样的规约，那么规约是什么样的呢？我这里把Man类的清单完整地列出
来：</p>
<div align="center">
<div style="border: 1px solid rgb(204, 204, 204); padding: 0px 0px 6px 10px; overflow: auto; margin-left: auto; width: 517px; margin-right: auto; height: 166px;">
<p align="left">
</p><div align="left"><pre>function Man() {<br>    // 私有静态属性<br>    var Sex = "男";<br>    //私有静态方法<br>    function checkSex() {<br>        return (Sex == "男");<br>    }<br>    //私有方法<br>    this._getSex = function() {<br>        //调用私有静态方法<br>        if(checkSex())<br>            return "男";<br>        else<br>            return "女";<br>    }<br>    //私有方法<br>    this.getFirstName = function() { <br>        return "Li";<br>    };<br>    //私有方法<br>    this.getLastName = function() {<br>        return "Ping";<br>    };<br>}<br>//公共方法<br>Man.prototype.getNickName = function() {<br>    return "Leepy";<br>};<br>//公共方法<br>Man.prototype.getFullName = function() {<br>    return this.getFirstName() + " " + this.getLastName();<br>};<br>//公共方法<br>Man.prototype.getSex = function() {<br>    //调用私有方法<br>    return this._getSex();<br>};<br>//公共静态方法<br>Man.say = function() {<br>    return "Happy new year!";<br>}<br></pre></div>
</div></div>
<p>这样的类是否看起来和传统的类很相似了呢？</p>
<p>2.接下来这个是本篇的一个重点，就是用Javascript如何设计一个接口，然后让类继承于它。</p>
<p>首先，先让我们看传统的C#语言是如何设计接口的吧：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>public interface Person<br>{<br>    string GetName();<br>    void SetName(string name);<br>}<br>public class Man : Person<br>{<br>    private string _name; <br><br>    public string GetName()<br>    {<br>        return _name;<br>    }<br>    public void SetName(string name)<br>    {<br>        _name = name;<br>    }<br>} <br></pre></td></tr></tbody></table>
<p>接口中可以声明属性、方法、事件和类型(Structure)，（但不能声明变量），但是并不能设置这些成员的具体值，也就是说，只能定义，不能给
它里面定义的东西赋值，而接口作为它的继承类或者派生类的规约，继承类或者它的派生类能够共同完成接口属性、方法、事件和类型的具体实现，因为这里
GetName()，SetName()，不管是方法名还是属性调用顺序上都是要保持一致的；</p>
<p>那么有了这样的一个基于接口的思想，我们设计Javascript的接口类的时候也需要考虑到这个规范。我先从主JS文件调用端开始说起：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>var Person = new Interface("Person", [["getName", 0], ["setName", 1]]); <br></pre></td></tr></tbody></table>
<p>其中Interface类是稍后要说的接口类，第一个参数"Person"是接口类的名称，第二个参数是个二维数组，"getName"是接口方法
的名称，"0"是该方法所带的参数个数（因为Javascript是弱语言，所以类型是不确定的，所以只要记住参数个数就好，"0"可以省略不
写），"setName"同理。这样一个接口定义好了。怎样使用它呢？</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>function Man() <br>{<br>    this.name = "";<br>    Interface.registerImplements(this, Person);<br>}<br>Man.prototype.getName = function() {<br>    return this.name;<br>};<br>Man.prototype.setName = function(name) {<br>    this.name = name;<br>}; <br></pre></td></tr></tbody></table>
<p>看到Man的构造函数里面包含</p>
<p><em>Interface.registerImplements(this, Person);</em></p>
<p>它是用来将实例化的this对象继承于Person接口，然后继承类对接口的方法进行实现。</p>
<p>代码看起来是不是很清晰和简单呢，那么现在要开始介绍真正的核心代码Interface.js了：</p>
<p>先看Interface的构造函数部分</p>
<div align="center">
<div style="border: 1px solid rgb(204, 204, 204); padding: 0px 0px 6px 10px; overflow: auto; margin-left: auto; width: 517px; margin-right: auto; height: 166px;">
<p align="left">
</p><div align="left"><pre>unction Interface(name, methods) <br>{<br>    if(arguments.length != 2) {<br>        throw new Error("接口构造函数含" + arguments.length + "个参数, 但需要2个参数.");<br>    }<br>    this.name = name;<br>    this.methods = [];<br>    if(methods.length &lt; 1) {<br>        throw new Error("第二个参数为空数组.");<br>    }<br>    for(var i = 0, len = methods.length; i &lt; len; i++) {<br>        if(typeof methods[i][0] !== 'string') {<br>            throw new Error("接口构造函数第一个参数必须为字符串类型.");<br>        }<br>        if(methods[i][1] &amp;&amp; typeof methods[i][1] !== 'number') {<br>            throw new Error("接口构造函数第二个参数必须为整数类型.");<br>        }<br>        if(methods[i].length == 1) {<br>            methods[i][1] = 0;<br>        } <br><br>        this.methods.push(methods[i]);<br>    }    <br>};<br></pre></div>
</div></div>
<p>刚才看到了var Person = new Interface("Person", [["getName", 0], ["setName", 1]]);，这里将两个参数分别保存起来；<br></p><p><strong>调用方法部分：</strong></p>
<div align="center">
<div style="border: 1px solid rgb(204, 204, 204); padding: 0px 0px 6px 10px; overflow: auto; margin-left: auto; width: 517px; margin-right: auto; height: 166px;">
<p align="left">
</p><div align="left"><pre>Interface.registerImplements = function(object) { <br><br>    if(arguments.length &lt; 2) {<br>        throw new Error("接口的实现必须包含至少2个参数.");<br>    } <br><br>    for(var i = 1, len = arguments.length; i &lt; len; i++) {<br>        var interface = arguments[i];<br>        if(interface.constructor !== Interface) {<br>            throw new Error("从第2个以上的参数必须为接口实例.");<br>        }<br>        for(var j = 0, methodsLen = interface.methods.length; j &lt; methodsLen; j++) {<br>            var method = interface.methods[j][0];<br>            if(!object[method] || typeof object[method] !== 'function' || object[method].getParameters().length != interface.methods[j][1]) {<br>                throw new Error("接口的实现对象不能执行" + interface.name + "的接口方法" + method + "，因为它找不到或者不匹配.");<br>            }<br>        }<br>    }<br>}; <br></pre></div>
</div></div>
<p>刚才这句Interface.registerImplements(this,
Person);，实际上这里是把this对象的方法名以及参数个数与刚Person保存的methods逐一进行比较，如果找不到或者不匹配，就警告错
误；其中object[method].getParameters().length，调用了如下的代码：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>Function.prototype.getParameters = function() { <br><br>    var str = this.toString();<br>    var paramString = str.slice(str.indexOf('(') + 1, str.indexOf(')')).rep<br>lace(/\s*/g,'');     //取得参数字符串<br>    try<br>    {<br>        return (paramString.length == 0 ? [] : paramString.split(','));<br>    }<br>    catch(err)<br>    {<br>        throw new Error("函数不合法!");<br>    }<br>} <br></pre></td></tr></tbody></table>
<p>getParrameters()方法作为Function对象的一个扩展，功能是取得方法含有的参数数组；</p>
<p>Interface.js完整的代码如下：</p>
<p><strong>Interface.js文件</strong></p>
<div align="center">
<div style="border: 1px solid rgb(204, 204, 204); padding: 0px 0px 6px 10px; overflow: auto; margin-left: auto; width: 517px; margin-right: auto; height: 166px;">
<p align="left">
</p><div align="left"><pre>function Interface(name, methods) <br>{<br>    if(arguments.length != 2) {<br>        throw new Error("接口构造函数含" + arguments.length + "个参数, 但需要2个参数.");<br>    }<br>    this.name = name;<br>    this.methods = [];<br>    if(methods.length &lt; 1) {<br>        throw new Error("第二个参数为空数组.");<br>    }<br>    for(var i = 0, len = methods.length; i &lt; len; i++) {<br>        if(typeof methods[i][0] !== 'string') {<br>            throw new Error("接口构造函数第一个参数必须为字符串类型.");<br>        }<br>        if(methods[i][1] &amp;&amp; typeof methods[i][1] !== 'number') {<br>            throw new Error("接口构造函数第二个参数必须为整数类型.");<br>        }<br>        if(methods[i].length == 1) {<br>            methods[i][1] = 0;<br>        } <br><br>        this.methods.push(methods[i]);<br>    }    <br>}; <br><br>Interface.registerImplements = function(object) { <br><br>    if(arguments.length &lt; 2) {<br>        throw new Error("接口的实现必须包含至少2个参数.");<br>    } <br><br>    for(var i = 1, len = arguments.length; i &lt; len; i++) {<br>        var interface = arguments[i];<br>        if(interface.constructor !== Interface) {<br>            throw new Error("从第2个以上的参数必须为接口实例.");<br>        }<br>        for(var j = 0, methodsLen = interface.methods.length; j &lt; methodsLen; j++) {<br>            var method = interface.methods[j][0];<br>            if(!object[method] || typeof object[method] !== 'function' || object[method].getParameters().length != interface.methods[j][1]) {<br>                throw new Error("接口的实现对象不能执行" + interface.name + "的接口方法" + method + "，因为它找不到或者不匹配.");<br>            }<br>        }<br>    }<br>}; <br><br>Function.prototype.getParameters = function() { <br><br>    var str = this.toString();<br>    var paramString = str.slice(str.indexOf('(') + 1, str.indexOf(')')).replace(/\s*/g,'');     //取得参数字符串<br>    try<br>    {<br>        return (paramString.length == 0 ? [] : paramString.split(','));<br>    }<br>    catch(err)<br>    {<br>        throw new Error("函数不合法!");<br>    }<br>} <br></pre></div>
</div></div>
<p>好了该创建一个html页面来试试效果了：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>＜script type="text/javascript"＞<br>function test()<br>{<br>    var man = new Man();<br>    man.setName("Leepy");<br>    alert(man.getName());<br>}<br>＜/script＞ <br><br>＜input type="button" value="click" onclick="test();" /＞<br></pre></td></tr></tbody></table>
<p>最终结果为："Leepy"的弹出框。</p>
<p>这里还有一点要强调，如果接口上的方法没有在继承类上得到完全实现，或者方法参数个数不匹配，那么就会提示错误。</p>
<p>3. 如果我要一个类继承于另一个类该怎么做呢，继续看例子，这里我再定义一个SchoolBoy（男学生）类：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>function SchoolBoy(classNo, post)<br>{<br>    Man.call(this);<br>    this._chassNo = classNo;<br>    this._post = post;<br>}<br>SchoolBoy.prototype = new Man();<br>SchoolBoy.prototype.getName = function() {<br>    return "Mr " + this.name;<br>}<br>SchoolBoy.prototype.setName = function(name) {<br>    this.name = name + "'s";<br>}<br></pre></td></tr></tbody></table>
<p>其中Man.call(this);实际上是将Man中的关键字this赋值于SchoolBoy对象中去，那么SchoolBoy就拥有了Man构造函数中的name属性了。</p>
<p>SchoolBoy.prototype = new Man();实际上是把Man的prototype赋值给SchoolBoy.prototype，那么SchoolBoy就有了Man类中的方法。</p>
<p>而后面跟着的getName()，setName()，实际上是覆盖了前面继承于Man类中的方法了。</p>
<p>然后看看效果：</p>
<table bordercolordark="#ffffff" bordercolorlight="#999999" width="400" align="center" border="1" cellpadding="2" cellspacing="0">
<tbody>
<tr>
<td  bgcolor="#e6e6e6"><pre>var schoolboy = new SchoolBoy("三年二班", "班长");<br>schoolboy.setName("周杰伦");<br>alert(schoolboy.getName());<br></pre></td></tr></tbody></table>
<p>最后结果为："Mr 周杰伦's"的弹出框。</p><p><br></p></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200922744437409</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200922744437409</guid>
    <pubDate>Fri, 27 Mar 2009 16:44:37 +0800</pubDate>
    <dcterms:modified>2009-03-28T11:01:45+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[ javascript 正则表达式祥解]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220092242850730</link>
    <description><![CDATA[<div>转<br><p>正则表达式使用详解<br>简介</p>
<p>简单的说，正则表达式是一种可以用于模式匹配和替换的强有力的工具。其作用如下：<br>测试字符串的某个模式。例如，可以对一个输入字符串进行测试，看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。<br>替换文本。可以在文档中使用一个正则表达式来标识特定文字，然后可以全部将其删除，或者替换为别的文字。<br>根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。</p>
<p>基本语法</p>
<p>在对正则表达式的功能和作用有了初步的了解之后，我们就来具体看一下正则表达式的语法格式。<br>正则表达式的形式一般如下：　　</p>
<p>/love/　　其中位于“/”定界符之间的部分就是将要在目标对象中进行匹配的模式。用户只要把希望查找匹配对象的模式内容放入“/”定界符之间
即可。为了能够使用户更加灵活的定制模式内容，正则表达式提供了专门的“元字符”。所谓元字符就是指那些在正则表达式中具有特殊意义的专用字符，可以用来
规定其前导字符（即位于元字符前面的字符）在目标对象中的出现模式。<br>较为常用的元字符包括： “+”， “*”，以及 “?”。</p>
<p>“+”元字符规定其前导字符必须在目标对象中连续出现一次或多次。</p>
<p>“*”元字符规定其前导字符必须在目标对象中出现零次或连续多次。</p>
<p>“?”元字符规定其前导对象必须在目标对象中连续出现零次或一次。</p>
<p>下面，就让我们来看一下正则表达式元字符的具体应用。</p>
<p>/fo+/　　因为上述正则表达式中包含“+”元字符，表示可以与目标对象中的 “fool”, “fo”, 或者 “football”等在字母f后面连续出现一个或多个字母o的字符串相匹配。</p>
<p>/eg*/　　因为上述正则表达式中包含“*”元字符，表示可以与目标对象中的 “easy”, “ego”, 或者 “egg”等在字母e后面连续出现零个或多个字母g的字符串相匹配。</p>
<p>/Wil?/　　因为上述正则表达式中包含“？”元字符，表示可以与目标对象中的 “Win”, 或者“Wilson”,等在字母i后面连续出现零个或一个字母l的字符串相匹配。</p>
<p>有时候不知道要匹配多少字符。为了能适应这种不确定性，正则表达式支持限定符的概念。这些限定符可以指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。</p>
<p>{n} n 是一个非负整数。匹配确定的 n 次。例如，'o{2}' 不能匹配 "Bob" 中的 'o'，但是能匹配 "food" 中的两个 o。</p>
<p>{n,} n 是一个非负整数。至少匹配 n 次。例如，'o{2,}' 不能匹配 "Bob" 中的 'o'，但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。</p>
<p>{n,m} m 和 n 均为非负整数，其中n &lt;= m。最少匹配 n 次且最多匹配 m 次。例如，"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。</p>
<p>除了元字符之外，用户还可以精确指定模式在匹配对象中出现的频率。例如，/jim {2,6}/ 上述正则表达式规定字符m可以在匹配对象中连续出现2-6次，因此，上述正则表达式可以同jimmy或jimmmmmy等字符串相匹配。<br>在对如何使用正则表达式有了初步了解之后，我们来看一下其它几个重要的元字符的使用方式。<br>代码</p>
<p>&nbsp;&nbsp; 1. \s：用于匹配单个空格符，包括tab键和换行符；&nbsp;&nbsp; <br>&nbsp;&nbsp; 2. \S：用于匹配除单个空格符之外的所有字符；&nbsp;&nbsp; <br>&nbsp;&nbsp; 3. \d：用于匹配从0到9的数字；&nbsp;&nbsp; <br>&nbsp;&nbsp; 4. \w：用于匹配字母，数字或下划线字符；&nbsp;&nbsp; <br>&nbsp;&nbsp; 5. \W：用于匹配所有与\w不匹配的字符；&nbsp;&nbsp; <br>&nbsp;&nbsp; 6. . ：用于匹配除换行符之外的所有字符。&nbsp;&nbsp; </p>
<p><br>（说明：我们可以把\s和\S以及\w和\W看作互为逆运算）<br>下面，我们就通过实例看一下如何在正则表达式中使用上述元字符。<br>/\s+/ 上述正则表达式可以用于匹配目标对象中的一个或多个空格字符。<br>/\d000/　如果我们手中有一份复杂的财务报表，那么我们可以通过上述正则表达式轻而易举的查找到所有总额达千元的款项。<br>除了我们以上所介绍的元字符之外，正则表达式中还具有另外一种较为独特的专用字符，即定位符。定位符用于规定匹配模式在目标对象中的出现位置。 较为常用的定位符包括： “^”, “$”, “\b” 以及 “\B”。<br>代码</p>
<p>&nbsp;&nbsp; 1. “^”定位符规定匹配模式必须出现在目标字符串的开头&nbsp; <br>&nbsp;&nbsp; 2. “$”定位符规定匹配模式必须出现在目标对象的结尾&nbsp; <br>&nbsp;&nbsp; 3. “\b”定位符规定匹配模式必须出现在目标字符串的开头或结尾的两个边界之一&nbsp; <br>&nbsp;&nbsp; 4. “\B”定位符则规定匹配对象必须位于目标字符串的开头和结尾两个边界之内，&nbsp; <br>&nbsp;&nbsp; 5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 即匹配对象既不能作为目标字符串的开头，也不能作为目标字符串的结尾。&nbsp; </p>
<p><br>同样，我们也可以把“^”和“$”以及“\b”和“\B”看作是互为逆运算的两组定位符。举例来说：
/^hell/　因为上述正则表达式中包含“^”定位符，所以可以与目标对象中以 “hell”,
“hello”或“hellhound”开头的字符串相匹配。 /ar$/　因为上述正则表达式中包含“$”定位符，所以可以与目标对象中以
“car”, “bar”或 “ar” 结尾的字符串相匹配。 /\bbom/　因为上述正则表达式模式以“\b”定位符开头，所以可以与目标对象中以
“bomb”, 或 “bom”开头的字符串相匹配。/man\b/　因为上述正则表达式模式以“\b”定位符结尾，所以可以与目标对象中以
“human”, “woman”或 “man”结尾的字符串相匹配。<br>为了能够方便用户更加灵活的设定匹配模式，正则表达式允许使用者在匹配模式中指定某一个范围而不局限于具体的字符。例如：<br>代码</p>
<p>&nbsp;&nbsp; 1. /[A-Z]/　　上述正则表达式将会与从A到Z范围内任何一个大写字母相匹配。&nbsp; <br>&nbsp;&nbsp; 2. /[a-z]/　　上述正则表达式将会与从a到z范围内任何一个小写字母相匹配。&nbsp;&nbsp; <br>&nbsp;&nbsp; 3. /[0-9]/ 　上述正则表达式将会与从0到9范围内任何一个数字相匹配。&nbsp;&nbsp; <br>&nbsp;&nbsp; 4. /([a-z][A-Z][0-9])+/　上述正则表达式将会与任何由字母和数字组成的字符串，如 “aB0” 等相匹配。&nbsp; </p>
<p><br>这里需要提醒用户注意的一点就是可以在正则表达式中使用 “()” 把字符串组合在一起。“()”符号包含的内容必须同时出现在目标对象中。因此，上述正则表达式将无法与诸如 “abc”等的字符串匹配，因为“abc”中的最后一个字符为字母而非数字。<br>如果我们希望在正则表达式中实现类似编程逻辑中的“或”运算，在多个不同的模式中任选一个进行匹配的话，可以使用管道符 “|”。例如：/to|too|2/　上述正则表达式将会与目标对象中的 “to”, “too”, 或 “2” 相匹配。<br>正
则表达式中还有一个较为常用的运算符，即否定符 “[^]”。与我们前文所介绍的定位符 “^” 不同，否定符
“[^]”规定目标对象中不能存在模式中所规定的字符串。例如：/[^A-C]/　上述字符串将会与目标对象中除A，B，和C之外的任何字符相匹配。一般
来说，当“^”出现在 “[]”内时就被视做否定运算符；而当“^”位于“[]”之外，或没有“[]”时，则应当被视做定位符。<br>最后，当用户需要在正则表达式的模式中加入元字符，并查找其匹配对象时，可以使用转义符“\”。例如：/Th\*/ 　上述正则表达式将会与目标对象中的“Th*”而非“The”等相匹配。<br>在构造正则表达式之后，就可以象数学表达式一样来求值，也就是说，可以从左至右并按照一个优先级顺序来求值。优先级如下：<br>代码</p>
<p>&nbsp;&nbsp; 1. 1．\ 转义符&nbsp; <br>&nbsp;&nbsp; 2. 2．(), (?, (?=), [] 圆括号和方括号&nbsp; <br>&nbsp;&nbsp; 3. 3．*, +, ?, {n}, {n,}, {n,m} 限定符&nbsp; <br>&nbsp;&nbsp; 4. 4．^, $, \anymetacharacter 位置和顺序&nbsp; <br>&nbsp;&nbsp; 5. 5．|“或”操作&nbsp; </p>
<p>使用实例<br>在JavaScript 1.2中带有一个功能强大的RegExp()对象，可以用来进行正则表达式的匹配操作。其中的test()方法可以检验目标对象中是否包含匹配模式，并相应的返回true或false。<br>我们可以使用JavaScript编写以下脚本，验证用户输入的邮件地址的有效性。<br>代码</p>
<p>&nbsp;&nbsp; 1. &lt;html&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp; 2. &lt;head&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp; 3. 　 &lt;script language="Javascript1.2"&gt;&nbsp;&nbsp; <br>&nbsp;&nbsp; 4. 　　　　 &lt;!-- start hiding&nbsp;&nbsp; <br>&nbsp;&nbsp; 5. 　　　　 function verifyAddress(obj)&nbsp;&nbsp; <br>&nbsp;&nbsp; 6. 　　　　　{&nbsp;&nbsp; <br>&nbsp;&nbsp; 7. 　　　　　　var email = obj.email.value;&nbsp;&nbsp; <br>&nbsp;&nbsp; 8. 　　　　　　var pattern =&nbsp;&nbsp; <br>&nbsp;&nbsp; 9. /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;&nbsp;&nbsp; <br>&nbsp; 10. 　　　　　　flag = pattern.test(email);&nbsp;&nbsp; <br>&nbsp; 11. 　　　　　　if(flag)&nbsp;&nbsp; <br>&nbsp; 12. 　　　　　　{&nbsp;&nbsp; <br>&nbsp; 13. 　　　　　　　alert(“Your email address is correct!”);&nbsp;&nbsp; <br>&nbsp; 14. 　　　　　　　return true;&nbsp;&nbsp; <br>&nbsp; 15. 　　　　　　}&nbsp;&nbsp; <br>&nbsp; 16. 　　　　　　else&nbsp;&nbsp; <br>&nbsp; 17. 　　　　　　　{&nbsp;&nbsp; <br>&nbsp; 18. 　　　　　　　　alert(“Please try again!”);&nbsp;&nbsp; <br>&nbsp; 19. 　　　　　　　　return false;&nbsp;&nbsp; <br>&nbsp; 20. 　　　　　　　 }&nbsp;&nbsp; <br>&nbsp; 21. 　　　　　 }&nbsp;&nbsp; <br>&nbsp; 22. 　　　　 // stop hiding --&gt;&nbsp;&nbsp; <br>&nbsp; 23. 　　　 &lt;/script&gt;&nbsp;&nbsp; <br>&nbsp; 24. 　　&lt;/head&gt;&nbsp;&nbsp; <br>&nbsp; 25. 　 &lt;body&gt;&nbsp;&nbsp; <br>&nbsp; 26. 　　 &lt;form onSubmit="return verifyAddress(this);"&gt;&nbsp;&nbsp; <br>&nbsp; 27. 　　　 &lt;input name="email" type="text"&gt;&nbsp;&nbsp; <br>&nbsp; 28. 　　　 &lt;input type="submit"&gt;&nbsp;&nbsp; <br>&nbsp; 29. 　　　 &lt;/form&gt;&nbsp;&nbsp; <br>&nbsp; 30. 　　&lt;/body&gt;&nbsp;&nbsp; <br>&nbsp; 31. &lt;/html&gt; <br>&nbsp;</p>
<p>JS的正则表达式</p>
<p>//校验是否全由数字组成<br>代码</p>
<p>&nbsp;&nbsp; 1. function isDigit(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. var patrn=/^[0-9]{1,20}$/;&nbsp; <br>&nbsp;&nbsp; 4. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 5. return true&nbsp; <br>&nbsp;&nbsp; 6. }&nbsp; </p>
<p>//校验登录名：只能输入5-20个以字母开头、可带数字、“_”、“.”的字串<br>代码</p>
<p>&nbsp;&nbsp; 1. function isRegisterUserName(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. var patrn=/^[a-zA-Z]{1}([a-zA-Z0-9]|[._]){4,19}$/;&nbsp; <br>&nbsp;&nbsp; 4. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 5. return true&nbsp; <br>&nbsp;&nbsp; 6. }&nbsp; </p>
<p>//校验用户姓名：只能输入1-30个以字母开头的字串<br>代码</p>
<p>&nbsp;&nbsp; 1. function isTrueName(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. var patrn=/^[a-zA-Z]{1,30}$/;&nbsp; <br>&nbsp;&nbsp; 4. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 5. return true&nbsp; <br>&nbsp;&nbsp; 6. }&nbsp; <br>&nbsp;&nbsp; 7. }}&nbsp; <br>&nbsp;&nbsp; 8.&nbsp;&nbsp; <br>&nbsp;&nbsp; 9. //校验密码：只能输入6-20个字母、数字、下划线&nbsp; <br>&nbsp; 10. [code]&nbsp; <br>&nbsp; 11. function isPasswd(s)&nbsp; <br>&nbsp; 12. {&nbsp; <br>&nbsp; 13. var patrn=/^(\w){6,20}$/;&nbsp; <br>&nbsp; 14. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp; 15. return true&nbsp; <br>&nbsp; 16. }&nbsp; </p>
<p>//校验普通电话、传真号码：可以“+”开头，除数字外，可含有“-”<br>代码</p>
<p>&nbsp;&nbsp; 1. function isTel(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. //var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?(\d){1,12})+$/;&nbsp; <br>&nbsp;&nbsp; 4. var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;&nbsp; <br>&nbsp;&nbsp; 5. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 6. return true&nbsp; <br>&nbsp;&nbsp; 7. }&nbsp; </p>
<p>//校验手机号码：必须以数字开头，除数字外，可含有“-”<br>代码</p>
<p>&nbsp;&nbsp; 1. function isMobil(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. var patrn=/^[+]{0,1}(\d){1,3}[ ]?([-]?((\d)|[ ]){1,12})+$/;&nbsp; <br>&nbsp;&nbsp; 4. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 5. return true&nbsp; <br>&nbsp;&nbsp; 6. }&nbsp; </p>
<p>//校验邮政编码<br>代码</p>
<p>&nbsp;&nbsp; 1. function isPostalCode(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. //var patrn=/^[a-zA-Z0-9]{3,12}$/;&nbsp; <br>&nbsp;&nbsp; 4. var patrn=/^[a-zA-Z0-9 ]{3,12}$/;&nbsp; <br>&nbsp;&nbsp; 5. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 6. return true&nbsp; <br>&nbsp;&nbsp; 7. }&nbsp; </p>
<p>//校验搜索关键字<br>代码</p>
<p>&nbsp;&nbsp; 1. function isSearch(s)&nbsp; <br>&nbsp;&nbsp; 2. {&nbsp; <br>&nbsp;&nbsp; 3. var patrn=/^[^`~!@#$%^&amp;*()+=|\\\][\]\{\}:;'\,.&lt;&gt;/?]{1}[^`~!@$%^&amp;()+=|\\\]&nbsp; <br>&nbsp;&nbsp; 4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [\]\{\}:;'\,.&lt;&gt;?]{0,19}$/;&nbsp; <br>&nbsp;&nbsp; 5. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp;&nbsp; 6. return true&nbsp; <br>&nbsp;&nbsp; 7. }&nbsp; <br>&nbsp;&nbsp; 8.&nbsp;&nbsp; <br>&nbsp;&nbsp; 9. function isIP(s) //by zergling&nbsp; <br>&nbsp; 10. {&nbsp; <br>&nbsp; 11. var patrn=/^[0-9.]{1,20}$/;&nbsp; <br>&nbsp; 12. if (!patrn.exec(s)) return false&nbsp; <br>&nbsp; 13. return true&nbsp; <br>&nbsp; 14. }&nbsp; </p>
<p>正则表达式<br>代码</p>
&nbsp;&nbsp; 1. "^\\d+$"　　//非负整数（正整数 + 0）&nbsp; <br>&nbsp;&nbsp; 2. "^[0-9]*[1-9][0-9]*$"　　//正整数&nbsp;&nbsp; <br>&nbsp;&nbsp; 3. "^((-\\d+)|(0+))$"　　//非正整数（负整数 + 0）&nbsp;&nbsp; <br>&nbsp;&nbsp; 4. "^-[0-9]*[1-9][0-9]*$"　　//负整数&nbsp;&nbsp; <br>&nbsp;&nbsp; 5. "^-?\\d+$"　　　　//整数&nbsp;&nbsp; <br>&nbsp;&nbsp; 6. "^\\d+(<a href="/file://%5c%5c.%5c%5cd+%29?$/">\\.\\d+)?$</a>"　　//非负浮点数（正浮点数 + 0）&nbsp;&nbsp; <br>&nbsp;&nbsp; 7. "^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*))$"　&nbsp; <br>&nbsp;&nbsp; 8. //正浮点数&nbsp;&nbsp; <br>&nbsp;&nbsp; 9. "^((-\\d+(<a href="/file://%5c%5c.%5c%5cd+%29?%29%7c%280+%28%5c%5c.0+%29?%29%29$/">\\.\\d+)?)|(0+(\\.0+)?))$</a>"　　//非正浮点数（负浮点数 + 0）&nbsp;&nbsp; <br>&nbsp; 10. "^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$"　&nbsp; <br>&nbsp; 11. //负浮点数&nbsp;&nbsp; <br>&nbsp; 12. "^(-?\\d+)(<a href="/file://%5c%5c.%5c%5cd+%29?$/">\\.\\d+)?$</a>"　　//浮点数&nbsp;&nbsp; <br>&nbsp; 13. "^[A-Za-z]+$"　　//由26个英文字母组成的字符串&nbsp;&nbsp; <br>&nbsp; 14. "^[A-Z]+$"　　//由26个英文字母的大写组成的字符串&nbsp;&nbsp; <br>&nbsp; 15. "^[a-z]+$"　　//由26个英文字母的小写组成的字符串&nbsp;&nbsp; <br>&nbsp; 16. "^[A-Za-z0-9]+$"　　//由数字和26个英文字母组成的字符串&nbsp;&nbsp; <br>&nbsp; 17. "^\\w+$"　　//由数字、26个英文字母或者下划线组成的字符串&nbsp;&nbsp; <br>&nbsp; 18. "^[\\w-]+(<a href="/file://%5c%5c.%5b%5c%5cw-%5d+%29*@%5b%5c%5cw-%5d+%28%5c%5c.%5b%5c%5cw-%5d+%29+$/">\\.[\\w-]+)*@[\\w-]+(\\.[\\w-]+)+$</a>"　　　　//email地址&nbsp;&nbsp; <br>&nbsp; 19. "^[a-zA-z]+://(<a href="/file://%5c%5cw+%28-%5c%5cw+%29*%29%28%5c%5c.%28%5c%5cw+%28-%5c%5cw+%29*%29%29*%28%5c%5c?%5c%5cs*%29?$/">\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$</a>"　　//url&nbsp; <br>&nbsp; 20. "^[A-Za-z0-9_]*$" <br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220092242850730</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220092242850730</guid>
    <pubDate>Tue, 24 Mar 2009 14:08:50 +0800</pubDate>
    <dcterms:modified>2009-03-24T14:08:50+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Javascript 闭包]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200924104025828</link>
    <description><![CDATA[<div><UL>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clIntro">简介</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clResO">基于对象的属性名解析</A> 
<UL>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clResA">值的指定</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clResR">值的读取</A></LI></UL></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clIRExSc">标识符解析、执行环境和作用域链</A> 
<UL>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clExCon">执行环境</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clScCh">作用域链与 [[scope]]</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clIdRes">标识符解析</A></LI></UL></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clClose">闭包</A> 
<UL>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clAtGb">自动垃圾收集</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clFrmC">构成闭包</A></LI></UL></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clClDo">通过闭包可以做什么？</A> 
<UL>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clSto">例 1：为函数引用设置延时</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clObjI">例 2：通过对象实例方法关联函数</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clEncap">例 3：包装相关的功能</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clOtE">其他例子</A></LI></UL></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clAc">意外的闭包</A></LI>
<LI><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#clMem">Internet Explorer 的内在泄漏问题</A></LI></UL>
<H2><A   ><BLOCKQUOTE cite=http://groups.google.com/groups?selm=wu535hos.fsf@hotpop.com>
<DL>
<DT><A   ><DD>所谓“闭包”，指的是一个拥有许多变量和绑定了这些变量的环境的表达式（通常是一个函数），因而这些变量也是该表达式的一部分。 </DD>
<DD></DD></A></DT></DL></BLOCKQUOTE>
</A><P>闭包是 ECMAScript （JavaScript）最强大的特性之一，但用好闭包的前提是必须理解闭包。闭包的创建相对容易，人们甚至会在不经意间创建闭包，但这些无意创建的闭包却存在潜在的危害，尤其是在比较常见的浏览器环境下。如果想要扬长避短地使用闭包这一特性，则必须了解它们的工作机制。而闭包工作机制的实现很大程度上有赖于标识符（或者说对象属性）解析过程中作用域的角色。 </P>
<P>关于闭包，最简单的描述就是 ECMAScript 允许使用内部函数－－即函数定义和函数表达式位于另一个函数的函数体内。而且，这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时，就会形成闭包。也就是说，内部函数会在外部函数返回后被执行。而当这个内部函数执行时，它仍然必需访问其外部函数的局部变量、参数以及其他内部函数。这些局部变量、参数和函数声明（最初时）的值是外部函数返回时的值，但也会受到内部函数的影响。 </P>
<P>遗憾的是，要适当地理解闭包就必须理解闭包背后运行的机制，以及许多相关的技术细节。虽然本文的前半部分并没有涉及 ECMA 262 规范指定的某些算法，但仍然有许多无法回避或简化的内容。对于个别熟悉对象属性名解析的人来说，可以跳过相关的内容，但是除非你对闭包也非常熟悉，否则最好是不要跳过下面几节。 </P>
</H2><H2><A   ></A><P>ECMAScript 认可两类对象：原生（Native）对象和宿主（Host）对象，其中宿主对象包含一个被称为内置对象的原生对象的子类（ECMA 262 3rd Ed Section 4.3）。原生对象属于语言，而宿主对象由环境提供，比如说可能是文档对象、DOM 等类似的对象。 </P>
<P>原生对象具有松散和动态的命名属性（对于某些实现的内置对象子类别而言，动态性是受限的－－但这不是太大的问题）。对象的命名属性用于保存值，该值可以是指向另一个对象（Objects）的引用（在这个意义上说，函数也是对象），也可以是一些基本的数据类型，比如：String、Number、 Boolean、Null 或 Undefined。其中比较特殊的是 Undefined 类型，因为可以给对象的属性指定一个 Undefined 类型的值，而不会删除对象的相应属性。而且，该属性只是保存着 <CODE>undefined</CODE> 值。 </P>
<P>下面简要介绍一下如何设置和读取对象的属性值，并最大程度地体现相应的内部细节。 </P>
</H2><H3><A   ></A><P>对象的命名属性可以通过为该命名属性赋值来创建，或重新赋值。即，对于： </P><PRE>var objectRef = new Object(); <SPAN javascript 对象。></SPAN>
</PRE>
<P>可以通过下面语句来创建名为 “testNumber” 的属性： </P><PRE>objectRef.testNumber = 5;
<SPAN - 或- */></SPAN>
objectRef["testNumber"] = 5;
</PRE>
<P>在赋值之前，对象中没有“testNumber” 属性，但在赋值后，则创建一个属性。之后的任何赋值语句都不需要再创建这个属性，而只会重新设置它的值： </P><PRE>objectRef.testNumber = 8;
<SPAN - 或- */></SPAN>
objectRef["testNumber"] = 8;
</PRE>
<P>稍后我们会介绍，Javascript 对象都有原型（prototypes）属性，而这些原型本身也是对象，因而也可以带有命名的属性。但是，原型对象命名属性的作用并不体现在赋值阶段。同样，在将值赋给其命名属性时，如果对象没有该属性则会创建该命名属性，否则会重设该属性的值。 </P>
</H3><H3><A   ></A><P>当读取对象的属性值时，原型对象的作用便体现出来。如果对象的原型中包含属性访问器（property accessor）所使用的属性名，那么该属性的值就会返回： </P><PRE><SPAN 为命名属性赋值。如果在赋值前对象没有相应的属性，那么赋值后就会得到一个：*/></SPAN>
objectRef.testNumber = 8;

<SPAN 从属性中读取值 */></SPAN>

var val = objectRef.testNumber;
<SPAN 现在， - val - 中保存着刚赋给对象命名属性的值 8*/></SPAN>
   </PRE>
<P>而且，由于所有对象都有原型，而原型本身也是对象，所以原型也可能有原型，这样就构成了所谓的原型链。原型链终止于链中原型为 null 的对象。<CODE>Object</CODE> 构造函数的默认原型就有一个 null 原型，因此： </P><PRE>var objectRef = new Object(); <SPAN JavaScript 对象。></SPAN>
</PRE>
<P>创建了一个原型为 <CODE>Object.prototype</CODE> 的对象，而该原型自身则拥有一个值为 null 的原型。也就是说，<CODE>objectRef</CODE> 的原型链中只包含一个对象－－ <CODE>Object.prototype</CODE>。但对于下面的代码而言： </P><PRE><SPAN 创建 - MyObject1 - 类型对象的函数*/></SPAN>
function MyObject1(formalParameter){
    <SPAN 给创建的对象添加一个名为 - testNumber -          的属性并将传递给构造函数的第一个参数指定为该属性的值：*/></SPAN>
    this.testNumber = formalParameter;
}

<SPAN 创建 - MyObject2 - 类型对象的函数*/></SPAN>
function MyObject2(formalParameter){
   <SPAN 给创建的对象添加一个名为 - testString -         的属性并将传递给构造函数的第一个参数指定为该属性的值：*/></SPAN>
    this.testString = formalParameter;
}

<SPAN   ></SPAN>
MyObject2.prototype = new MyObject1( 8 );

<SPAN   ></SPAN>

var objectRef = new MyObject2( "String_Value" );
</PRE>
<P>被变量 <CODE>objectRef</CODE> 所引用的 <CODE>MyObject2</CODE> 的实例拥有一个原型链。该链中的第一个对象是在创建后被指定给 <CODE>MyObject2</CODE> 构造函数的 prototype 属性的 <CODE>MyObject1</CODE> 的一个实例。<CODE>MyObject1</CODE> 的实例也有一个原型，即与 <CODE>Object.prototype</CODE> 所引用的对象对应的默认的 Object 对象的原型。最后， <CODE>Object.prototype</CODE> 有一个值为 null 的原型，因此这条原型链到此结束。 </P>
<P>当某个属性访问器尝试读取由 <CODE>objectRef</CODE> 所引用的对象的属性值时，整个原型链都会被搜索。在下面这种简单的情况下： </P><PRE>var val = objectRef.testString;
</PRE>
<P>因为 <CODE>objectRef</CODE> 所引用的 <CODE>MyObject2</CODE> 的实例有一个名为“testString”的属性，因此被设置为“String_Value”的该属性的值被赋给了变量 <CODE>val</CODE>。但是： </P><PRE>var val = objectRef.testNumber;
</PRE>
<P>则不能从 <CODE>MyObject2</CODE> 实例自身中读取到相应的命名属性值，因为该实例没有这个属性。然而，变量 <CODE>val</CODE> 的值仍然被设置为 <CODE>8</CODE>，而不是未定义－－这是因为在该实例中查找相应的命名属性失败后，解释程序会继续检查其原型对象。而该实例的原型对象是 <CODE>MyObject1</CODE> 的实例，这个实例有一个名为“testNumber”的属性并且值为 <CODE>8</CODE>，所以这个属性访问器最后会取得值 <CODE>8</CODE>。而且，虽然 <CODE>MyObject1</CODE> 和 <CODE>MyObject2</CODE> 都没有定义 <CODE>toString</CODE> 方法，但是当属性访问器通过 <CODE>objectRef</CODE> 读取 <CODE>toString</CODE> 属性的值时： </P><PRE>var val = objectRef.toString;
</PRE>
<P>变量 <CODE>val</CODE> 也会被赋予一个函数的引用。这个函数就是在 <CODE>Object.prototype</CODE> 的 <CODE>toString</CODE> 属性中所保存的函数。之所以会返回这个函数，是因为发生了搜索<CODE>objectRef</CODE> 原型链的过程。当在作为对象的 <CODE>objectRef</CODE> 中发现没有“toString”属性存在时，会搜索其原型对象，而当原型对象中不存在该属性时，则会继续搜索原型的原型。而原型链中最终的原型是 <CODE>Object.prototype</CODE>，这个对象确实有一个 <CODE>toString</CODE> 方法，因此该方法的引用被返回。 </P>
<P>最后： </P><PRE>var val = objectRef.madeUpProperty;
</PRE>
<P>返回 <CODE>undefined</CODE>，因为在搜索原型链的过程中，直至 <CODE>Object.prototype</CODE> 的原型－－null，都没有找到任何对象有名为“madeUpPeoperty”的属性，因此最终返回 <CODE>undefined</CODE>。 </P>
<P>不论是在对象或对象的原型中，读取命名属性值的时候只返回首先找到的属性值。而当为对象的命名属性赋值时，如果对象自身不存在该属性则创建相应的属性。 </P>
<P>这意味着，如果执行像 <CODE>objectRef.testNumber = 3</CODE> 这样一条赋值语句，那么这个 <CODE>MyObject2</CODE> 的实例自身也会创建一个名为“testNumber”的属性，而之后任何读取该命名属性的尝试都将获得相同的新值。这时候，属性访问器不会再进一步搜索原型链，但 <CODE>MyObject1</CODE> 实例值为 <CODE>8</CODE> 的“testNumber”属性并没有被修改。给 <CODE>objectRef</CODE> 对象的赋值只是遮挡了其原型链中相应的属性。 </P>
<P>注意：ECMAScript 为 Object 类型定义了一个内部 <CODE>[[prototype]]</CODE> 属性。这个属性不能通过脚本直接访问，但在属性访问器解析过程中，则需要用到这个内部 <CODE>[[prototype]]</CODE> 属性所引用的对象链－－即原型链。可以通过一个公共的 <CODE>prototype</CODE> 属性，来对与内部的 <CODE>[[prototype]]</CODE> 属性对应的原型对象进行赋值或定义。这两者之间的关系在 ECMA 262（3rd edition）中有详细描述，但超出了本文要讨论的范畴。 </P>
</H3><H2><A   ><H3><A   ></A><P>执行环境是 ECMAScript 规范（ECMA 262 第 3 版）用于定义 ECMAScript 实现必要行为的一个抽象的概念。对如何实现执行环境，规范没有作规定。但由于执行环境中包含引用规范所定义结构的相关属性，因此执行环境中应该保有（甚至实现）带有属性的对象－－即使属性不是公共属性。 </P>
<P>所有 JavaScript 代码都是在一个执行环境中被执行的。全局代码（作为内置的 JS 文件执行的代码，或者 <SPAN title="HyperText Mark-up Language"><ABBR title="HyperText Mark-up Language">HTML</ABBR></SPAN> 页面加载的代码）是在我将称之为“全局执行环境”的执行环境中执行的，而对函数的每次调用（有可能是作为构造函数）同样有关联的执行环境。通过 <CODE>eval</CODE> 函数执行的代码也有截然不同的执行环境，但因为 JavaScript 程序员在正常情况下一般不会使用 <CODE>eval</CODE>，所以这里不作讨论。有关执行环境的详细说明请参阅 ECMA 262（第 3 版）第 10.2 节。 </P>
<P>当调用一个 JavaScript 函数时，该函数就会进入相应的执行环境。如果又调用了另外一个函数（或者递归地调用同一个函数），则又会创建一个新的执行环境，并且在函数调用期间执行过程都处于该环境中。当调用的函数返回后，执行过程会返回原始执行环境。因而，运行中的 JavaScript 代码就构成了一个执行环境栈。 </P>
<P>在创建执行环境的过程中，会按照定义的先后顺序完成一系列操作。首先，在一个函数的执行环境中，会创建一个“活动”对象。活动对象是规范中规定的另外一种机制。之所以称之为对象，是因为它拥有可访问的命名属性，但是它又不像正常对象那样具有原型（至少没有预定义的原型），而且不能通过 JavaScript 代码直接引用活动对象。 </P>
<P>为函数调用创建执行环境的下一步是创建一个 <CODE>arguments</CODE> 对象，这是一个类似数组的对象，它以整数索引的数组成员一一对应地保存着调用函数时所传递的参数。这个对象也有 <CODE>length</CODE> 和 <CODE>callee</CODE> 属性（这两个属性与我们讨论的内容无关，详见规范）。然后，会为活动对象创建一个名为“arguments”的属性，该属性引用前面创建的 <CODE>arguments</CODE> 对象。 </P>
<P>接着，为执行环境分配作用域。作用域由对象列表（链）组成。每个函数对象都有一个内部的 <CODE>[[scope]]</CODE> 属性（该属性我们稍后会详细介绍），这个属性也由对象列表（链）组成。指定给一个函数调用执行环境的作用域，由该函数对象的 <CODE>[[scope]]</CODE> 属性所引用的对象列表（链）组成，同时，活动对象被添加到该对象列表的顶部（链的前端）。 </P>
<P>之后会发生由 ECMA 262 中所谓“可变”对象完成的“变量实例化”的过程。只不过此时使用活动对象作为可变对象（这里很重要，请注意：它们是同一个对象）。此时会将函数的形式参数创建为可变对象命名属性，如果调用函数时传递的参数与形式参数一致，则将相应参数的值赋给这些命名属性（否则，会给命名属性赋 <CODE>undefined</CODE> 值）。对于定义的内部函数，会以其声明时所用名称为可变对象创建同名属性，而相应的内部函数则被创建为函数对象并指定给该属性。变量实例化的最后一步是将在函数内部声明的所有局部变量创建为可变对象的命名属性。 </P>
<P>根据声明的局部变量创建的可变对象的属性在变量实例化过程会被赋予 <CODE>undefined</CODE> 值。在执行函数体内的代码、并计算相应的赋值表达式之前不会对局部变量执行真正的实例化。 </P>
<P>事实上，拥有 <CODE>arguments</CODE> 属性的活动对象和拥有与函数局部变量对应的命名属性的可变对象是同一个对象。因此，可以将标识符 <CODE>arguments</CODE> 作为函数的局部变量来看待。 </P><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#">回到顶部</A> 
<P>最后，在this可以被使用之前，还必须先对其赋值。如果赋的值是一个对象的引用，则 this.m 访问的便是该对象上的 m。如果（内部）赋的值是 null，则this就指向全局对象。 （此段由 <A href="http://blog.csdn.net/pongba">pangba 刘未鹏</A> 翻译） </P>
<P a value is assigned for use with the this keyword. If the value assigned refers to an object then property accessors prefixed with the this keyword reference properties of that object. If the value assigned (internally) is null then the this keyword will refer to the global object. ） ></P>
<P>创建全局执行环境的过程会稍有不同，因为它没有参数，所以不需要通过定义的活动对象来引用这些参数。但全局执行环境也需要一个作用域，而它的作用域链实际上只由一个对象－－全局对象－－组成。全局执行环境也会有变量实例化的过程，它的内部函数就是涉及大部分 JavaScript 代码的、常规的顶级函数声明。而且，在变量实例化过程中全局对象就是可变对象，这就是为什么全局性声明的函数是全局对象属性的原因。全局性声明的变量同样如此。 </P>
<P>全局执行环境也会使用 <CODE>this</CODE> 对象来引用全局对象。 </P>
</H3><H3><A [[scope]]&gt;</A></H3>
</A><P>调用函数时创建的执行环境会包含一个作用域链，这个作用域链是通过将该执行环境的活动（可变）对象添加到保存于所调用函数对象的 <CODE>[[scope]]</CODE> 属性中的作用域链前端而构成的。所以，理解函数对象内部的 <CODE>[[scope]]</CODE> 属性的定义过程至关重要。 </P>
<P>在 ECMAScript 中，函数也是对象。函数对象在变量实例化过程中会根据函数声明来创建，或者是在计算函数表达式或调用 <CODE>Function</CODE> 构造函数时创建。 </P>
<P>通过调用 <CODE>Function</CODE> 构造函数创建的函数对象，其内部的 <CODE>[[scope]]</CODE> 属性引用的作用域链中始终只包含全局对象。 </P>
<P>通过函数声明或函数表达式创建的函数对象，其内部的 <CODE>[[scope]]</CODE> 属性引用的则是创建它们的执行环境的作用域链。 </P>
<P>在最简单的情况下，比如声明如下全局函数：- </P><PRE>function exampleFunction(formalParameter){
    ...   <SPAN 函数体内的代码></SPAN>
}
</PRE>
<P>当为创建全局执行环境而进行变量实例化时，会根据上面的函数声明创建相应的函数对象。因为全局执行环境的作用域链中只包含全局对象，所以它就给自己创建的、并以名为“exampleFunction”的属性引用的这个函数对象的内部 <CODE>[[scope]]</CODE> 属性，赋予了只包含全局对象的作用域链。 </P>
<P>当在全局环境中计算函数表达式时，也会发生类似的指定作用域链的过程：- </P><PRE>var exampleFuncRef = function(){
    ...   <SPAN 函数体代码></SPAN>
}
</PRE>
<P>在这种情况下，不同的是在全局执行环境的变量实例化过程中，会先为全局对象创建一个命名属性。而在计算赋值语句之前，暂时不会创建函数对象，也不会将该函数对象的引用指定给全局对象的命名属性。但是，最终还是会在全局执行环境中创建这个函数对象（当计算函数表达式时。译者注），而为这个创建的函数对象的 <CODE>[[scope]]</CODE> 属性指定的作用域链中仍然只包含全局对象。 </P>
<P>内部的函数声明或表达式会导致在包含它们的外部函数的执行环境中创建相应的函数对象，因此这些函数对象的作用域链会稍微复杂一些。在下面的代码中，先定义了一个带有内部函数声明的外部函数，然后调用外部函数： </P><PRE>function exampleOuterFunction(formalParameter){
    function exampleInnerFuncitonDec(){
        ... <SPAN 内部函数体代码></SPAN>
    }
    ...  <SPAN 其余的外部函数体代码></SPAN>
}

exampleOuterFunction( 5 );
</PRE>
<P>与外部函数声明对应的函数对象会在全局执行环境的变量实例化过程中被创建。因此，外部函数对象的 <CODE>[[scope]]</CODE> 属性中会包含一个只有全局对象的“单项目”作用域链。 </P>
<P>当在全局执行环境中调用 <CODE>exampleOuterFunction</CODE> 函数时，会为该函数调用创建一个新的执行环境和一个活动（可变）对象。这个新执行环境的作用域就由新的活动对象后跟外部函数对象的 <CODE>[[scope]]</CODE> 属性所引用的作用域链（只有全局对象）构成。在新执行环境的变量实例化过程中，会创建一个与内部函数声明对应的函数对象，而同时会给这个函数对象的 <CODE>[[scope]]</CODE> 属性指定创建该函数对象的执行环境（即新执行环境。译者注）的作用域值－－即一个包含活动对象后跟全局对象的作用域链。 </P>
<P>到目前为止，所有过程都是自动、或者由源代码的结构所控制的。但我们发现，执行环境的作用域链定义了执行环境所创建的函数对象的 <CODE>[[scope]]</CODE> 属性，而函数对象的 <CODE>[[scope]]</CODE> 属性则定义了它的执行环境的作用域（包括相应的活动对象）。不过，ECMAScript 也提供了用于修改作用域链 <CODE>with</CODE> 语句。 </P>
<P><CODE>with</CODE> 语句会计算一个表达式，如果该表达式是一个对象，那么就将这个对象添加到当前执行环境的作用域链中（在活动&lt;可变&gt;对象之前）。然后，执行 <CODE>with</CODE> 语句（它自身也可能是一个语句块）中的其他语句。之后，又恢复到调用它之前的执行环境的作用域链中。 </P>
<P><CODE>with</CODE> 语句不会影响在变量实例化过程中根据函数声明创建函数对象。但是，可以在一个 <CODE>with</CODE> 语句内部对函数表达式求值：- </P><PRE><SPAN 创建全局变量 - y - 它引用一个对象：- */></SPAN>
var y = {x:5}; <SPAN 带有一个属性 - x - 的对象直接量></SPAN>
function exampleFuncWith(){
    var z;
    <SPAN 将全局对象 - y - 引用的对象添加到作用域链的前端：- */></SPAN>
    with(y){
        <SPAN 对函数表达式求值，以创建函数对象并将该函数对象的引用指定给局部变量 - z - :-  */></SPAN>
        z = function(){
            ... <SPAN 内部函数表达式中的代码;></SPAN>
        }
    }
    ... 
}

<SPAN 执行 - exampleFuncWith - 函数:- */></SPAN>
exampleFuncWith();
</PRE>
<P>在调用 <CODE>exampleFuncWith</CODE> 函数所创建的执行环境中包含一个由其活动对象后跟全局对象构成的作用域链。而在执行 <CODE>with</CODE> 语句时，又会把全局变量 <CODE>y</CODE> 引用的对象添加到这个作用域链的前端。在对其中的函数表达式求值的过程中，所创建函数对象的 <CODE>[[scope]]</CODE> 属性与创建它的执行环境的作用域保持一致－－即，该属性会引用一个由对象 <CODE>y</CODE> 后跟调用外部函数时所创建执行环境的活动对象，后跟全局对象的作用域链。 </P>
<P>当与 <CODE>with</CODE> 语句相关的语句块执行结束时，执行环境的作用域得以恢复（<CODE>y</CODE> 会被移除），但是已经创建的函数对象（<CODE>z</CODE>。译者注）的 <CODE>[[scope]]</CODE> 属性所引用的作用域链中位于最前面的仍然是对象 <CODE>y</CODE>。 </P>
</H2><H3><A   ></A><P>标识符是沿作用域链逆向解析的。ECMA 262 将 <CODE>this</CODE> 归类为关键字而不是标识符，并非不合理。因为解析 <CODE>this</CODE> 值时始终要根据使用它的执行环境来判断，而与作用域链无关。 </P>
<P>标识符解析从作用域链中的第一个对象开始。检查该对象中是否包含与标识符对应的属性名。因为作用域链是一条对象链，所以这个检查过程也会包含相应对象的原型链（如果有）。如果没有在作用域链的第一个对象中发现相应的值，解析过程会继续搜索下一个对象。这样依次类推直至找到作用域链中包含以标识符为属性名的对象为止，也有可能在作用域链的所有对象中都没有发现该标识符。 </P>
<P>当基于对象使用属性访问器时，也会发生与上面相同的标识符解析过程。当属性访问器中有相应的属性可以替换某个对象时，这个属性就成为表示该对象的标识符，该对象在作用域链中的位置进而被确定。全局对象始终都位于作用域链的尾端。 </P>
<P>因为与函数调用相关的执行环境将会把活动（可变）对象添加到作用域链的前端，所以在函数体内使用的标识符会首先检查自己是否与形式参数、内部函数声明的名称或局部变量一致。这些都可以由活动（可变）对象的命名属性来确定。 </P>
</H3><H2><A   ><H3><A   ></A><P>ECMAScript 要求使用自动垃圾收集机制。但规范中并没有详细说明相关的细节，而是留给了实现来决定。但据了解，相当一部分实现对它们的垃圾收集操作只赋予了很低的优先级。但是，大致的思想都是相同的，即如果对象不再“可引用（由于不存在对它的引用，使执行代码无法再访问到它）”时，该对象就成为垃圾收集的目标。因而，在将来的某个时刻会将这个对象销毁并将它所占用的一切资源释放，以便操作系统重新利用。 </P>
<P>正常情况下，当退出一个执行环境时就会满足类似的条件。此时，作用域链结构中的活动（可变）对象以及在该执行环境中创建的任何对象－－包括函数对象，都不再“可引用”，因此将成为垃圾收集的目标。 </P>
</H3><H3><A   ></A><P>闭包是通过在对一个函数调用的执行环境中返回一个函数对象构成的。比如，在对函数调用的过程中，将一个对内部函数对象的引用指定给另一个对象的属性。或者，直接将这样一个（内部）函数对象的引用指定给一个全局变量、或者一个全局性对象的属性，或者一个作为参数以引用方式传递给外部函数的对象。例如：- </P><PRE>function exampleClosureForm(arg1, arg2){
    var localVar = 8;
    function exampleReturned(innerArg){
        return ((arg1 + arg2)/(innerArg + localVar));
    }
    <SPAN 返回一个定义为 exampleReturned 的内部函数的引用 -:-  */></SPAN>
    return exampleReturned;
}

var globalVar = exampleClosureForm(2, 4);
</PRE>
<P>这种情况下，在调用外部函数 <CODE>exampleClosureForm</CODE> 的执行环境中所创建的函数对象就不会被当作垃圾收集，因为该函数对象被一个全局变量所引用，而且仍然是可以访问的，甚至可以通过 <CODE>globalVar(n)</CODE> 来执行。 </P>
<P>的确，情况比正常的时候要复杂一些。因为现在这个被变量 <CODE>globalVar</CODE> 引用的内部函数对象的 <CODE>[[scope]]</CODE> 属性所引用的作用域链中，包含着属于创建该内部函数对象的执行环境的活动对象（和全局对象）。由于在执行被 <CODE>globalVar</CODE> 引用的函数对象时，每次都要把该函数对象的 <CODE>[[scope]]</CODE> 属性所引用的整个作用域链添加到创建的（内部函数的）执行环境的作用域中（即此时的作用域中包括：内部执行环境的活动对象、外部执行环境的活动对象、全局对象。译者注）， 所以这个（外部执行环境的）活动对象不会被当作垃圾收集。 </P>
<P>闭包因此而构成。此时，内部函数对象拥有自由的变量，而位于该函数作用域链中的活动（可变）对象则成为与变量绑定的环境。 </P>
<P>由于活动（可变）对象受限于内部函数对象（现在被 <CODE>globalVar</CODE> 变量引用）的 <CODE>[[scope]]</CODE> 属性中作用域链的引用，所以活动对象连同它的变量声明－－即属性的值，都会被保留。而在对内部函数调用的执行环境中进行作用域解析时，将会把与活动（可变）对象的命名属性一致的标识符作为该对象的属性来解析。活动对象的这些属性值即使是在创建它的执行环境退出后，仍然可以被读取和设置。 </P>
<P>在上面的例子中，当外部函数返回（退出它的执行环境）时，其活动（可变）对象的变量声明中记录了形式参数、内部函数定义以及局部变量的值。<CODE>arg1</CODE> 属性的值为 <CODE>2</CODE>，而 <CODE>arg2</CODE> 属性的值为 <CODE>4</CODE>，<CODE>localVar</CODE> 的值是 <CODE>8</CODE>，还有一个 <CODE>exampleReturned</CODE> 属性，它引用由外部函数返回的内部函数对象。（为方便起见，我们将在后面的讨论中，称这个活动&lt;可变&gt;对象为 "ActOuter1"）。 </P>
<P>如果再次调用 <CODE>exampleClosureForm</CODE> 函数，如：- </P><PRE>var secondGlobalVar = exampleClosureForm(12, 3);
</PRE>
<P>- 则会创建一个新的执行环境和一个新的活动对象。而且，会返回一个新的函数对象，该函数对象的 <CODE>[[scope]]</CODE> 属性引用的作用域链与前一次不同，因为这一次的作用域链中包含着第二个执行环境的活动对象，而这个活动对象的属性 <CODE>arg1</CODE> 值为 <CODE>12</CODE> 而属性 <CODE>arg2</CODE> 值为 <CODE>3</CODE>。（为方便起见，我们将在后面的讨论中，称这个活动&lt;可变&gt;对象为 "ActOuter2"）。 </P>
<P>通过第二次执行 <CODE>exampleClosureForm</CODE> 函数，第二个、也是截然不同的闭包诞生了。 </P>
<P>通过执行 <CODE>exampleClosureForm</CODE> 创建的两个函数对象分别被指定给了全局变量 <CODE>globalVar</CODE> 和 <CODE>secondGlobalVar</CODE>，并返回了表达式 <CODE>((arg1 + arg2)/(innerArg + localVar))</CODE>。该表达式对其中的四个标识符应用了不同的操作符。如何确定这些标识符的值是体现闭包价值的关键所在。 </P>
<P>我们来看一看，在执行由 <CODE>globalVar</CODE> 引用的函数对象－－如 <CODE>globalVar(2)</CODE>－－时的情形。此时，会创建一个新的执行环境和相应的活动对象（我们将称之为“ActInner1”），并把该活动对象添加到执行的函数对象的 <CODE>[[scope]]</CODE> 属性所引用的作用域链的前端。ActInner1 会带有一个属性 <CODE>innerArg</CODE>，根据传递的形式参数，其值被指定为 <CODE>2</CODE>。这个新执行环境的作用域链变成： <SPAN ></SPAN></P>
<P>为了返回表达式 <CODE>((arg1 + arg2)/(innerArg + localVar))</CODE> 的值，要沿着作用域链进行标识符解析。表达式中标识符的值将通过依次查找作用域链中每个对象（与标识符名称一致）的属性来确定。 </P>
<P>作用域链中的第一个对象是 ActInner1，它有一个名为 <CODE>innerArg</CODE> 的属性，值是 <CODE>2</CODE>。所有其他三个标识符在 ActOuter1 中都有对应的属性：<CODE>arg1</CODE> 是 <CODE>2</CODE>，<CODE>arg2</CODE> 是 <CODE>4</CODE> 而 <CODE>localVar</CODE> 是 <CODE>8</CODE>。最后，函数调用返回 <CODE>((2 + 2)/(2 + 8))</CODE>。 </P>
<P>现在再来看一看由 <CODE>secondGlobalVar</CODE> 引用的同一个函数对象的执行情况，比如 <CODE>secondGlobalVar(5)</CODE>。我们把这次创建的新执行环境的活动对象称为 “ActInner2”，相应的作用域链就变成了：<SPAN 返回 ><CODE>innerArg</CODE> 的值 <CODE>5</CODE>，而 ActOuter2 分别返回 <CODE>arg1</CODE>、<CODE>arg2</CODE> 和 <CODE>localVar</CODE> 的值 <CODE>12</CODE>、<CODE>3</CODE> 和 <CODE>8</CODE>。函数调用返回的值就是 <CODE>((12 + 3)/(5 + 8))</CODE>。 </SPAN></P>
<P>如果再执行一次 <CODE>secondGlobalVar</CODE>，则又会有一个新活动对象被添加到作用域链的前端，但 ActOuter2 仍然是链中的第二个对象，而他的命名属性会再次用于完成标识符 <CODE>arg1</CODE>、<CODE>arg2</CODE> 和 <CODE>localVar</CODE> 的解析。 </P>
<P>这就是 ECMAScript 的内部函数获取、维持和访问创建他们的执行环境的形式参数、声明的内部函数以及局部变量的过程。这个过程说明了构成闭包以后，内部的函数对象在其存续过程中，如何维持对这些值的引用、如何对这些值进行读取的机制。即，创建内部函数对象的执行环境的活动（可变）对象，会保留在该函数对象的 <CODE>[[scope]]</CODE> 属性所引用的作用域链中。直到所有对这个内部函数的引用被释放，这个函数对象才会成为垃圾收集的目标（连同它的作用域链中任何不再需要的对象）。 </P>
<P>内部函数自身也可能有内部函数。在通过函数执行返回内部函数构成闭包以后，相应的闭包自身也可能会返回内部函数从而构成它们自己的闭包。每次作用域链嵌套，都会增加由创建内部函数对象的执行环境引发的新活动对象。ECMAScript 规范要求作用域链是临时性的，但对作用域链的长度却没有加以限制。在具体实现中，可能会存在实际的限制，但还没有发现有具体限制数量的报告。目前来看，嵌套的内部函数所拥有的潜能，仍然超出了使用它们的人的想像能力。 </P>
</H3><H2><A   ></A><P>对这个问题的回答可能会令你惊讶－－闭包什么都可以做。据我所知，闭包使得 ECMAScript 能够模仿任何事物，因此局限性在于设计和实现要模仿事物的能力。只是从字面上看可能会觉得这么说很深奥，下面我们就来看一些更有实际意义的例子。 </P>
</H2><H3><A 1：为函数引用设置延时></A></H3>
</A><P>闭包的一个常见用法是在执行函数之前为要执行的函数提供参数。例如：将函数作为 <CODE>setTimout</CODE> 函数的第一个参数，这在 Web 浏览器的环境下是非常常见的一种应用。 </P>
<P><CODE>setTimeout</CODE> 用于有计划地执行一个函数（或者一串 JavaScript 代码，不是在本例中），要执行的函数是其第一个参数，其第二个参数是以毫秒表示的执行间隔。也就是说，当在一段代码中使用 <CODE>setTimeout</CODE> 时，要将一个函数的引用作为它的第一个参数，而将以毫秒表示的时间值作为第二个参数。但是，传递函数引用的同时无法为计划执行的函数提供参数。 </P>
<P>然而，可以在代码中调用另外一个函数，由它返回一个对内部函数的引用，再把这个对内部函数对象的引用传递给 <CODE>setTimeout</CODE> 函数。执行这个内部函数时要使用的参数在调用返回它的外部函数时传递。这样，<CODE>setTimeout</CODE> 在执行这个内部函数时，不用传递参数，但该内部函数仍然能够访问在调用返回它的外部函数时传递的参数： </P><PRE>function callLater(paramA, paramB, paramC){
    <SPAN 返回一个由函数表达式创建的匿名内部函数的引用:- */  ></SPAN>
    return (function(){
        <SPAN 这个内部函数将通过 - setTimeout - 执行，           而且当它执行时它会读取并按照传递给           外部函数的参数行事：          */></SPAN>
        paramA[paramB] = paramC;
    });
}

...

<SPAN 调用这个函数将返回一个在其执行环境中创建的内部函数对象的引用。   传递的参数最终将作为外部函数的参数被内部函数使用。   返回的对内部函数的引用被赋给一个全局变量:-  */  ></SPAN>
var functRef = callLater(elStyle, "display", "none");
<SPAN 调用 setTimeout 函数，将赋给变量 - functRef -   的内部函数的引用作为传递的第一个参数:- */   ></SPAN>
hideMenu=setTimeout(functRef, 500);
</PRE>
</H2><H3><A 2: 通过对象实例方法关联函数></A></H3><A href="http://www.cn-cuckoo.com/wordpress/wp-content/uploads/2007/08/JavaScriptClosures.html#">回到顶部</A> 
<P>许多时候我们需要将一个函数对象暂时挂到一个引用上留待后面执行，因为不等到执行的时候是很难知道其具体参数的，而先前将它赋给那个引用的时候更是压根不知道的。 （此段由 <A href="http://blog.csdn.net/pongba">pangba 刘未鹏</A> 翻译） </P>
<P>（luyy朋友的翻译_2008-7-7更新）很多时候需要将一个函数引用进行赋值，以便在将来某个时候执行该函数，在执行这些函数时给函数提供参数将会是有用处的，但这些参数在执行时不容易获得，他们只有在上面赋值给时才能确定。 </P>
<P are many other circumstances when a reference to a function object is assigned so that it would be executed at some future time where it is useful to provide parameters for the execution of that function that would not be easily available at the time of execution but cannot be known until the moment of assignment.）></P>
<P>一个相关的例子是，用 JavaScript 对象来封装与特定 DOM 元素的交互。这个 JavaScript 对象具有 <CODE>doOnClick</CODE>、<CODE>doMouseOver</CODE> 和 <CODE>doMouseOut</CODE> 方法，并且当用户在该特定的 DOM 元素中触发了相应的事件时要执行这些方法。不过，可能会创建与不同的 DOM 元素关联的任意数量的 JavaScript 对象，而且每个对象实例并不知道实例化它们的代码将会如何操纵它们（即注册事件处理函数与定义相应的事件处理函数分离。译者注）。这些对象实例并不知道如何在全局环境中引用它们自身，因为它们不知道将会指定哪个全局变量（如果有）引用它们的实例。 </P>
<P>因而问题可以归结为执行一个与特定的 JavaScript 对象关联的事件处理函数，并且要知道调用该对象的哪个方法。</P>
<P>下面这个例子使用了一个基于闭包构建的一般化的函数（此句多谢未鹏指点），该函数会将对象实例与 DOM 元素事件关联起来，安排执行事件处理程序时调用对象实例的指定方法，给象的指定方法传递的参数是事件对象和与元素关联的引用，该函数返回执行相应方法后的返回值。 </P><PRE><SPAN 一个关联对象实例和事件处理器的函数。   它返回的内部函数被用作事件处理器。对象实例以 - obj - 参数表示，   而在该对象实例中调用的方法名则以 - methodName - （字符串）参数表示。   */   ></SPAN>
function associateObjWithEvent(obj, methodName){
    <SPAN 下面这个返回的内部函数将作为一个 DOM 元素的事件处理器*/   ></SPAN>
    return (function(e){
        <SPAN    ></SPAN>
        e = e||window.event;
        <SPAN 事件处理器通过保存在字符串 - methodName - 中的方法名调用了对象         - obj - 的一个方法。并传递已经规范化的事件对象和触发事件处理器的元素         的引用 - this - （之所以 this 有效是因为这个内部函数是作为该元素的方法执行的）        */   ></SPAN>
        return obj[methodName](e, this);
    });
}

<SPAN 这个构造函数用于创建将自身与 DOM 元素关联的对象，      DOM 元素的 ID 作为构造函数的字符串参数。      所创建的对象会在相应的元素触发 onclick、      onmouseover 或 onmouseout 事件时，      调用相应的方法。   */   ></SPAN>
function DhtmlObject(elementId){
    <SPAN 调用一个返回 DOM 元素（如果没找到返回 null）引用的函数，      必需的参数是 ID。 将返回的值赋给局部变量 - el -。       */ ></SPAN>
    var el = getElementWithId(elementId);
    <SPAN ></SPAN>
    if(el){
        <SPAN 为给元素的事件处理器指定一个函数，该对象调用了        - associateObjWithEvent - 函数。        同时对象将自身（通过 - this - 关键字）作为调用方法的对象，        并提供了调用的方法名称。 - associateObjWithEvent - 函数会返回        一个内部函数，该内部函数被指定为 DOM 元素的事件处理器。        在响应事件时，执行这个内部函数就会调用必要的方法。        */></SPAN>
        el.onclick = associateObjWithEvent(this, "doOnClick");
        el.onmouseover = associateObjWithEvent(this, "doMouseOver");
        el.onmouseout = associateObjWithEvent(this, "doMouseOut");
        ...
    }
}
DhtmlObject.prototype.doOnClick = function(event, element){
    ... <SPAN doOnClick 方法体。></SPAN>.
}
DhtmlObject.prototype.doMouseOver = function(event, element){
    ... <SPAN doMouseOver 方法体。></SPAN>
}
DhtmlObject.prototype.doMouseOut = function(event, element){
    ... <SPAN doMouseOut 方法体。></SPAN>
}
</PRE>
<P>这样，<CODE>DhtmlObject</CODE> 的任何实例都会将自身与相应的 DOM 元素关联起来，而这些 DOM 元素不必知道其他代码如何操纵它们（即当触发相应事件时，会执行什么代码。译者注），也不必理会全局命名空间的影响以及与 <CODE>DhtmlObject</CODE> 的其他实例间存在冲突的危险。 </P>
<H3><A 3：包装相关的功能></A></H3>
<P>闭包可以用于创建额外的作用域，通过该作用域可以将相关的和具有依赖性的代码组织起来，以便将意外交互的风险降到最低。假设有一个用于构建字符串的函数，为了避免重复性的连接操作（和创建众多的中间字符串），我们的愿望是使用一个数组按顺序来存储字符串的各个部分，然后再使用 <CODE>Array.prototype.join</CODE> 方法（以空字符串作为其参数）输出结果。这个数组将作为输出的缓冲器，但是将数组作为函数的局部变量又会导致在每次调用函数时都重新创建一个新数组，这在每次调用函数时只重新指定数组中的可变内容的情况下并不是必要的。 </P>
<P>一种解决方案是将这个数组声明为全局变量，这样就可以重用这个数组，而不必每次都建立新数组。但这个方案的结果是，除了引用函数的全局变量会使用这个缓冲数组外，还会多出一个全局属性引用数组自身。如此不仅使代码变得不容易管理，而且，如果要在其他地方使用这个数组时，开发者必须要再次定义函数和数组。这样一来，也使得代码不容易与其他代码整合，因为此时不仅要保证所使用的函数名在全局命名空间中是唯一的，而且还要保证函数所依赖的数组在全局命名空间中也必须是唯一的。 </P>
<P>而通过闭包可以使作为缓冲器的数组与依赖它的函数关联起来（优雅地打包），同时也能够维持在全局命名空间外指定的缓冲数组的属性名，免除了名称冲突和意外交互的危险。 </P>
<P>其中的关键技巧在于通过执行一个单行（in-line）函数表达式创建一个额外的执行环境，而将该函数表达式返回的内部函数作为在外部代码中使用的函数。此时，缓冲数组被定义为函数表达式的一个局部变量。这个函数表达式只需执行一次，而数组也只需创建一次，就可以供依赖它的函数重复使用。 </P>
<P>下面的代码定义了一个函数，这个函数用于返回一个 <SPAN title="HyperText Mark-up Language"><ABBR title="HyperText Mark-up Language">HTML</ABBR></SPAN> 字符串，其中大部分内容都是常量，但这些常量字符序列中需要穿插一些可变的信息，而可变的信息由调用函数时传递的参数提供。 </P>
<P>通过执行单行函数表达式返回一个内部函数，并将返回的函数赋给一个全局变量，因此这个函数也可以称为全局函数。而缓冲数组被定义为外部函数表达式的一个局部变量。它不会暴露在全局命名空间中，而且无论什么时候调用依赖它的函数都不需要重新创建这个数组。 </P><PRE><SPAN 声明一个全局变量 - getImgInPositionedDivHtml -   并将一次调用一个外部函数表达式返回的内部函数赋给它。       这个内部函数会返回一个用于表示绝对定位的 DIV 元素     包围着一个 IMG 元素 的 ><SPAN title="HyperText Mark-up Language"><ABBR title="HyperText Mark-up Language">HTML</ABBR></SPAN> 字符串，这样一来，
   所有可变的属性值都由调用该函数时的参数提供：
*/</SPAN>
var getImgInPositionedDivHtml = (function(){
     [ http://img.bimg.126.net/photo/oeVtR29iQQ_AJmg6PlXx-w==/1424263382157276883.jpg+ZG+JLS+KPB+ZYB+ ] </SPAN>
    var buffAr = [
        '&lt;div id="',
        '',   <SPAN 1, DIV ID 属性></SPAN>
        '" style="position:absolute;top:',
        '',   <SPAN 3, DIV 顶部位置></SPAN>
        'px;left:',
        '',   <SPAN 5, DIV 左端位置></SPAN>
        'px;width:',
        '',   <SPAN 7, DIV 宽度></SPAN>
        'px;height:',
        '',   <SPAN 9, DIV 高度></SPAN>
        'px;overflow:hidden;\"&gt;&lt;img src=\"',
        '',   <SPAN 11, IMG URL></SPAN>
        '\" width=\"',
        '',   <SPAN 13, IMG 宽度></SPAN>
        '\" height=\"',
        '',   <SPAN 15, IMG 调蓄></SPAN>
        '\" alt=\"',
        '',   <SPAN 17, IMG alt 文本内容></SPAN>
        '\"&gt;&lt;\/div&gt;'
    ];
    <SPAN 返回作为对函数表达式求值后结果的内部函数对象。   这个内部函数就是每次调用执行的函数   - getImgInPositionedDivHtml( ... ) -      */></SPAN>
    return (function(url, id, width, height, top, left, altText){
        <SPAN 将不同的参数插入到缓冲数组相应的位置：          */></SPAN>
        buffAr[1] = id;
        buffAr[3] = top;
        buffAr[5] = left;
        buffAr[13] = (buffAr[7] = width);
        buffAr[15] = (buffAr[9] = height);
        buffAr[11] = url;
        buffAr[17] = altText;
        <SPAN 返回通过使用空字符串（相当于将数组元素连接起来）    连接数组每个元素后形成的字符串：          */></SPAN>
        return buffAr.join('');
    }); <SPAN   })();  ><SPAN :单行外部函数表达式。*/></SPAN>
</PRE>
<P>如果一个函数依赖于另一（或多）个其他函数，而其他函数又没有必要被其他代码直接调用，那么可以运用相同的技术来包装这些函数，而通过一个公开暴露的函数来调用它们。这样，就将一个复杂的多函数处理过程封装成了一个具有移植性的代码单元。 </P>
<H3><A   ></A><P>有关闭包的一个可能是最广为人知的应用是 <A href="http://www.crockford.com/javascript/private.html">Douglas Crockford's technique for the emulation of private instance variables in ECMAScript objects</A>。这种应用方式可以扩展到各种嵌套包含的可访问性（或可见性）的作用域结构，包括 <A href="http://www.litotes.demon.co.uk/js_info/private_static.html">the emulation of private static members for ECMAScript objects</A>。 </P>
<P>闭包可能的用途是无限的，可能理解其工作原理才是把握如何使用它的最好指南。 </P>
</H3><H2><A   ></A><P>在创建可访问的内部函数的函数体之外解析该内部函数就会构成闭包。这表明闭包很容易创建，但这样一来可能会导致一种结果，即没有认识到闭包是一种语言特性的 JavaScript 作者，会按照内部函数能完成多种任务的想法来使用内部函数。但他们对使用内部函数的结果并不明了，而且根本意识不到创建了闭包，或者那样做意味着什么。 </P>
<P>正如下一节谈到 IE 中内存泄漏问题时所提及的，意外创建的闭包可能导致严重的负面效应，而且也会影响到代码的性能。问题不在于闭包本身，如果能够真正做到谨慎地使用它们，反而会有助于创建高效的代码。换句话说，使用内部函数会影响到效率。 </P>
<P>使用内部函数最常见的一种情况就是将其作为 DOM 元素的事件处理器。例如，下面的代码用于向一个链接元素添加 onclick 事件处理器： </P><PRE><SPAN 定义一个全局变量，通过下面的函数将它的值     作为查询字符串的一部分添加到链接的 - href - 中：  */></SPAN>
var quantaty = 5;
<SPAN 当给这个函数传递一个链接（作为函数中的参数 - linkRef -）时，     会将一个 onclick 事件处理器指定给该链接，该事件处理器     将全局变量 - quantaty - 的值作为字符串添加到链接的 - href -      属性中，然后返回 true 使该链接在单击后定位到由  - href -      属性包含的查询字符串指定的资源：  */></SPAN>
function addGlobalQueryOnClick(linkRef){
    <SPAN 如果可以将参数 - linkRef - 通过类型转换为 ture        （说明它引用了一个对象）：      */></SPAN>
    if(linkRef){
        <SPAN 对一个函数表达式求值，并将对该函数对象的引用             指定给这个链接元素的 onclick 事件处理器：          */></SPAN>
        linkRef.onclick = function(){
            <SPAN 这个内部函数表达式将查询字符串                 添加到附加事件处理器的元素的 - href - 属性中：              */></SPAN>
            this.href += ('?quantaty='+escape(quantaty));
            return true;
        };
    }
}
</PRE>
<P>无论什么时候调用 <CODE>addGlobalQueryOnClick</CODE> 函数，都会创建一个新的内部函数（通过赋值构成了闭包）。从效率的角度上看，如果只是调用一两次 <CODE>addGlobalQueryOnClick</CODE> 函数并没有什么大的妨碍，但如果频繁使用该函数，就会导致创建许多截然不同的函数对象（每对内部函数表达式求一次值，就会产生一个新的函数对象）。 </P>
<P>上面例子中的代码没有关注内部函数在创建它的函数外部可以访问（或者说构成了闭包）这一事实。实际上，同样的效果可以通过另一种方式来完成。即单独地定义一个用于事件处理器的函数，然后将该函数的引用指定给元素的事件处理属性。这样，只需创建一个函数对象，而所有使用相同事件处理器的元素都可以共享对这个函数的引用： </P><PRE><SPAN 定义一个全局变量，通过下面的函数将它的值     作为查询字符串的一部分添加到链接的 - href - 中：  */></SPAN>
var quantaty = 5;

<SPAN 当把一个链接（作为函数中的参数 - linkRef -）传递给这个函数时，     会给这个链接添加一个 onclick 事件处理器，该事件处理器会     将全局变量  - quantaty - 的值作为查询字符串的一部分添加到     链接的 - href -  中，然后返回 true，以便单击链接时定位到由     作为 - href - 属性值的查询字符串所指定的资源：  */></SPAN>
function addGlobalQueryOnClick(linkRef){
    <SPAN 如果 - linkRef - 参数能够通过类型转换为 true      （说明它引用了一个对象）：      */></SPAN>
    if(linkRef){
        <SPAN 将一个对全局函数的引用指定给这个链接             的事件处理属性，使函数成为链接元素的事件处理器：          */></SPAN>
        linkRef.onclick = forAddQueryOnClick;
    }
}
<SPAN 声明一个全局函数，作为链接元素的事件处理器，     这个函数将一个全局变量的值作为要添加事件处理器的     链接元素的  - href - 值的一部分：  */></SPAN>
function forAddQueryOnClick(){
    this.href += ('?quantaty='+escape(quantaty));
    return true;
}
</PRE>
<P>在上面例子的第一个版本中，内部函数并没有作为闭包发挥应有的作用。在那种情况下，反而是不使用闭包更有效率，因为不用重复创建许多本质上相同的函数对象。 </P>
<P>类似地考量同样适用于对象的构造函数。与下面代码中的构造函数框架类似的代码并不罕见： </P><PRE>function ExampleConst(param){
    <SPAN 通过对函数表达式求值创建对象的方法，         并将求值所得的函数对象的引用赋给要创建对象的属性：      */></SPAN>
    this.method1 = function(){
        ... <SPAN 方法体。></SPAN>
    };
    this.method2 = function(){
        ... <SPAN 方法体。></SPAN>
    };
    this.method3 = function(){
        ... <SPAN 方法体。></SPAN>
    };
    <SPAN 把构造函数的参数赋给对象的一个属性：      */></SPAN>
    this.publicProp = param;
}
</PRE>
<P>每当通过 <CODE>new ExampleConst(n)</CODE> 使用这个构造函数创建一个对象时，都会创建一组新的、作为对象方法的函数对象。因此，创建的对象实例越多，相应的函数对象也就越多。 </P>
<P>Douglas Crockford 提出的模仿 JavaScript 对象私有成员的技术，就利用了将对内部函数的引用指定给在构造函数中构造对象的公共属性而形成的闭包。如果对象的方法没有利用在构造函数中形成的闭包，那么在实例化每个对象时创建的多个函数对象，会使实例化过程变慢，而且将有更多的资源被占用，以满足创建更多函数对象的需要。 </P>
<P>这那种情况下，只创建一次函数对象，并把它们指定给构造函数 <CODE>prototype</CODE> 的相应属性显然更有效率。这样一来，它们就能被构造函数创建的所有对象共享了： </P><PRE>function ExampleConst(param){
    <SPAN 将构造函数的参数赋给对象的一个属性：      */></SPAN>
    this.publicProp = param;
}
<SPAN 通过对函数表达式求值，并将结果函数对象的引用     指定给构造函数原型的相应属性来创建对象的方法：  */></SPAN>
ExampleConst.prototype.method1 = function(){
    ... <SPAN 方法体。></SPAN>
};
ExampleConst.prototype.method2 = function(){
    ... <SPAN 方法体。></SPAN>
};
ExampleConst.prototype.method3 = function(){
    ... <SPAN 方法体。></SPAN>
};

</PRE>
</H2><H2><A Explorer 的内存泄漏问题 ></A></H2>
<P>Internet Explorer Web 浏览器（在 IE 4 到 IE 6 中核实）的垃圾收集系统中存在一个问题，即如果 ECMAScript 和某些宿主对象构成了 "循环引用"，那么这些对象将不会被当作垃圾收集。此时所谓的宿主对象指的是任何 DOM 节点（包括 document 对象及其后代元素）和 ActiveX 对象。如果在一个循环引用中包含了一或多个这样的对象，那么这些对象直到浏览器关闭都不会被释放，而它们所占用的内存同样在浏览器关闭之前都不会交回系统重用。 </P>
<P>当两个或多个对象以首尾相连的方式相互引用时，就构成了循环引用。比如对象 1 的一个属性引用了对象 2 ，对象 2 的一个属性引用了对象 3，而对象 3 的一个属性又引用了对象 1。对于纯粹的 ECMAScript 对象而言，只要没有其他对象引用对象 1、2、3，也就是说它们只是相互之间的引用，那么仍然会被垃圾收集系统识别并处理。但是，在 Internet Explorer 中，如果循环引用中的任何对象是 DOM 节点或者 ActiveX 对象，垃圾收集系统则不会发现它们之间的循环关系与系统中的其他对象是隔离的并释放它们。最终它们将被保留在内存中，直到浏览器关闭。 </P>
<P>闭包非常容易构成循环引用。如果一个构成闭包的函数对象被指定给，比如一个 DOM 节点的事件处理器，而对该节点的引用又被指定给函数对象作用域中的一个活动（或可变）对象，那么就存在一个循环引用。<SPAN -&gt;></SPAN><SPAN -&gt;></SPAN><SPAN -&gt;></SPAN><SPAN -&gt;></SPAN><SPAN ></SPAN></P>
<P>多加注意可以避免形成循环引用，而在无法避免时，也可以使用补偿的方法，比如使用 IE 的 onunload 事件来来清空（null）事件处理函数的引用。时刻意识到这个问题并理解闭包的工作机制是在 IE 中避免此类问题的关键。 </P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200924104025828</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200924104025828</guid>
    <pubDate>Wed, 4 Mar 2009 22:40:25 +0800</pubDate>
    <dcterms:modified>2009-03-04T22:40:25+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[实例学习call、apply、callee用法]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200912613612865</link>
    <description><![CDATA[<div><div >
    <p>可能不少学习javascript在使用call,apply,callee时会感到困惑，以下希望对于你有所帮助：<br>
1、它是函数的方法或属性；<br>
2、它可以改变执行上下文的this指向；<br>
3、作为另一个对象调用一个方法(即可以把一个对象的方法作为另一个对象的方法来引用)；<br>
4、apply方法类似，但只能接收数组为参数；<br>
5、callee函数的调用者。</p>
<p>f.call(o,1,2) 等同于<br>
o.m = f;<br>
o.m(1,2);</p>
<p>例1：<br>
function o1(value){<br>
if(value &lt; 100){<br>
this.value = value;<br>
}else{<br>
this.value = 100;<br>
}<br>
}</p>
<p>function o2(value){<br>
o1.call(this,value);<br>
alert(this.value);<br>
}</p>
<p>var o = new o2(133554) //100&nbsp; 改变了this的指向</p>
<p>例2：<br>
function c1(){<br>
this.m1 = function(){<br>
alert(this.name);<br>
}<br>
}</p>
<p>function c2(){<br>
this.name = “mike”;<br>
}<br>
var nc1 = new c1();<br>
var nc2 = new c2(); //必须<br>
nc1.m1.call(nc2);&nbsp; //mike 把方法m1作为对象nc2的方法来引用</p>
<p>例3：<br>
<span> function o1(arg){<br>
if (arguments[1] &lt; 100) {<br>
this.value = </span><span>arguments[1] </span><span>;<br>
}<br>
else {<br>
this.value = 100;<br>
}<br>
}</span></p>
<p>function o2(arg){<br>
o1.apply(this, arg);<br>
alert(this.value);<br>
}</p>
<p>var o = new o2([101,60]) //60 参数只能是数组</p>
<p>callee用法，常用于匿名函数中<br>
var factorial = function(x){<br>
if(x &lt;= 1){<br>
return 1;<br>
}<br>
return x * arguments.callee(x - 1);<br>
}<br>
alert(factorial(5)); //120</p>
   </div></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200912613612865</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200912613612865</guid>
    <pubDate>Thu, 26 Feb 2009 13:36:12 +0800</pubDate>
    <dcterms:modified>2009-02-26T13:36:12+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[淘宝前端开发人员的心声]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200911892215217</link>
    <description><![CDATA[<div>转自淘宝前端开发某成员博客，与大家共勉。<br><h3>淘宝改版的喜与忧</h3>
<p>淘宝改版了，论坛上骂声一片。一天之内，长达<a target="_blank" href="http://forum.taobao.com/forum-14/show_thread----21029093-.htm">300多页的反馈</a>，的确让我们这些局内人很沮丧。我只说说“已买到/已卖出的宝贝”列表页面，从加入淘宝开始，就一直负责部分交易相关页面的前端工作，真的是很有感情了。</p>
<p>“已买到/已卖出的宝贝”页面，上次改版是08年6月份，回顾一下<a target="_blank" href="http://forum.taobao.com/forum-14/show_thread----16270357-0-.htm">当时的公告贴</a>吧。当时也有不少用户对新页面不满意，非常反对，要求恢复老版。和这次很多卖家的口号是一样的，只是这次反应更剧烈，有时想想，蛮戏剧化的（现在要求恢复的是当时极力反对的）。</p>
<p>关于网站改版，JavaEye的坛主robbin有过一篇很不错的<a target="_blank" href="http://www.javaeye.com/topic/141889">分析</a>。一般来说，改版要采取渐进式，一次不要发布太多功能，并且最好有个老旧并存，新版公测期。这两点，因为各种原因，淘宝这次明显没做好。但这和上层的决策有关，现在还难以看出好坏。改版的策略和方式，在此不多说（我这个小虾米也影响不了什么）。</p>
<p>我说一点能说的，以及我的担心：</p>
<p>首先，淘宝现在已然是个大象，很多新项目新功能都在开发中。淘宝鼓励做加法，同时大部分项目也只敢做加法。举个简单的例子，“已买到的宝贝”列表页
面，“我要秀”功能，很鸡肋的一个功能，而且里面的页面都好久没维护了，就是这样一个大部分用户不会去用的功能，却死活去不掉，因为这牵扯到麻烦，可能有
风险，于是一个项目一个项目下来，一直留到了现在。</p>
<p>这和我的理念有冲突，我推崇的是简单法则，我相信的是<a target="_blank" href="http://gettingreal.37signals.com/GR_chn.php">Getting Real</a>. 我觉得保持简单，突出核心竞争力，这也是淘宝应该做到的。小学，我们先学加法，然后才学减法，因为减法比加法更难。对于一个产品来说，减法更需要魄力。我亲爱的淘宝，什么时候，你才能学会做减法呢？（或许高层们比我看得更远更深，纯粹当我发牢骚吧。）</p>
<p>其次，淘宝已经是大象，大家都忙着新项目和新功能，对原有系统的一些问题，却不大愿意花费时间去改进。例子很明显，“我的淘宝”里面的页面，风格有
好几种，统一“我的淘宝”，这件事情两三年前就有人提，但一直到现在，却没有人真正的把这件事情做起来。都忙着做加法呢，没时间做扫地的工作了。真诚期望
淘宝什么时候能设立“默默无闻改进奖”，而不是仅搞个“轰轰烈烈创新奖”。（当然，我这里仅针对前端展示层。对于后台功能，比如这次改版，我相信对底层代
码是做了很多重构和改进工作的。但每次进入“我的淘宝”，心里忍不住还是会痛一下。）</p>
<p>最后，在淘宝开发流程中，还是有非常多的不足。这次改版发布后的调整过程中，视觉和交互设计师的精心设计，比不上高层的一句话。种种情况，职责的不分明，有时真让人怀疑，这是不是淘宝。（很多公司都有这种毛病，但身临其境，还是让人很郁闷。）</p><h3>对自己以及对公司的建议</h3>
<ol><li>加班要尊重员工自己的选择。如果的确需要加班，请选择合适的方式交流沟通。（我自己也做得不够好，性子有点急，以后一定要注意）</li><li>改版要慎重。一定要采取妥善的方式，尽早从最终用户中获取建议。</li><li>学学减法，我相信对淘宝有好处。</li><li>默默无闻的改进，有时比轰轰烈烈的创新更重要。</li><li>产品经理，项目经理，视觉设计师，交互设计师，要职责分明，要彼此尊重。</li><li>高层请在自己精通的领域指点江山，请不要轻易否定员工的努力，某些领域，你不一定比员工强，你的感觉也不一定对。</li></ol><h3>不加班冲突</h3>
<p>昨天因为不愿意加班，和一个项目经理Y发生了一些不愉快。Y的一部分理论是马云语录：“正常上班是正常的， 不正常上班也是正常的，
只有工作没有完成是不正常的。”
我坚持的是：“第一，在上班时间内，我肯定会努力解决问题，想尽一切办法。第二，如果上班时间内没搞定，对不起，家庭比工作更重要，我得先做更重要的事。
”</p>
<p>现在想想，Y的确有Y的难处，但这件事情，不应该通过强制加班来解决。在阿里，加班是自愿的，也是无酬的。当员工的确不想加班时，是应该可以自由选
择的。从加入淘宝一直到过年前，我几乎都是有求必应，有班必加。但人总有倦的时候，总有疲惫的时候，总有有想法的时候。我不想加班，Y却想通过加班来解决
问题，这个矛盾，我也不知道怎么解决。Y我理解你的难处，但也请你尊重我的选择。</p>
<p>马云的加班论，我一直觉得是谬论<span></span>，因为很难判定“一天应该完成哪些工作”。比如这个例子中，Y的理解是，今天要把反馈的
问题都改完。我的理解是，今天把工作时间内能做的事情做完。不同的角色，不同的角度，对“当天的工作是否完成”的判断是不同的，而且不存在对错。马云的不
少观点，都是初看有点道理，细想却经不起推敲。<br><br>作者：<span >lifesinger&nbsp; 原文链接：http://lifesinger.org/blog/?p=1346<br></span></p><br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200911892215217</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200911892215217</guid>
    <pubDate>Wed, 18 Feb 2009 09:22:15 +0800</pubDate>
    <dcterms:modified>2009-02-18T09:22:15+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[页面性能改进-新闻首页改版]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/2475322009090721994</link>
    <description><![CDATA[<div><p>&nbsp;&nbsp; 在国内的门户网部中，页面多是追求大而全，而很少在页面性能上考虑；此次新闻改版，我们首次在页面性能上作了较大的改进力度，借助于yahoo开发的页面性能评测工具YSlow，得分截图如下：</p>
<p><a href="http://img.blog.163.com/photo/YAEqCcpSRyytc71u2lZWHg==/1453255304758282206.jpg" target="_blank"><img title="页面性能改进-新闻首页改版 - 罗金 - 用户体验" alt="页面性能改进-新闻首页改版 - 罗金 - 用户体验" src="http://img.blog.163.com/photo/YAEqCcpSRyytc71u2lZWHg==/1453255304758282206.jpg"></a><br>
总得分为80分：(A为最好，F为最差）<br>
第二点”Use a CDN”，采不采用CDN不是我们所能决定，这一点得分为0；<br>
第三点”Add an Expires header”，由于新闻首页里有财经的三个行情图，由于需要实时刷新，这三张图片是不能设置太长的过期时间，为此，这三个图导致扣了一半分；<br>
第九点”Reduce DNS lookups”，由于我们页面里的内容来源域名较多，有博客的、有有道的等，为此导致扣了一半分。其它的还算做的比较好了。<br>
&nbsp;&nbsp;&nbsp; 我们借助于第三方的软件测试，分数不是我们的最终目的，我们的目的是优化页面代码、提高用户的打开速度，用户的满意度才是我们的最终目的。其实在标签的语义化、Javascript代码还有改进的空间，这些都还需要我们整个团队的进一步努力。</p>
注：上线之后，由于广告代码的加入，分数降的很低。广告方面很需兄弟部门的努力和改进</div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/2475322009090721994</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/2475322009090721994</guid>
    <pubDate>Fri, 9 Jan 2009 12:07:21 +0800</pubDate>
    <dcterms:modified>2009-01-09T12:07:21+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[JavaScript的速度问题和未来 ]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200811312044397</link>
    <description><![CDATA[<div>转：http://www.openlab.net.cn/forums/threads/1385628.aspx<br><div >
                      <p>相对于Flex和SilverLigth，JavaScript的优势在于浏览器天然支持。我甚至觉得JavaScript可以作为启蒙性的编程语言，为什么呢？简单，方便。没有指针，没有复杂的语法，打开浏览器就能运行。对于任何初学抠代码的童鞋，真是太方便不过了。</p><p>JavaScript的问题也很突出，最受指责的，可能是它的执行速度。微软的IE浏览器里，JavaScript的速度是极其低下的，当然，在其他大多数主流浏览器里的速度，也很糟糕。</p><p>Google
Chrome浏览器的出现给JavaScript的速度带来了曙光，也打响了JavaScript性能大战。为什么说这个革命性的呢？因为Chrome浏
览器用了一种名叫
”V8“的JS执行引擎。原先所有的浏览器执行JavaScript，是采用”解释“的方法。相对于拥有自己相应虚拟机的
Flash（Flex），SilverLight，JavaFX/Applet，JavaScript的效率，差了一个数量级。</p><p>但是V8引
擎的出现，打破了”解释“模式。Chrome浏览器执行JavaScript，采用了和Java类似的方法：JIT（即时编译）。把JavaScript
优化编译成二进制本地执行文件并存放在内存里面。这种执行方法，使得JavaScript的速度在理论上能和Java/.NET一样快！相对传统的浏览
器，那是数量级的飞跃。</p><p>这样就出现了一种可能：我们可以开发更复杂的JavaScript应用，而不用求助于其他的前台技术。我们甚至可以用JavaScript来实现3D效果。</p><p>大家可以看看这个：</p><p><a href="http://www.xs4all.nl/%7Epeterned/3d/">http://www.xs4all.nl/~peterned/3d/</a></p><p>Chrome的V8引擎给大家带来了新的希望，紧接着，新的Safari浏览器也采用了更高效的JIT JavaScript 引擎，FireFox3.1亦不甘示弱，新一轮浏览器大战将打响。</p><p>上个月，微软承认JavaScript的速度在未来18个月内会有百倍提升，JavaScript的未来如何，我们拭目以待吧</p>
                      </div><br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200811312044397</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200811312044397</guid>
    <pubDate>Wed, 3 Dec 2008 13:20:44 +0800</pubDate>
    <dcterms:modified>2008-12-03T13:20:44+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[香港印象]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200811212947157</link>
    <description><![CDATA[<div>&nbsp;&nbsp;&nbsp;&nbsp; 每去一个新地方，应该了解一下当地的风土人情，这次也不例外。<br>1、很羡慕香港的车：奔驰、宝马、凌志满街都是，大陆的车根本进不了这个市场，因为太烂了，只有看了香港的车，才知共产党有多黑；<br>2、香港的城市管理绝对是国内应该好好学习的，它们的街道虽然窄，但绝对是干净的，也并不是任何时候任何地方都有人在扫，要知道，那里的人力成本是比较高的，路边的电线杆，树木也见不到乱贴的小广告，那里一条街中有一块墙壁是专门让人乱贴的（估计是每条街都有）；<br>3、他们的房子很多是建在半山的，也是出名的贵，100平方米（它们用的是平方尺）的房子，稍微好点的就要1000万。这不是一般家庭可以承受的，所以大房子在香港人心目中是最大的梦想。<br>4、香港人很勤奋，很多头发已经白了不少的人仍然在辛勤的工作着，现在国内动不动就到了四十五就内退，或许是国内人太多了，但香港人口也不少啊。。。<br>5、香港色情MS是合法化的。。。<br><br>稍后传几张相片上来。。。<br><br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200811212947157</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200811212947157</guid>
    <pubDate>Tue, 2 Dec 2008 13:29:47 +0800</pubDate>
    <dcterms:modified>2008-12-02T13:29:47+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[ 转变]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/247532200891011513677</link>
    <description><![CDATA[<div>不在限于工作相关的主题。<br><br>现在全世界都是谈论如何救市，股票不知跌到何时。<br><br>如果中国房地产崩溃，世界会如何？<br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/247532200891011513677</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/247532200891011513677</guid>
    <pubDate>Fri, 10 Oct 2008 23:51:36 +0800</pubDate>
    <dcterms:modified>2008-10-10T23:51:36+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[产品]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/2475322008997637864</link>
    <description><![CDATA[<div><div >
    <p>关键字：生命周期 产品 创新 挖掘用户潜在的需求 细分用户 潜在竞争产品 用户体验</p>
<p>产品：互联网的各种应用都可以称为“狭义”上的产品，如搜索引擎、视频应用、门户网站、网络游戏等，再进一步细分，互联网中的一个互动策划活动都可
以称为一个产品。任何产品都有它的生命周期，必然会经历：萌芽、发展、繁荣、衰落、死亡，只是在不同的产品中，生命周期有长有短。</p>
<p>用户体验的最佳实践就是和产品开发的完美结合：包含创新、挖掘用户潜在的需求、细分用户、和潜在同类产品相比的优势。</p>
<p>创新永远是产品致胜的核心，其余三个是产品成功的重要条件，在进行产品开发之前，分析你的产品是否符合上述四个条件的一个或多个。</p>
<p>梦幻足球经理的PM在立项之前找我聊了一下，当时自己感觉这是一个不错的项目。但足球经理项目试运营了一个赛季后，数据结果却不是很理想，结合上面提到的四点去分析一下：<br>
1、足球经理不是一个创新的项目，国外已经有类似成功的产品；<br>
2、挖掘用户潜在的需求、细分用户，用户就是球迷，为球迷除了资讯之外多一个选择；<br>
3、和潜在同类产品相比，如FIFA系列的实战游戏，在娱乐操作方面明显处于下风；</p>
<p>另外足球经理项目自身有先天的不足之处：<br>
1、悬念失去过早：<br>
在漫长的赛季中，悬念失去过早。<br>
把游戏中人群分为三类：<br>
一、希望通过每轮累计积分获奖的人，此类用户如果是赛季进行二个月后才加入，最终基本会流失，因为28轮的总成绩和38轮的总成绩相比，明显处于下风，所以由于时间的先后顺序，导致悬念失去过早；<br>
二、对获不获奖无关紧要，纯粹是足球爱好者，只有这类用户才是最忠诚的；<br>
三、纯粹来玩玩，这类用户不容易留下，如上面提到的FIFA系列的实战游戏，操控性明显会强于足球经理。<br>
2、受客观赛程的影响：<br>
由于每一轮比赛场次有时会相隔几天，轮数之间的时间不固定，导致用户操作不便；</p>
<p>注：无意攻击足球经理项目，只是引出话题与大家探讨。</p>
   </div></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/2475322008997637864</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/2475322008997637864</guid>
    <pubDate>Thu, 9 Oct 2008 19:06:37 +0800</pubDate>
    <dcterms:modified>2008-10-09T19:06:37+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[回家]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220089785835612</link>
    <description><![CDATA[<div>&nbsp; 国庆回了一趟乡下，调皮的侄儿依旧调皮。<br><a href="http://img.blog.163.com/photo/-URfdygq9adNqt4gPzxbnw==/2014234933342412450.jpg" target="_blank"><img src="http://img.blog.163.com/photo/-URfdygq9adNqt4gPzxbnw==/2014234933342412450.jpg"></a><br></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220089785835612</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220089785835612</guid>
    <pubDate>Tue, 7 Oct 2008 08:58:35 +0800</pubDate>
    <dcterms:modified>2008-10-07T08:58:35+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[奥运官方合作网站报道]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220087905156495</link>
    <description><![CDATA[<div><P>2008年8月8日晚8点08分，整整等了一百多年的中华儿女、北京终于圆梦了。看奥运报道当然去官方网站了，号称技术驱动的官方网站竟然有地理岐视，但我是中国人啊。。。。看图说话</P>
<P><A href="http://img.blog.163.com/photo/m5rdrVkrGscVMFn92R6B1A==/325948023031747938.jpg" target=_blank><IMG src="http://img.blog.163.com/photo/m5rdrVkrGscVMFn92R6B1A==/325948023031747938.jpg"></A></P>
<P>&nbsp;</P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220087905156495</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220087905156495</guid>
    <pubDate>Sat, 9 Aug 2008 12:51:56 +0800</pubDate>
    <dcterms:modified>2008-08-09T12:51:56+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Google搜索结果页改版了]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220087194513328</link>
    <description><![CDATA[<div><P>Google搜索结果页改版啦，界面上看主要有三点：<BR>1、无厘头的上方LOGO重复了；如图<BR>2、搜索结果间距设大了，看起来清晰明朗，看来网易在这方面是最早抛弃密密麻麻的排版设计；<BR>3、下方的结果翻页有一个显著的改变，当前页突起来，以国内设计惯例，很快会有类似的模仿页面出现，我一年半前对文章页提出类似的方案，未获通过，有文章为证。<A href="http://blog.163.com/mike_gz/blog/static/247532200711510350798/">http://blog.163.com/mike_gz/blog/static/247532200711510350798/</A><BR><BR>翻页<BR><A href="http://img.blog.163.com/photo/MGy0Kw9Qm8ezPYU-iQq-lw==/4792111478499154381.jpg" target=_blank><IMG src="http://img.blog.163.com/photo/MGy0Kw9Qm8ezPYU-iQq-lw==/4792111478499154381.jpg"></A></P>
<P>logo重复</P>
<P><A href="http://img.blog.163.com/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg" target=_blank><IMG src="http://img.blog.163.com/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg"></A></P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220087194513328</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220087194513328</guid>
    <pubDate>Fri, 1 Aug 2008 09:45:13 +0800</pubDate>
    <dcterms:modified>2008-08-01T11:16:29+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[切尔西VS广州医药队]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220086240357511</link>
    <description><![CDATA[<div><P>&nbsp;&nbsp;&nbsp;&nbsp; 昨天，也就是7月23日，切尔西亚洲之旅的第一场比赛在奥体中心举行，意外从同事手上得到一票，而且还是VIP票。下班吃完饭就赶过去，进场花了半个小时，找入口（VIP就是不同），安检特严。</P>
<P>&nbsp;&nbsp;&nbsp; 八点比赛准时进行，明显切尔西的实力高三个档次，好像是在半场演练，一脚传球、不看人传球、跑位、盘带、突破，精彩接连出现，让人真喊爽快，由于没有太多拼抢，上半场只取得一个进球，上半场结束我就退场了，警察同志把我的车分流到离球场比较远的地方停车，我怕结束时要排很久的队才能出来，很多很多车。</P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220086240357511</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220086240357511</guid>
    <pubDate>Thu, 24 Jul 2008 12:35:07 +0800</pubDate>
    <dcterms:modified>2008-07-24T12:35:07+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Javascritp模板机制]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/2475322008671475236</link>
    <description><![CDATA[<div><P><FONT color=#c80100>作者 罗礼权 </FONT></P>
<P><FONT color=#c80100></FONT>&nbsp;</P>
<P style="TEXT-INDENT: 2em">应用背景</P>
<P style="TEXT-INDENT: 2em">毫无疑问，模板机制是CMS里面的重要组成要素。本来模板机制只涉及CMS后台程序处理，但是随着AJAX的发展，我们经常会通过XMLHttpRequest从后台获取数据再套入到特定的HTML结构注入到页面上。这时我们的前台处理也要涉及到模板机制的概念。</P>
<P style="TEXT-INDENT: 2em">解决方案</P>
<P style="TEXT-INDENT: 2em">假设要我们需要从后台异步读取一篇文章的信息（假设该文章只有标题、作者、内容三项信息）并显示在当前页面上。文章的HTML结构是：</P>
<P style="TEXT-INDENT: 2em">&lt;h1&gt;标题&lt;/h1&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;div&gt;作者&lt;/div&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;p&gt;内容&lt;/p&gt;</P>
<P style="TEXT-INDENT: 2em">方案一：后台生成HTML代码</P>
<P style="TEXT-INDENT: 2em">由后台生成HTML代码表面上是最方便的，前台程序员只需要通过XMLHttpRequest获取这段HTML并注入到页面（innerHTML）中就行了。但是，这种方法的可维护性是最差的，因为后台程序负责HTML的输出意味着一旦HTML结构有所更改就必须在后台程序中改。</P>
<P style="TEXT-INDENT: 2em">方案二：动态创建HTML结点</P>
<P style="TEXT-INDENT: 2em">代码示例：</P>
<P style="TEXT-INDENT: 2em">&nbsp;var titleNode = document.createElement(”h1″);</P>
<P style="TEXT-INDENT: 2em">&nbsp; title.innerHTML = title;</P>
<P style="TEXT-INDENT: 2em">&nbsp; var authorNode = document.createElement(”div”);</P>
<P style="TEXT-INDENT: 2em">&nbsp; authorNode.innerHTML = author;</P>
<P style="TEXT-INDENT: 2em">&nbsp; var contentNode = document.createElement(”p”);</P>
<P style="TEXT-INDENT: 2em">&nbsp; contentNode.innerHTML = content;</P>
<P style="TEXT-INDENT: 2em">document.body.appendChild(titleNode);</P>
<P style="TEXT-INDENT: 2em">&nbsp;document.body.appendChild(authorNode);</P>
<P style="TEXT-INDENT: 2em">&nbsp;document.body.appendChild(contentNode);</P>
<P style="TEXT-INDENT: 2em">HTML结构比较简单的时候，这种结构是可以接受的。但是一旦出现了复杂的HTML结构，它的代码就会相当冗长，编写和维护起来都极为不便，程序效率也不高。</P>
<P style="TEXT-INDENT: 2em">方案三：HTML模板</P>
<P style="TEXT-INDENT: 2em">代码示例：</P>
<P style="TEXT-INDENT: 2em">&nbsp;var template = “&lt;h1&gt;{$title}&lt;/h1&gt;&lt;div&gt;{$author}&lt;/div&gt;&lt;p&gt;{$content}&lt;/p&gt;”;</P>
<P style="TEXT-INDENT: 2em">&nbsp;template = template.replace(”{$title}”, title).replace(”{$author}”,author).replace(”{$content}”, content);</P>
<P style="TEXT-INDENT: 2em">document.body.innerHTML = template;</P>
<P style="TEXT-INDENT: 2em">这种方法的缺陷在于需要多次替换，如果数据很多，就要进行多次替换，效率非常差。但是它的思想是非常好的，只要避免了多次替换的问题，这种方法可以成为很好的解决方案。</P>
<P style="TEXT-INDENT: 2em">我们可以引入正则表达式对这种方法进行改良。模板中要替换的字符串格式是 {$文章属性}，这种格式写成正则表达式就是 \{\$\w+\} 。如果要把文章属性（就是{$和}间的内容）提取出来，还要加一个分组，所以正则表达式最终是这样的 就是 \{\$(\w+)\}。</P>
<P style="TEXT-INDENT: 2em">代码改良如下：</P>
<P style="TEXT-INDENT: 2em">&nbsp;var article = {title: title, author: author, content: content}; // 先把文章封装成对象</P>
<P style="TEXT-INDENT: 2em">&nbsp; var template = “&lt;h1&gt;{$title}&lt;/h1&gt;&lt;div&gt;{$author}&lt;/div&gt;&lt;p&gt;{$content}&lt;/p&gt;”;</P>
<P style="TEXT-INDENT: 2em">document.body.innerHTML = template.replace(/\{\$(\w+)\}/g, function($1, $2) { /* 返回文章对象的属性 */ return article[$2] || “”; });</P>
<P style="TEXT-INDENT: 2em">扩展应用</P>
<P style="TEXT-INDENT: 2em">最近做了一个奥运弹窗后台管理页面，其中有一个预览功能。管理员在表单中输入数据：</P>
<P style="TEXT-INDENT: 2em">排行榜：(输入框)金牌(输入框)银牌(输入框)铜牌</P>
<P style="TEXT-INDENT: 2em">然后显示结果：</P>
<P style="TEXT-INDENT: 2em">排行榜：10 金牌 6 银牌 3 铜牌</P>
<P style="TEXT-INDENT: 2em">结果的显示其实就是把输入框中的内容替换输入框代码。据此，我写的代码如下：</P>
<P style="TEXT-INDENT: 2em">// 假设style是输入框所在节点，preview是预览层节点</P>
<P style="TEXT-INDENT: 2em">&nbsp; preview.innerHTML = style.innerHTML.replace(</P>
<P style="TEXT-INDENT: 2em">/&lt;input[^&gt;]*id=\”?(\w+)\”?[^&gt;]*&gt;/gi, function($1, $2) {</P>
<P style="TEXT-INDENT: 2em">&nbsp; 　　return document.getElementById($2).value;</P>
<P style="TEXT-INDENT: 2em">&nbsp; });</P>
<P style="TEXT-INDENT: 2em">&nbsp;</P>
<P style="TEXT-INDENT: 2em">原理就是用正则表达式匹配出id，然后通过document.getElementById方法提取input输入框的value属性，从而获得输入值，然后用输入值替换input输入框再注入到预览层中去。</P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/2475322008671475236</comments>
    <slash:comments>1</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/2475322008671475236</guid>
    <pubDate>Mon, 7 Jul 2008 13:47:05 +0800</pubDate>
    <dcterms:modified>2008-07-07T13:47:05+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[开心网试用手记]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220086364350845</link>
    <description><![CDATA[<div><P>&nbsp;&nbsp;&nbsp;&nbsp; 初次听到开心网是二个多月前的事了，那时朋友在IM说发了一个邀请链接我，让我去注册，我回了他一句“没兴趣”，直到上周，时不时听到周围的人谈论着“奴隶啊、举报啊、前世啊什么的”开始还听不明白，后来隐约知道，都在玩开心网。真的有那么好玩吗？带着试试的心情也让同事发了一个邀请链接我，因为之前我试用了Facebook、校内、海内等社交网站，觉的很没意思，所以注册之时我的期望值是不高的，试玩了之后，发觉是更了解中国国情的Facebook，彻底改变了看法:<BR>1、对注册流程做了很大的压缩，比Facebook简化多了；<BR>2、组件是有趣、上手简单，并带有很大娱乐性的，很符合国人的习惯；<BR>3、邀请机制多样化；<BR>我觉的它比校内、海内等社交网站最成功的地方是“充分研究并理解国人的文化、操作习惯”，这是他讯速发展的核心所在，按这样的创新模式发展下去，前途不可限量，当然这有待于时间的检验。开心网讯速发展的同时，也并不是不存在不足的地方，而且不足地方还很明显的：<BR>1、系统负荷问题，这有可能成为致命的问题，现在还没有正式开放，稍为人多一点在线，就显的非常之慢了，这与系统架构、均衡负荷、服务器、带宽各方面都有联系；<BR>2、可玩性问题，由于提供的组件都是比较简单，难度不高的组件，这对持续可玩性是一个很大的挑战；<BR>3、金钱系统问题，各组件的金钱系统是各不相关的，这在一定程度给开心网打了一个折扣，当然要把各组件的金钱系统统一起来，可不是一个简单的事，特别是组件开放第三方开发时；<BR>4、域名问题，<A href="http://www.kaixin001.com">http://www.kaixin001.com</A>，初次看到时觉的跟病毒网站网址或钓鱼网址差不多，还真不想去点，怕会时骗人的，当然这只是我个人的看法。</P>
<P>总的来说，开心网我个人认为做的相当不错。</P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220086364350845</comments>
    <slash:comments>5</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220086364350845</guid>
    <pubDate>Thu, 3 Jul 2008 18:43:50 +0800</pubDate>
    <dcterms:modified>2008-07-03T18:43:50+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[释迦摩尼]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/2475322008563350693</link>
    <description><![CDATA[<div>摘<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有一个人，在对象树下，整整想了九九八十一天，终于悟出了生命的痛苦来自于欲望，但究其欲望的根源是来自于自我意识。于是他放下了“自我”，在对象树下成了佛，从此他开始普度众生，传播真经。他的名字就叫释迦摩尼。</div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/2475322008563350693</comments>
    <slash:comments>2</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/2475322008563350693</guid>
    <pubDate>Fri, 6 Jun 2008 15:03:50 +0800</pubDate>
    <dcterms:modified>2008-06-06T15:04:19+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[Javascript prototype]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220085544933962</link>
    <description><![CDATA[<div><P>function $oriA(o){<BR>this._name=o;<BR>}<BR>$oriA.prototype._wintip=function()<BR>{<BR>alert("my name is "+this._name);<BR>}</P>
<P>function $targetA(o){<BR>$oriA.call(this,o);<BR>} //把$oriA复制给$targetA;<BR>$targetA.prototype=new $oriA();<BR>var newC=new $targetA("李四");<BR>newC._wintip();</P>
<P>&nbsp;</P>
<P>其中$oriA.call(this,o)我是理解成"把$oriA复制给$targetA"，不知大侠有何高见！</P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220085544933962</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220085544933962</guid>
    <pubDate>Thu, 5 Jun 2008 16:49:33 +0800</pubDate>
    <dcterms:modified>2008-06-05T16:49:33+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[IE8新功能Web Slice和Activity]]></title>	
    <link>http://blog.163.com/mike_gz/blog/static/24753220085441813215</link>
    <description><![CDATA[<div><P style="TEXT-INDENT: 2em">微软于3月推出了Internet Explorer 8 Beta 1 for Developers中文版，主要是针对开发者。添加了不少新功能，其中二个比较受关注：Web Slice（网站订阅）和Activity（活动内容服务），当正式版发布后加上微软一贯的作风在操作系统上捆绑销售，估计对一些RSS提供商有相当大的杀伤力，并想独吞浏览器市场，结果如何，我们拭目以待吧！</P>
<P style="TEXT-INDENT: 2em">如果你有兴趣，看看<A href="http://ie8.163.com/">http://ie8.163.com/</A></P>
<P style="TEXT-INDENT: 2em">IE8的这二个新功能方便实用，而且对开发者来说，技术上不用学习什么新语言。主要是用类和XML文件组成。下面分别介绍一下实现方试：</P>
<P style="TEXT-INDENT: 2em">一、Web Slice（网站订阅）</P>
<P style="TEXT-INDENT: 2em">&lt;div class=”hslice” id=”theSlice”&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;div class=”entry-title”&gt;Title&lt;/div&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;div class=”entry-content”&gt;This is Content &lt;/div&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/div&gt;</P>
<P style="TEXT-INDENT: 2em">其中类hslice，entry-title，entry-content和ID是必需的，当然你定义样式完全可以用另外的类，class支持多引用的，如class=”hslice&nbsp; oneSlice”。除了这几个必需的外，还可根据具体需要设置如结束时间、带宽、HTTP 身份验证等都有预定的类来实现，具体查看官司开发文档<A href="http://www.microsoft.com/windows/ie/ie8/welcome/zh-cn/default.html">http://www.microsoft.com/windows/ie/ie8/welcome/zh-cn/default.html</A>。</P>
<P style="TEXT-INDENT: 2em">二、Activity（活动内容服务）</P>
<P style="TEXT-INDENT: 2em">这个比起Web Slice稍微复杂点，首先每个具体活动要调用一个XML文档，然后在页面里用一个简单的脚本来调用，分别如下：</P>
<P style="TEXT-INDENT: 2em">&lt;script type=”text/javascript”&gt;</P>
<P style="TEXT-INDENT: 2em">var</P>
<P style="TEXT-INDENT: 2em">function addActivity(index) {</P>
<P style="TEXT-INDENT: 2em">if (navigator.userAgent.indexOf(’MSIE 8′) == -1) {</P>
<P style="TEXT-INDENT: 2em">alert(’请首先安装IE8.’);</P>
<P style="TEXT-INDENT: 2em">} else {</P>
<P style="TEXT-INDENT: 2em">window.external.addService(”stock.xml”);</P>
<P style="TEXT-INDENT: 2em">}</P>
<P style="TEXT-INDENT: 2em">}</P>
<P style="TEXT-INDENT: 2em">&lt;/script&gt;</P>
<P style="TEXT-INDENT: 2em">脚本比较简单。</P>
<P style="TEXT-INDENT: 2em">XML文档有特定的关键词：</P>
<P style="TEXT-INDENT: 2em">&lt;?xml version=”1.0″ encoding=”GBK” ?&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;openServiceDescription xmlns=”<A href="http://www.microsoft.com/schemas/openservicedescription/1.0">http://www.microsoft.com/schemas/openservicedescription/1.0</A>“&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;homepageUrl&gt;http://www.163.com&lt;/homepageUrl&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;display&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;name&gt;网易财经基金股票查询&lt;/name&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;icon&gt;http://cimg2.163.com/cnews/favicon.ico&lt;/icon&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/display&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;activity category=”stocks”&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;activityAction context=”selection”&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;preview accept-charset=”gb2312″ action=”<A href="http://news.163.com/special/00012NB3/widget.htm">http://news.163.com/special/00012NB3/widget.htm</A>“&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;parameter name=”code” value=”{selection}” /&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/preview&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;execute accept-charset=”gb2312″ action=”<A href="http://news.163.com/special/00012NB3/widget.htm">http://news.163.com/special/00012NB3/widget.htm</A>“&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;parameter name=”code” value=”{selection}” /&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/execute&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/activityAction&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/activity&gt;</P>
<P style="TEXT-INDENT: 2em">&lt;/openServiceDescription&gt;</P>
<P style="TEXT-INDENT: 2em">XML文件主要由三部分组成：</P>
<P style="TEXT-INDENT: 2em">1、活动：其中名字空间xmlns和活动域homepageUrl是必需的。</P>
<P style="TEXT-INDENT: 2em">2、显示：其中display和name是必需的。</P>
<P style="TEXT-INDENT: 2em">3、内容：activity元素，category属性，activityAction元素，execute元素，action 属性是必需的，每一个元素或属性都有特定的作用，具体参考官方开发文档<A href="http://www.microsoft.com/windows/ie/ie8/welcome/zh-cn/default.html">http://www.microsoft.com/windows/ie/ie8/welcome/zh-cn/default.html</A>。</P>
<P style="TEXT-INDENT: 2em">Web Slice界面</P>
<P style="TEXT-INDENT: 2em"><A href="http://img.blog.163.com/photo/OMNxm0-VzbamQ8fUAHcomA==/4244642648797369708.jpg" target=_blank></A><A href="http://img.blog.163.com/photo/AznZALeCMpsD0F_tfXUKMg==/2261651437870573172.jpg" target=_blank></A><A href="http://img.blog.163.com/photo/qqeXXmHwCX5P4yGEpp5OQw==/2261651437870573171.jpg" target=_blank></A><A href="http://img.blog.163.com/photo/VaCJRxdYfcWCWCYPDTa-Og==/4244642648797369709.jpg" target=_blank></A><A href="http://img.blog.163.com/photo/8Wk3NjbxCdWlpheFHNYleQ==/2261651437870573165.jpg" target=_blank><IMG src="http://img.blog.163.com/photo/8Wk3NjbxCdWlpheFHNYleQ==/2261651437870573165.jpg"></A></P>
<P style="TEXT-INDENT: 2em">鼠标放上去就会出现紫色的图标<BR></P>
<P style="TEXT-INDENT: 2em"><A href="http://img.blog.163.com/photo/VaCJRxdYfcWCWCYPDTa-Og==/4244642648797369709.jpg"><IMG border=0 src="http://img.blog.163.com/photo/VaCJRxdYfcWCWCYPDTa-Og==/4244642648797369709.jpg"></A><BR>点击紫色的图标就会弹出这个窗口
</P><P style="TEXT-INDENT: 2em"><BR><A href="http://img.blog.163.com/photo/qqeXXmHwCX5P4yGEpp5OQw==/2261651437870573171.jpg"><IMG border=0 src="http://img.blog.163.com/photo/qqeXXmHwCX5P4yGEpp5OQw==/2261651437870573171.jpg"></A><BR>当添加之后就会在收藏夹栏出现，点击之后的窗口<BR>
</P><P style="TEXT-INDENT: 2em">Activity界面</P>
<P style="TEXT-INDENT: 2em"><A href="http://img.blog.163.com/photo/AznZALeCMpsD0F_tfXUKMg==/2261651437870573172.jpg"><IMG border=0 src="http://img.blog.163.com/photo/AznZALeCMpsD0F_tfXUKMg==/2261651437870573172.jpg"></A><BR>选取网页里的如股票代码后点击弹出来的绿色小箭头<BR>
</P><P style="TEXT-INDENT: 2em"><A href="http://img.blog.163.com/photo/OMNxm0-VzbamQ8fUAHcomA==/4244642648797369708.jpg"><IMG border=0 src="http://img.blog.163.com/photo/OMNxm0-VzbamQ8fUAHcomA==/4244642648797369708.jpg"></A><BR>把鼠标放在你所定制的服务上后弹出来的信息框
</P><P style="TEXT-INDENT: 2em">感谢rukey完成<A href="http://ie8.163.com">http://ie8.163.com</A></P></div>]]></description>
	    <author><![CDATA[罗西]]></author>
	    <comments>http://blog.163.com/mike_gz/blog/static/24753220085441813215</comments>
    <slash:comments>0</slash:comments>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/blog/static/24753220085441813215</guid>
    <pubDate>Wed, 4 Jun 2008 16:18:13 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:18:13+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  ta]]></title>	
    <link>http://img.bimg.126.net/photo/RbFjFw0uAV406DJtt99Z9g==/2833045640593940215.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/RbFjFw0uAV406DJtt99Z9g==/2833045640593940215.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/RbFjFw0uAV406DJtt99Z9g==/2833045640593940215.jpg" border="0" width="201" height="240" alt="ta 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/RbFjFw0uAV406DJtt99Z9g==/2833045640593940215.jpg</guid>
    <pubDate>Fri, 9 Jan 2009 12:05:34 +0800</pubDate>
    <dcterms:modified>2009-01-09T12:05:34+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1064]]></title>	
    <link>http://img.bimg.126.net/photo/DLHv4D9cP0UvNG3uaPTNtA==/3737706215741516583.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/DLHv4D9cP0UvNG3uaPTNtA==/3737706215741516583.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/DLHv4D9cP0UvNG3uaPTNtA==/3737706215741516583.jpg" border="0" width="240" height="202" alt="IMG_1064 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/DLHv4D9cP0UvNG3uaPTNtA==/3737706215741516583.jpg</guid>
    <pubDate>Tue, 7 Oct 2008 08:57:14 +0800</pubDate>
    <dcterms:modified>2008-10-07T08:57:14+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  tt]]></title>	
    <link>http://img.bimg.126.net/photo/Yt2DowZhqMMcH-JcRMEyVA==/2860630188311224575.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/Yt2DowZhqMMcH-JcRMEyVA==/2860630188311224575.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/Yt2DowZhqMMcH-JcRMEyVA==/2860630188311224575.jpg" border="0" width="240" height="159" alt="tt 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/Yt2DowZhqMMcH-JcRMEyVA==/2860630188311224575.jpg</guid>
    <pubDate>Sat, 9 Aug 2008 12:50:22 +0800</pubDate>
    <dcterms:modified>2008-08-09T12:50:22+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  4009892518220426335]]></title>	
    <link>http://img.bimg.126.net/photo/sFDk0hgcSObv0sUNF4uubA==/2860348713334501722.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/sFDk0hgcSObv0sUNF4uubA==/2860348713334501722.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/sFDk0hgcSObv0sUNF4uubA==/2860348713334501722.jpg" border="0" width="240" height="180" alt="4009892518220426335 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/sFDk0hgcSObv0sUNF4uubA==/2860348713334501722.jpg</guid>
    <pubDate>Fri, 1 Aug 2008 14:01:55 +0800</pubDate>
    <dcterms:modified>2008-08-01T14:01:55+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  2]]></title>	
    <link>http://img.bimg.126.net/photo/fgMqYvBaoqsze6fd1aX-Ig==/1762033354209558268.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/fgMqYvBaoqsze6fd1aX-Ig==/1762033354209558268.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/fgMqYvBaoqsze6fd1aX-Ig==/1762033354209558268.jpg" border="0" width="240" height="110" alt="2 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/fgMqYvBaoqsze6fd1aX-Ig==/1762033354209558268.jpg</guid>
    <pubDate>Fri, 1 Aug 2008 09:43:13 +0800</pubDate>
    <dcterms:modified>2008-08-01T09:43:13+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  1]]></title>	
    <link>http://img.bimg.126.net/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg" border="0" width="212" height="156" alt="1 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/f8383pYUPRi-VsPkbNBOSw==/4792111478499154380.jpg</guid>
    <pubDate>Fri, 1 Aug 2008 09:43:13 +0800</pubDate>
    <dcterms:modified>2008-08-01T09:43:13+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  VN7W00100]]></title>	
    <link>http://img.bimg.126.net/photo/AQbZ3HUUrKkaYLFkmU8d_w==/2568740637461847328.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/AQbZ3HUUrKkaYLFkmU8d_w==/2568740637461847328.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/AQbZ3HUUrKkaYLFkmU8d_w==/2568740637461847328.jpg" border="0" width="208" height="240" alt="VN7W00100 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/AQbZ3HUUrKkaYLFkmU8d_w==/2568740637461847328.jpg</guid>
    <pubDate>Wed, 18 Jun 2008 09:26:02 +0800</pubDate>
    <dcterms:modified>2008-06-18T09:26:02+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  VN7W0010]]></title>	
    <link>http://img.bimg.126.net/photo/VpDkn2xh_Q6Goa0kxT0wSg==/2568740637461847325.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/VpDkn2xh_Q6Goa0kxT0wSg==/2568740637461847325.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/VpDkn2xh_Q6Goa0kxT0wSg==/2568740637461847325.jpg" border="0" width="160" height="240" alt="VN7W0010 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/VpDkn2xh_Q6Goa0kxT0wSg==/2568740637461847325.jpg</guid>
    <pubDate>Wed, 18 Jun 2008 09:26:02 +0800</pubDate>
    <dcterms:modified>2008-06-18T09:26:02+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1011]]></title>	
    <link>http://img.bimg.126.net/photo/lA18q6_2XPGhsnHjUcc2oQ==/5655395232071179996.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/lA18q6_2XPGhsnHjUcc2oQ==/5655395232071179996.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/lA18q6_2XPGhsnHjUcc2oQ==/5655395232071179996.jpg" border="0" width="240" height="180" alt="IMG_1011 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/lA18q6_2XPGhsnHjUcc2oQ==/5655395232071179996.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1010]]></title>	
    <link>http://img.bimg.126.net/photo/G6Wi6gapSbO_vheizmPK2g==/5655395232071179988.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/G6Wi6gapSbO_vheizmPK2g==/5655395232071179988.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/G6Wi6gapSbO_vheizmPK2g==/5655395232071179988.jpg" border="0" width="240" height="180" alt="IMG_1010 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/G6Wi6gapSbO_vheizmPK2g==/5655395232071179988.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1009]]></title>	
    <link>http://img.bimg.126.net/photo/xOQaYfTWDjUdGnmaAI8Iaw==/5655395232071179974.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/xOQaYfTWDjUdGnmaAI8Iaw==/5655395232071179974.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/xOQaYfTWDjUdGnmaAI8Iaw==/5655395232071179974.jpg" border="0" width="240" height="180" alt="IMG_1009 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/xOQaYfTWDjUdGnmaAI8Iaw==/5655395232071179974.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1008]]></title>	
    <link>http://img.bimg.126.net/photo/9N3RwiO9sneb-5xVuPwuRw==/5655395232071179962.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/9N3RwiO9sneb-5xVuPwuRw==/5655395232071179962.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/9N3RwiO9sneb-5xVuPwuRw==/5655395232071179962.jpg" border="0" width="240" height="180" alt="IMG_1008 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/9N3RwiO9sneb-5xVuPwuRw==/5655395232071179962.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1007]]></title>	
    <link>http://img.bimg.126.net/photo/pqG0qRO2JdmRTujjawFvRw==/5655395232071179953.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/pqG0qRO2JdmRTujjawFvRw==/5655395232071179953.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/pqG0qRO2JdmRTujjawFvRw==/5655395232071179953.jpg" border="0" width="240" height="180" alt="IMG_1007 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/pqG0qRO2JdmRTujjawFvRw==/5655395232071179953.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  IMG_1006]]></title>	
    <link>http://img.bimg.126.net/photo/tOqlwZe7qntKAbyZtJ7tjg==/576742227280864436.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/tOqlwZe7qntKAbyZtJ7tjg==/576742227280864436.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/tOqlwZe7qntKAbyZtJ7tjg==/576742227280864436.jpg" border="0" width="240" height="180" alt="IMG_1006 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/tOqlwZe7qntKAbyZtJ7tjg==/576742227280864436.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 21:52:11 +0800</pubDate>
    <dcterms:modified>2008-06-04T21:52:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  5]]></title>	
    <link>http://img.bimg.126.net/photo/Npo3bpmM6t9Kqj_pnhey9w==/1182757852138584888.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/Npo3bpmM6t9Kqj_pnhey9w==/1182757852138584888.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/Npo3bpmM6t9Kqj_pnhey9w==/1182757852138584888.jpg" border="0" width="240" height="153" alt="5 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/Npo3bpmM6t9Kqj_pnhey9w==/1182757852138584888.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 16:14:43 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:14:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  4]]></title>	
    <link>http://img.bimg.126.net/photo/GHs542ZzXwSNWPY1sfp83w==/1182757852138584886.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/GHs542ZzXwSNWPY1sfp83w==/1182757852138584886.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/GHs542ZzXwSNWPY1sfp83w==/1182757852138584886.jpg" border="0" width="240" height="135" alt="4 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/GHs542ZzXwSNWPY1sfp83w==/1182757852138584886.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 16:14:43 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:14:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  3]]></title>	
    <link>http://img.bimg.126.net/photo/qvPXro4g6yaJRkb0iZiaYg==/1182757852138584884.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/qvPXro4g6yaJRkb0iZiaYg==/1182757852138584884.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/qvPXro4g6yaJRkb0iZiaYg==/1182757852138584884.jpg" border="0" width="240" height="189" alt="3 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/qvPXro4g6yaJRkb0iZiaYg==/1182757852138584884.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 16:14:43 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:14:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  2]]></title>	
    <link>http://img.bimg.126.net/photo/atlSbDkEKvBi9MNUgvsnNg==/1182757852138584882.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/atlSbDkEKvBi9MNUgvsnNg==/1182757852138584882.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/atlSbDkEKvBi9MNUgvsnNg==/1182757852138584882.jpg" border="0" width="240" height="141" alt="2 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/atlSbDkEKvBi9MNUgvsnNg==/1182757852138584882.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 16:14:43 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:14:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  1]]></title>	
    <link>http://img.bimg.126.net/photo/CZ2WHt_gPychLep-ls02tw==/1182757852138584880.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/CZ2WHt_gPychLep-ls02tw==/1182757852138584880.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/CZ2WHt_gPychLep-ls02tw==/1182757852138584880.jpg" border="0" width="240" height="158" alt="1 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/CZ2WHt_gPychLep-ls02tw==/1182757852138584880.jpg</guid>
    <pubDate>Wed, 4 Jun 2008 16:14:43 +0800</pubDate>
    <dcterms:modified>2008-06-04T16:14:43+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[相片:  t]]></title>	
    <link>http://img.bimg.126.net/photo/qhC151UmRW8m1BOKm93a1g==/2880614911657258043.jpg</link>
    <description><![CDATA[<div>
	<a href="http://img.bimg.126.net/photo/qhC151UmRW8m1BOKm93a1g==/2880614911657258043.jpg" target="_blank">
	<img src="http://img.bimg.126.net/photo/qhC151UmRW8m1BOKm93a1g==/2880614911657258043.jpg" border="0" width="240" height="180" alt="t 互联网研究 关注用户体验、产品策划、交互设计"/>
	</a><br/><br/>
</div>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">http://img.bimg.126.net/photo/qhC151UmRW8m1BOKm93a1g==/2880614911657258043.jpg</guid>
    <pubDate>Mon, 2 Jun 2008 14:56:11 +0800</pubDate>
    <dcterms:modified>2008-06-02T14:56:11+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[web:  参考文档]]></title>	
    <link>http://blog.163.com/mike_gz/prevResource.do?selectId=fks_087065082080081065093095074065080081084064086</link>
    <description><![CDATA[<ul>
	<li>
	<a href="http://chyf1982.blueidea.com/archives/2006/1637.shtml" target="_blank">支持标准的手动＋自动轮显</a>
	: 自动切换</li>

	<li>
	<a href="http://chyf1982.blueidea.com/archives/2006/1228.shtml" target="_blank">window方法属性</a>
	: 方法属性</li>
</ul>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">collection/static/fks_087065082080081065093095074065080081084064086</guid>
    <pubDate>Fri, 18 May 2007 15:00:03 +0800</pubDate>
    <dcterms:modified>2007-05-18T15:00:03+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[web:  友情链接]]></title>	
    <link>http://blog.163.com/mike_gz/prevResource.do?selectId=fks_080065082084081067085074084071083083082065</link>
    <description><![CDATA[<ul>
	<li>
	<a href="http://livedocs.macromedia.com/flash/8_cn/main/wwhelp/wwhimpl/js/html/wwhelp.htm" target="_blank">flash8 中文手册</a>
	: 部落数据迁移新建链接</li>

	<li>
	<a href="http://www5.blog.163.com/-aIDo.html" target="_blank">frienk</a>
	: 部落数据迁移新建链接</li>

	<li>
	<a href="http://www7.blog.163.com/-Ko65.html" target="_blank">张怀旧的博客</a>
	: 部落数据迁移新建链接</li>

	<li>
	<a href="http://xfwindow.it.com.cn/" target="_blank">前进路249号</a>
	: 部落数据迁移新建链接</li>

	<li>
	<a href="http://umike.photo.163.com" target="_blank">我的相册</a>
	: 部落数据迁移新建链接</li>
</ul>]]></description>
	    <author><![CDATA[mike_gz]]></author>
    <guid isPermaLink="false">collection/static/fks_080065082084081067085074084071083083082065</guid>
    <pubDate>Wed, 13 Dec 2006 10:57:40 +0800</pubDate>
    <dcterms:modified>2006-12-13T10:57:40+08:00</dcterms:modified>
  </item>    
  <item>
  	<title><![CDATA[罗西关注的博友]]></title>	
    <link>http://blog.163.com/mike_gz/friends</link>
    <description><![CDATA[<div>
			<a href="http://sanllyzhao.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/FYFKbrlRNzxszmJKK3MFZg==/1126744331772791472.jpg" border="0" />夕阳 - sanllyzhao</a>
			<a href="http://hctan.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/bdk1fdUG-MJUQ0EIlmyMsQ==/182395784908674995.jpg" border="0" />阿海</a>
			<a href="http://bsu.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/eY-lIU7zmaKCSfEbWtnv_w==/180143985095093949.jpg" border="0" />网友甲</a>
			<a href="http://fanyaci.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/-HQz-5icKOFVOs5d0Jw0MA==/5428244925865063917.jpg" border="0" />非洲和尚</a>
			<a href="http://oldjanson.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/3Qf9EfYkcKvMIyq-0b3kDw==/229965055972612615.jpg" border="0" />janson 简森</a>
			<a href="http://faykwong.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/wQAqH0tXapVP-oYiZ6ye6Q==/175921860444403293.jpg" border="0" />Alex Kwong</a>
			<a href="http://shenhaiyu0618.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/_98P-pD7mw3VMOfJAwuC0g==/215891307137086095.jpg" border="0" />深海鱼</a>
			<a href="http://ued163.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/x9MJRX8xEVn6PivwJ_1Xtw==/5069082855582374701.jpg" border="0" />ued163</a>
			<a href="http://snowmay.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/wMJEBQl7x5h7QCo-5RvT_g==/213358032347060967.jpg" border="0" />Snowmay</a>
			<a href="http://faitle.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/LgqjHzwg7inpn-L8o-WEyA==/2314850208468589729.jpg" border="0" />faitle</a>
			<a href="http://speed97.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/9slUAzuf2igVlTR-wUH6Cg==/3133097965766446358.jpg" border="0" />speed97</a>
			<a href="http://skybluecai.blog.163.com/" target="_blank"><img src="http://ava.bimg.126.net/photo/rwfySJ8gcoJh70T2J5PPww==/185492009652548495.jpg" border="0" />蔚蓝天空</a>
</div>]]></description>
    <guid isPermaLink="true">http://blog.163.com/mike_gz/friends</guid>
    <pubDate>Tue, 1 Jan 2008 00:00:00 +0800</pubDate>
    <dcterms:modified>2008-01-01T00:00:00+08:00</dcterms:modified>
  </item>    
 </channel>
</rss>