<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>achun</title>
    <description>要干就干，别扯淡。</description>
    <link>http://achun.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>根据nicEdit代码风格制作的js模块打包工具,未完成</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/217757" style="color:red;">http://achun.javaeye.com/blog/217757</a>&nbsp;
          发表时间: 2008年07月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>根据<a href="../../blog/214954" target="_blank">nicEdit 源码组织结构</a>
中所讲的组织方法,和打包注释,其实可以做一个通用的,nicEdit代码风格的模块打包器.</p>
<p>这里用JavaScript实现一个(没有全部完成,有些地方如何做更好,还在考虑中),</p>
<p>对于一个打包器来说,数据的来源我并不考虑,因为这和使用方法有关,你可以从后台程序输出,也可以通过web服务器支持目录列表自动获取,就是因为方法很多,所以这才不是打包器考虑的内容.</p>
<pre name="code" class="js">/**
 * nicEdit 风格 模块打包器说明
 */
var modulePacker={
  /**
   * 初始化,输入是一个nicEdit 风格的 src 目录结构的对象,最终js文件直接附加原始文件文本
   * 例如:
   {
     nicCore:{
         nicCore.js:'source code',
         bkLib.js:'source code'
     },
     nicCode:{
         nicCode.js:'source code'
     }
   }
   * 生成一个按模块分的依赖关系对象 this.Dep
   * 生成一个按依赖关系的模块打包次序数组 this.Order
   */
  init:function(src){
    this.Dep={};
    for (var i in src) {
      if (typeof src[i]=='string' || typeof src[i][i+'.js']!='string') continue;
      this.Dep[i]={};
      var module = src[i][i+'.js'];
      var s = module.indexOf('@requires:');
      if (s&lt;0) continue;
      s=s+'@requires:'.length;
      var e = module.indexOf('\n',s);
      if (e&lt;0) continue;
      var dep=module.slice(s,e).split(',');
      for (var j = 0; j &lt; dep.length; j++) {
        dep[j]=(dep[j] || &quot;&quot;).replace( /^\s+|\s+$/g, &quot;&quot; );
        this.Dep[i][dep[j]]=true;
      }
    }
    this.sort();
    return this;
  },
  /**
   * 获取某个 moudle 都请求了那些modle,或是否请求了dep
   */
  getrequire:function(module,dep){
    if(dep &amp;&amp; this.Dep[module])
      return this.Dep[module][dep];
    return this.Dep[module];
  },
  /**
   * 依赖于输入参数 module 的模块
   */
  dependent:function(module){
    var re={};
    for (var i in this.Dep){
      if (this.Dep[i][module])
        re[i]=true;
    }
    return re;
  },
  /**
   * 根据依赖关系生成 module 打包次序
   */
  sort:function(){
    function find(str){
      for (var i=0;i&lt;order.length;i++) {
        if (order[i]==str) return i;
      }
      return null;
    }
    var order=this.Order=[];
    var pos;
    for (var i in this.Dep) {
      pos=find(i);
      if(pos!=null) {
        for (var j in this.Dep[i]) {
          var pos2=find(j);
          if (pos2&lt;pos) continue;
          var str=order[pos];
          order[pos]=order[pos2];
          order[pos2]=str;
        }
        continue;
      }
      for (var j in this.Dep[i]) {
        pos=find(j);
        if(pos!=null) continue;
        order.push(j);
      }
      order.push(i);
    }
    return order;
  },
  /**
   * 配置语法
   */
  Config:{
    /*配置开始和结束*/
    configStart:'START CONFIG',
    configEnd:'END CONFIG',
    /*合并图标文件的URL路径*/
    iconPathStart:'NICEDIT_ICONSPATH_START',
    iconPathEnd:'NICEDIT_ICONSPATH_END',
    /*图标和标号列表*/
    iconListStart:'NICEDIT_ICONLIST_START',
    iconListEnd:'NICEDIT_ICONLIST_END',
    /*需要删除的代码*/
    removeStart:'NICEDIT_REMOVE_START',
    removeEnd:'NICEDIT_REMOVE_END'
  }
}</pre>
<p>&nbsp;下面应该继续写关于配置的一些东西了,稍后完成.</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/217757#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Jul 2008 11:28:06 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/217757</link>
        <guid>http://achun.javaeye.com/blog/217757</guid>
      </item>
      <item>
        <title>css 常用配色,做个笔记</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/216447" style="color:red;">http://achun.javaeye.com/blog/216447</a>&nbsp;
          发表时间: 2008年07月19日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="background-color: #09460f; font-family: courier new,courier; color: #ff0000; font-size: medium;">&nbsp;9460F &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>
</p>
<p><span style="background-color: #588e03; font-family: courier new,courier; color: #ff0000; font-size: medium;">#588E03 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span>
<span style="font-family: courier new,courier; color: #ff0000; font-size: medium;"><br />
</span>
<span style="background-color: #9cce2e; font-family: courier new,courier; color: #ff0000; font-size: medium;">#9CCE2E &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; </span>
<span style="font-family: courier new,courier; color: #ff0000; font-size: medium;"><br />
</span>
<span style="background-color: #c3bb1f; font-family: courier new,courier; color: #ff0000; font-size: medium;">#C3BB1F &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span>
<span style="font-family: courier new,courier; color: #ff0000; font-size: medium;"><br />
</span>
<span style="background-color: #f9630d; font-family: courier new,courier; color: #ff0000; font-size: medium;">#F9630D &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span>
<span style="font-family: courier new,courier; color: #ff0000; font-size: medium;"><br />
</span>
<span style="background-color: #f7ae16; font-family: courier new,courier; color: #ff0000; font-size: medium;">#F7AE16 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span>
<span style="font-family: courier new,courier; color: #ff0000; font-size: medium;"><br />
</span>
<span style="background-color: #ffec00; font-family: courier new,courier; color: #ff0000; font-size: medium;">#FFEC00 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</span>
</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img src="http://www.colourlovers.com/paletteImgDetail/1024/585/DE5B5B/D95252/D96952/D98A52/D9B052/back_to_the_remedy.png" height="103" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImgDetail/1024/585/1A1414/261715/4D1919/3D3E4A/5C5E5E/even_if_it_hurts.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImgDetail/1024/585/333741/D3D5E6/FFFFFF/680064/8D468B/modern_japan.png2" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImgDetail/1024/585/CA141A/DB5026/E47B24/E99C17/FDC119/light_fire.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p>&nbsp;</p>
<p><img src="http://www.colourlovers.com/paletteImg/CA141A/E99C17/FFCC74/FDC119/FDE6A5/gryffon_dor.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/647D2F/E8E8E8/ECFFC2/B4E053/415711/Limeade.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/32373C/E8E8E8/FBFAFF/F1F6F1/839CA5/Penquins.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/242424/E8E8E8/C2A469/914E24/1F1E18/ruff_life..png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/F0F0F0/ECCFFA/BE9FCC/9C5DB9/F0F0F0/Silver_Mauve.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/7D6942/AF7A52/F67F00/FFA833/A6E3BB/Andaman_Sea.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
<p><img src="http://www.colourlovers.com/paletteImg/827A7C/757676/484444/3C3B3B/939696/First.png" height="102" alt="" style="float: left; margin: 2px;" width="205" />
</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/216447#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 19 Jul 2008 10:37:03 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/216447</link>
        <guid>http://achun.javaeye.com/blog/216447</guid>
      </item>
      <item>
        <title>HTTP连接等出错代码大全</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/215528" style="color:red;">http://achun.javaeye.com/blog/215528</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>Information Codes<br />
&nbsp; 100 - Continue&nbsp; 101 - Switching Protocols<br />
<br />
Success Codes<br />
&nbsp; 200 - OK<br />
&nbsp; 201 - Created<br />
&nbsp; 202 - Accepted<br />
&nbsp; 203 - Non-Authoritative Information (for DNS)<br />
&nbsp; 204 - No Content<br />
&nbsp; 205 - Reset Content<br />
&nbsp; 206 - Partial Content<br />
<br />
Redirection Codes<br />
&nbsp; 300 - Multiple Choices<br />
&nbsp; 301 - Moved Permanently<br />
&nbsp; 302 - Moved Temporarily<br />
&nbsp; 303 - See Other<br />
&nbsp; 304 - Not Modified<br />
&nbsp; 305 - Use Proxy<br />
&nbsp; 307 - Redirect Keep Verb<br />
<br />
Failure Codes<br />
&nbsp; 400 - Bad Request<br />
&nbsp; 401 - Unauthorized<br />
&nbsp; 402 - Payment Required<br />
&nbsp; 403 - Forbidden<br />
&nbsp; 404 - Not Found<br />
&nbsp; 405 - Bad Request<br />
&nbsp; 406 - Not Acceptable<br />
&nbsp; 407 - Proxy Authentication Required<br />
&nbsp; 408 - Request Timed-Out<br />
&nbsp; 409 - Conflict<br />
&nbsp; 410 - Gone<br />
&nbsp; 411 - Length Required<br />
&nbsp; 412 - Precondition Failed<br />
&nbsp; 413 - Request Entity Too Large<br />
&nbsp; 414 - Request, URI Too Large<br />
&nbsp; 415 - Unsupported Media Type<br />
<br />
Server Error Codes<br />
&nbsp; 500 - Internal Server Error<br />
&nbsp; 501 - Not Implemented<br />
&nbsp; 502 - Bad Gateway<br />
&nbsp; 503 - Server Unavailable<br />
&nbsp; 504 - Gateway Timed-Out<br />
&nbsp; 505 - HTTP Version not supported<br />
<br />
Internet API Error Codes<br />
&nbsp; 12001 - Out of Handles<br />
&nbsp; 12002 - Timeout<br />
&nbsp; 12003 - Extended Error<br />
&nbsp; 12004 - Internal Error<br />
&nbsp; 12005 - Invalid URL<br />
&nbsp; 12006 - Unrecognized Scheme<br />
&nbsp; 12007 - Name Not Resolved<br />
&nbsp; 12008 - Protocol Not Found<br />
&nbsp; 12009 - Invalid Option<br />
&nbsp; 12010 - Bad Option Length<br />
&nbsp; 12011 - Option not Settable<br />
&nbsp; 12012 - Shutdown<br />
&nbsp; 12013 - Incorrect User Name<br />
&nbsp; 12014 - Incorrect Password<br />
&nbsp; 12015 - Login Failure<br />
&nbsp; 12016 - Invalid Option<br />
&nbsp; 12017 - Operation Cancelled<br />
&nbsp; 12018 - Incorrect Handle Type<br />
&nbsp; 12019 - Inccorect Handle State<br />
&nbsp; 12020 - Not Proxy Request<br />
&nbsp; 12021 - Registry Value Not Found<br />
&nbsp; 12022 - Bad Registry Parameter<br />
&nbsp; 12023 - No Direct Access<br />
&nbsp; 12024 - No Content<br />
&nbsp; 12025 - No Callback<br />
&nbsp; 12026 - Request Pending<br />
&nbsp; 12027 - Incorrect Format<br />
&nbsp; 12028 - Item Not Found<br />
&nbsp; 12029 - Cannot Connect<br />
&nbsp; 12030 - Connection Aborted<br />
&nbsp; 12031 - Connection Reset<br />
&nbsp; 12032 - Force Retry<br />
&nbsp; 12033 - Invalid Proxy Request<br />
&nbsp; 12034 - Need UI<br />
&nbsp; 12035 - Not Defined in WinInet<br />
&nbsp; 12036 - Handle Exists<br />
&nbsp; 12037 - See Cert Date Invalid<br />
&nbsp; 12038 - See Cert CN Invalid<br />
&nbsp; 12039 - HTTP to HTTPS on Redir<br />
&nbsp; 12040 - HTTPs to HTTP on Redir<br />
&nbsp; 12041 - Mixed Security<br />
&nbsp; 12042 - Chg Post is Non Secure<br />
&nbsp; 12043 - Post is Non Secure<br />
&nbsp; 12044 - Client Auth Cert Needed<br />
&nbsp; 12045 - Invalid CA (Cert)<br />
&nbsp; 12046 - Client Auth Not Setup<br />
&nbsp; 12047 - Async Thread Failed<br />
&nbsp; 12048 - Redirect Scheme Changed<br />
&nbsp; 12049 - Dialog Pending<br />
&nbsp; 12050 - Retry Dialog<br />
&nbsp; 12052 - Https Http Submit Redir<br />
&nbsp; 12053 - Insert Cdrom<br />
&nbsp; 12171 - Failed DueToSecurityCheck<br />
<br />
FTP API Error Codes<br />
&nbsp; 12110 - Transfer in Progress<br />
&nbsp; 12111 - FTP Dropped<br />
<br />
Gopher API Error Codes<br />
&nbsp; 12130 - Protocol Error<br />
&nbsp; 12131 - Not File<br />
&nbsp; 12132 - Data Error<br />
&nbsp; 12133 - End of Data<br />
&nbsp; 12134 - Invalid Locator<br />
&nbsp; 12135 - Invalid Locator Type<br />
&nbsp; 12136 - Not Gopher Plus<br />
&nbsp; 12137 - Attribute Not Found<br />
&nbsp; 12138 - Unknown Locator<br />
<br />
HTTP API Error Codes<br />
&nbsp; 12150 - Header Not Found<br />
&nbsp; 12151 - Downlevel Server<br />
&nbsp; 12152 - Invalid Server Response<br />
&nbsp; 12153 - Invalid Header<br />
&nbsp; 12154 - Invalid Query Request<br />
&nbsp; 12155 - Header Already Exists<br />
&nbsp; 12156 - Redirect Failed<br />
&nbsp; 12157 - Security Channel Error<br />
&nbsp; 12158 - Unable to Cache File<br />
&nbsp; 12159 - TCP/IP not installed<br />
&nbsp; 12160 - Not Redirected<br />
&nbsp; 12161 - Cookie Needs Confirmation<br />
&nbsp; 12162 - Cookie Declined<br />
&nbsp; 12168 - Redirect Needs Confirmation<br />
<br />
Additional Internet API Error Codes<br />
&nbsp; 12157 - Security Channel Error<br />
&nbsp; 12158 - Unable To Cache File<br />
&nbsp; 12159 - Tcpip Not Installed<br />
&nbsp; 12163 - Disconnected<br />
&nbsp; 12164 - Server Unreachable<br />
&nbsp; 12165 - Proxy Server Unreachable<br />
&nbsp; 12166 - Bad Auto Proxy Script<br />
&nbsp; 12167 - Unable To Download Script<br />
&nbsp; 12169 - Sec Invalid Cert<br />
&nbsp; 12170 - Sec Cert Revoked</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/215528#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Jul 2008 19:04:01 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/215528</link>
        <guid>http://achun.javaeye.com/blog/215528</guid>
      </item>
      <item>
        <title>caller 仿冒,有浏览器兼容性问题!纯属探讨测试</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/215422" style="color:red;">http://achun.javaeye.com/blog/215422</a>&nbsp;
          发表时间: 2008年07月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>首先,我不知道这个方法能怎么应用,仅仅知道这是一种<span style="color: #ff6600;"><strong>无副作用</strong></span>的方法(虽然看似多余的丑陋的怪异的方法,),而且有浏览器兼容性问题,不知道ecma-262是如何定义caller的.</p>
<pre name="code" class="js">function foo(s){
  if (!s){
    f.caller=function(s){alert('ya......'+s)};
    f();
  }else
    alert(s);
}
function f(){
  var caller=arguments.callee.caller;
  delete arguments.callee.caller;
  arguments.callee.caller('foo');
  caller('foo');
}
foo();</pre>
&nbsp;
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/215422#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Jul 2008 14:59:29 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/215422</link>
        <guid>http://achun.javaeye.com/blog/215422</guid>
      </item>
      <item>
        <title>nicEdit 源码组织结构</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214954" style="color:red;">http://achun.javaeye.com/blog/214954</a>&nbsp;
          发表时间: 2008年07月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>nicEdit 源码组织很有规律从src目录开始看,</p>
<p style="padding-left: 30px;">&nbsp;</p>
<p style="padding-left: 30px;">nicAdvancedButton<br />
nicBBCode<br />
nicButtonTips<br />
nicCode<br />
nicColors<br />
nicCore<br />
nicImage<br />
nicLink<br />
nicPane<br />
nicSelect<br />
nicUndo<br />
nicXHTML<br />
<strong>nicLicense.js</strong>
</p>
<p>&nbsp;</p>
<p>里面除了一个<strong>nicLicense.js</strong>
是个文件,其他的都是目录,而这个nicLicense.js其实就是一段版权的声明.</p>
<p>如果继续看每个子目录内容的话,你会发现一个规律:</p>
<p><strong>每个目录下都有一个和目录名称一致的js文件</strong>
</p>
<p>这就是第一个规律,或者称之为<strong>代码规范</strong>
,<strong>编程契约</strong>
,也就是说:</p>
<p><strong><span style="color: #ff6600;">nicEdit按目录来存储模块,目录名和模块名称一致,目录下一定有一个和目录(</span>
</strong>
<strong><span style="color: #ff6600;">模块)</span>
</strong>
<strong><span style="color: #ff6600;">名一致的js文件</span>
</strong>
</p>
<p>那我们就称这个文件为<span style="color: #000000;"><strong>模块主文件</strong>
</span>
.让我们截取nicCore/nicCore.js的注释来看看:</p>
<pre name="code" class="js">/**
 * NicEdit Core
 * @description: Core of nicEdit with basic features, required for all plugins 
 * @author: Brian Kirchoff
 * @version: 0.9.0
 * @order: bkLib,nicConfig,nicCore,nicInstance,nicIFrameInstance,nicPanel,nicButton,nicPlugin
 * The core includes nicEditors and nicEditor classes that handle the public interface for using NicEdit as well as a central point for sending events and commands.
 */</pre>
<p>注意这个注释不仅仅起到注释作用,阐明</p>
<pre name="code" class="js">@description: 模块功能说明
@author: 作者
@version: 版本</pre>
<p>而且 <span style="color: #ff6600;"><strong>@order</strong>
</span>
 还明确了此模块中文件的调入次序要求.</p>
<pre name="code" class="js">@order: bkLib,nicConfig,nicCore,nicInstance,nicIFrameInstance,nicPanel,nicButton,nicPlugin
</pre>
<p>再看nicImage模块的主文件注释</p>
<pre name="code" class="js">/**
 * nicImage
 * @description: Adds buttons to insert images in the editor area
 * @requires: nicCore, nicPane, nicAdvancedButton
 * @author: Brian Kirchoff
 * @version: 0.9.0
 */</pre>
<p>里面有一个:</p>
<pre name="code" class="js">@requires: nicCore, nicPane, nicAdvancedButton</pre>
<p>也就是说:<span style="color: #ff6600;"><strong>@requires</strong>
</span>
 声明了模块间的依赖关系,在这个例子中要求预先调入</p>
<pre name="code" class="js"> nicCore, nicPane, nicAdvancedButton</pre>
<p>这几个模块.</p>
<p>通过 <span style="color: #ff6600;"><strong>@requires,</strong>
</span>
<span style="color: #ff6600;"><strong>@order </strong>
</span>
.形成了一个模块,模块文件的调入次序定义.</p>
<p>&nbsp;</p>
<p>最后我们看看nicCore/nicConfig.js</p>
<pre name="code" class="js">/* START CONFIG */
var nicEditorConfig = bkClass.extend({
	buttons : {为方便查看此处略去},
	iconsPath : /* NICEDIT_ICONSPATH_START */'nicEditorIcons.gif'/* NICEDIT_ICONSPATH_END */,
	buttonList : ['bold','italic','underline','left','center','right','ol','ul','fontSize','fontFamily','fontFormat','indent','outdent','link','image'],
	iconList : /* NICEDIT_ICONLIST_START */{}/* NICEDIT_ICONLIST_END */
	/* NICEDIT_REMOVE_START */,iconFiles : {'bold' : 'src/nicCore/icons/bold.gif', 'italic' : 'src/nicCore/icons/italic.gif', 'underline' : 'src/nicCore/icons/underline.gif', 'outdent' : 'src/nicCore/icons/outdent.gif', 'indent' : 'src/nicCore/icons/indent.gif', 'hr' : 'src/nicCore/icons/hr.gif', 'superscript' : 'src/nicCore/icons/superscript.gif', 'subscript' : 'src/nicCore/icons/subscript.gif', 'strikethrough' : 'src/nicCore/icons/strikethrough.gif', 'ul' : 'src/nicCore/icons/ul.gif', 'ol' : 'src/nicCore/icons/ol.gif', 'left' : 'src/nicCore/icons/left.gif', 'right' : 'src/nicCore/icons/right.gif', 'center' : 'src/nicCore/icons/center.gif', 'justify' : 'src/nicCore/icons/justify.gif', 'save' : 'src/nicCore/icons/save.gif'}/* NICEDIT_REMOVE_END */
});
/* END CONFIG */</pre>
<p>这个文件中含有全部的打包指示语法(略去"/* "和" */")</p>
<ol>
<li>配置开始和结束:<br />
START CONFIG<br />
END CONFIG</li>
<li>合并图标文件的URL路径:因为打包后要把所有涉及的图标合并起来成为一个文件,所以要制定这个文件的URL<br />
NICEDIT_ICONSPATH_START<br />
NICEDIT_ICONSPATH_END</li>
<li>图标和标号列表:既然图标合并了,那就要标注图标名称和对应的序号<br />
NICEDIT_ICONLIST_START<br />
NICEDIT_ICONLIST_END</li>
<li>需要删除的代码:打包后应该删除的代码<br />
NICEDIT_REMOVE_START<br />
NICEDIT_REMOVE_END<br />
</li>
</ol>
<p>这些定义在其他文件里也可能出现,回头看看这个组织结构,很合理.</p>
<p>我为这个结构添加了一个新的兼容规则:如果我们扩展(扩展不是插件,是指对nicEdit原模块的改造)了nicEdit,为了不破坏原来的结构和源代码(因为可能要升级),我采取了一个小技巧:对那一个文件的实现进行扩展就按这样的规则起名字:</p>
<pre name="code" class="js">foo.js--&gt;fooEx.js</pre>
<p>我们对nicEdit进行打包的时候,确定文件次序后,如果有扩展(Ex),直接把对应的扩展在原文件后调入就可以了(通过文件名的规则).</p>
<p>例子:对"__"函数的扩展,因__在nicCore/bkLib.js文件中所以对应的文件名是nicCore/bkLibEx.js:</p>
<pre name="code" class="js">/**
 * nicEdit bkLib module Extend
 * @description: bkLib module Extend
 * @author: achun.shx at gmail.com
 * @version: 0.9.0
 */
var nicEditorI18N=function(s){  
  return s;
};
function __(s) {
  return nicEditorI18N(s);
}
</pre>
<p>__函数的本意就是为了实现国际化(I18N)设立的接口,如果我们要中文化,就需要进行中文化的扩展,这里我起了一个符合常规习惯的函数</p>
<pre name="code" class="js">nicEditorI18N</pre>
<p>重定义了__,让__调用nicEditorI18N,那国际化在哪里呢?</p>
<p>让我们做一个nicLang的插件:</p>
<p>nicLang/nicLang.js</p>
<pre name="code" class="js">/**
 * nicLang
 * @description: Add I18N for nicEdit
 * @requires: nicCore
 * @author: achun.shx at gmail.com
 * @version: 0.9.0
 */
var nicEditorI18N=function(s){
  var callee=arguments.callee;
  return callee[callee.withIn][s] || s;
};

bkExtend(nicEditorI18N,{
	withIn:navigator.userLanguage||navigator.language,
	setLang:function(lang){
		if (typeof this[lang]=='object') this.withIn=lang;
	},
	en:{}
});</pre>
<p>这里重新定义了</p>
<pre name="code" class="js">nicEditorI18N</pre>
<p>而具体的国际化文件是独立的,比如nicLang/zh-CN.js:</p>
<pre name="code" class="js">/**
 * nicEdit language support zh-CN
 * @description: Language Support zh-CN
 * @author: achun.shx at gmail.com
 * @version: 0.9.0
 */
nicEditorI18N['zh-CN'] = {
"save":"保存",
"undo":"撤销",
"redo":"重做",
"Click to Bold":"加黑",
"Click to Italic":"倾斜",
"Click to Underline":"下划线",
"Left Align":"左对齐",
"Center Align":"中间对齐",
"Right Align":"右对齐",
"Insert Ordered List":"有序列表",
"Insert Unordered List":"无序列表",
"Font Size...":"字体大小",
"Font Family...":"字体样式",
"Font Format...":"字体格式",
"Select Font Size":"字体大小",
"Select Font Family":"字体样式",
"Select Font Format":"字体格式",
"Click to Subscript":"下标",
"Click to Superscript":"上标",
"Click to Strike Through":"删除线",
"Remove Indent":"减少缩进量",
"Indent Text":"增加缩进量",
"Horizontal Rule":"水平线",
"Change Text Color":"更改文字颜色",
"Change Background Color":"更改背景色",
"Add Image":"增改图片",
"Add/Edit Image":"增改图片",
"Edit HTML":"编辑 HTML",
"Add/Edit Link":"增改链接",
"Add Link":"增改链接",
"Remove Link":"移除链接",
"File Explore":"文件管理器",
"submit":"确认",
"Align":"对齐",
"Alt Text":"替代文字",
"URL":"地址",
"Title":"提示",
"Open In":"打开方式"
};</pre>
<p>好了我们分析完了nicEdit的结构,给出了最简单的一个扩展和插件实例,剩下的就是书写一个打包工具了,我准备用js重新写一个打包工具,稍后放出.</p>
<p><a href="../../../category/31274" target="_self">nicEdit专题</a>
</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214954#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 15 Jul 2008 14:07:43 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214954</link>
        <guid>http://achun.javaeye.com/blog/214954</guid>
      </item>
      <item>
        <title>JavaScript对象工厂实现(发现此方法有浏览器兼容性问题,无效了)</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214285" style="color:red;">http://achun.javaeye.com/blog/214285</a>&nbsp;
          发表时间: 2008年07月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>这个工厂是不是和别人说的工厂模式不太一样呀！所以说是对象工厂。名字只是个符号。</p>
<p>&nbsp;</p>
<pre name="code" class="js">/**
 *名称:JavaScript 对象工厂
 *说明:根据第一参数的类型,创建同类型的对象,并且用其它参数对象的成员通过prototype方法扩展此返回对象.
 */
function Factory(){
	if (0==arguments.length) return null;
	var args=[].slice.call(arguments,0);
	var self=args.shift();
	switch(self.constructor){
	case Function:
		var factory=function(){
			var func=function(){
				if (typeof arguments.callee.this =='function')
					arguments.callee.this.apply(arguments.callee,arguments);
			}
			for (var p in this) func[p]=this[p];
			return func;
		}
		for (var i=0;i&lt;args.length;i++)
			for (var p in args[i])
				factory.prototype[p]=args[i][p];
		return new factory();
	case Array:
	case Object:
		var factory=function(){};
		factory.prototype=self;
               return new factory;
	case Number:
	case Boolean:
		return (self).constructor(self);
	}
}
Factory(3);
Factory(true);
Factory({foo:3});
Factory([{d:3}]);
function ff(){};
Factory(ff);
</pre>
&nbsp;
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214285#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 13 Jul 2008 01:03:40 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214285</link>
        <guid>http://achun.javaeye.com/blog/214285</guid>
      </item>
      <item>
        <title>无污染的 JavaScript 对象设计</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214270" style="color:red;">http://achun.javaeye.com/blog/214270</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>在使用JavaScript构建对象时，出于某种需求要使用prototype（原型定义）设计，</p>
<p>不过这种设计当中有一个讨厌的事情就是Array污染，比如这样定义：</p>
<pre name="code" class="js">Array.prototype.foo='foo';</pre>
<p>&nbsp;这是一个典型的Array污染，因为所有的Array对象都会继承foo这个成员。这对于习惯用</p>
<pre name="code" class="js">for (var in [])</pre>
<p>这样语法的是个灾难，虽然有方法可以避免，但是这个问题的麻烦还有很多。</p>
<p>现在介绍一种无污染的设计方法:</p>
<pre name="code" class="js">function array(){};
array.prototype=[];
array.prototype.slice=function(){return this.length;}
var a=new array;
alert('array.slice():'+a.slice());
alert('Array.slice():'+[1,2,3].slice(1));
function object(){};
object.prototype={};
object.prototype.foo=function(){return this.name;}
var o=new object;
o.name='name from new object';
alert('object.foo():'+o.foo());
alert('{foo:"foo"}.foo:'+({foo:"foo"}).foo);</pre>
<p>就是这样了，如果你的代码有一些特殊的需要，也许这个方法会有所帮助。</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214270#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 23:02:18 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214270</link>
        <guid>http://achun.javaeye.com/blog/214270</guid>
      </item>
      <item>
        <title>固有对象和非固有对象继承的差异</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214248" style="color:red;">http://achun.javaeye.com/blog/214248</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>&nbsp;</p>
<p>这篇是 上篇 <a href="../../../blog/214228" target="_blank">固有对象和非固有对象的成员,值类型赋值,非值型引用的差异</a>
</p>
<p>的继续.</p>
<p>首先我们这里说固有对象就是 <strong><span style="color: #ff6600;">布尔值</span>
 </strong>
<strong><span style="color: #ff6600;">字符串</span>
 </strong>
<strong><span style="color: #ff6600;">数值 </span>
</strong>
<strong><span style="color: #ff6600;">通用对象 </span>
</strong>
<strong><span style="color: #ff6600;">数组 </span>
</strong>
<strong><span style="color: #ff6600;">函数</span>
 </strong>
(<strong><span style="color: #ff6600;">未定义</span>
 </strong>
<strong><span style="color: #ff6600;">空值</span>
太特殊,就不提了</strong>
)</p>
<p>对应的对象就是 Boolean,String,Number,Object,Array,Function(这几个字母在这里指的是对象,不是指类型表示,这几个对象的类型都是 function/函数 )</p>
<p>&nbsp;</p>
<p>还记得上篇中说的</p>
<p><span style="color: #ff6600;"><strong>无法对</strong>
<strong>值类型赋予新的可变成员</strong>
</span>
</p>
<p><strong><span style="color: #ff6600;">布尔值</span>
 </strong>
<strong><span style="color: #ff6600;">字符串</span>
 </strong>
<strong><span style="color: #ff6600;">数值&nbsp;</span>
</strong>
 就是值类型, Boolean,String,Number 不是值类型,是function</p>
<p>这个绕嘴的说法都是因为文字上的写法造成的,我们用 小写 boolean,string,number (其实javascript也就是这么表示的)或中文的布尔值,字符串,数值表示类型,Boolean,String,Number表示JavaScript 的3个对象.</p>
<p>所以:</p>
<pre name="code" class="js">/*以下有效*/
Boolean.foo='foo';
String.foo='foo';
Number.foo='foo';
Object.foo='foo';
Array.foo='foo';
Function.foo='foo';
/*以下无效*/
'string'.foo='foo';
(1).foo='foo';
true.foo='foo';
</pre>
<p>&nbsp;下面看看用prototype(原型定义)方法扩展对象在使用上的差别:</p>
<pre name="code" class="js">String.prototype.foo='foo';
var v=new String('string');
v.foo=3;
alert(v.foo);//3
var v='string';
v.foo=3;
alert(v.foo);//foo
</pre>
<p>噢,原来new这个关键字用和不用还是有差别的,同样的道理也适用于Boolean,Number,但是:</p>
<pre name="code" class="js">Object.prototype.foo='foo';
var v=new Object();
v.foo=3;
alert(v.foo);//3
var v={};
v.foo=3;
alert(v.foo);//3,原型都被改了
Object.prototype.foo={v:'foo'};//非值对象也同样
var v={};
v.foo.v=3;
alert(v.foo.v);//3
var v={};
alert(v.foo.v);//3,原型都被改了

</pre>
<p>进一步:</p>
<pre name="code" class="js">String.prototype.foo={v:'foo'};
var v=new String('string');
v.foo.v=3;
alert(v.foo.v);//3
var v='string';
alert(v.foo.v);//3,原型都被改了
</pre>
<p>值对象和非值对象就是不一样.</p>
<p>&nbsp;</p>
<p>好像有些乱,我也没有找到合适的语言来组织这个</p>
<pre name="code" class="js">var v=new String('string');//和
var v='string';//以及
String.prototype.foo={foo:'foo'};//对JavaScript内建 string的影响到底如何描述
</pre>
<p>&nbsp;</p>
<p>不过对于<strong>非固有对象</strong>
也就是<strong>对象</strong>
就没有那么复杂了,</p>
<pre name="code" class="js">var foo=function(){};
foo.prototype={v:'foo',foo:{v:'foo'}};
var o=new foo;
o.v=3;
o.foo.v=4;
var o =new foo;
alert(o.v);//foo
alert(o.foo.v);//,原型都被改了
</pre>
<p>&nbsp;原因很简单,因为foo.prototype只不过由于名称的特殊,会让JavaScript对new 操作进行特殊的继承处理,除此之外,</p>
<p>foo.prototype也具有普通对象的特性,符合<strong>值类型拷贝副本</strong>
,<strong>非值型引用</strong>
的规律</p>
<p>那容易让人迷惑的o.foo.v的v不也是<strong>值类型</strong>
么?是可是别忘了前面的foo是<strong>非值型</strong>
,</p>
<p><strong>o.foo.v&nbsp; </strong>
中的<span style="color: #ff6600;"><strong>foo已经指向</strong>
</span>
了 <strong>foo.prototype.foo</strong>
</p>
<p>当然<strong>o.foo.v</strong>
和<strong>foo.prototype.foo.v</strong>
是<span style="color: #ff6600;"><strong>同一个</strong>
</span>
对象了</p>
<p>&nbsp;</p>
<p>同样道理:由于</p>
<pre name="code" class="js">var o=new foo;</pre>
<p>o是foo的一个实例,是两个对象,那</p>
<pre name="code" class="js">o!=foo;
o!=foo.prototype;
o.v!=foo.prototype.v;//因为是值类型
o.foo===foo.prototype.foo;//非值型</pre>
<p>非值类型就引用到同一内存对象上了.</p>
<p>不过非值型的赋值也有意思,就是改变的是引用,而不是单纯的改变值.</p>
<pre name="code" class="js">var foo=function(){};
foo.prototype={v:'foo',foo:{v:{v:'foo'}}};
var o=new foo;
o.v={};
o.foo.v={v:'new'};
var o =new foo;
alert(o.foo.v.v);//原型都被改了</pre>
<p>&nbsp;这回原型又被改了.这样</p>
<pre name="code" class="js">var foo=function(){};
foo.prototype={v:'foo',foo:{v:{v:'foo'}}};
var o=new foo;
o.v={};
o.foo={v:'new'};
var o =new foo;
alert(o.foo.v.v);//没有被改</pre>
<p>一会儿改一会儿不改,到底问题在哪里,差别在哪里问题就在那里:</p>
<p>差别在:</p>
<pre name="code" class="js">o.foo={v:'new'};
o.foo.v={v:'new'};
</pre>
<p>注意o是独立的实例对象,o.foo是引用,和 foo.prototype.foo是同一个对象.直接对o.foo赋值当然改变的是引用,掐断了引用,引用到一个新的对象了,和原来的foo.prototype.foo不一样了,虽然</p>
<pre name="code" class="js">{v:'foo'}</pre>
<p>也是一个对象,不过要注意o.foo.v中的foo已经<span style="color: #ff6600;"><strong>明确范围</strong>
</span>
,这个范围就是同一个对象,当然原型也被改了.回头再看看前面的o,</p>
<p>哈哈,原来o是个新的实例,<span style="color: #ff6600;"><strong>范围不同</strong>
</span>
呀!同样适用这个确定范围的说法</p>
<p>说了这么多,其实就一句话,<span style="color: #ff6600;"><strong>引用的问题,先</strong>
</span>
<span style="color: #ff6600;"><strong>确定范围</strong>
</span>
<span style="color: #ff6600;">
</span>
吧,是不同的,还是相同的.</p>
<p>如果用标准的说法这是个Scope Chain的问题.抄一段规范的翻译文章:</p>
<div class="quote_title">http://www.cnblogs.com/winter-cn/archive/2008/07/07/1237168.html 写道</div>
<div class="quote_div">1. 获取Scope Chain的下一个对象。如果没有对象了，则转到第5步。<br />
2. 调用结果(1)的[[HasProperty]]方法, 传递Identifier作为参数<br />
3. 如果结果(2)是true, Reference(引用)类型的值，它的base object是结果(1)而它的<br />
property name是Identifier<br />
4. 跳到第1步<br />
5. 返回一个Reference类型，它的base object是null它的property name 是Identifier.<br />
注：Reference(引用)类型的值是JS引擎使用的一种数据类型，它分为base object和property name两个部分。假设在JS代码中有obj.prop这样的表达式，那么解释成Reference类型，base object是对象obj,而property name是字符串&rdquo;prop&rdquo;<br />
　Scope Chain开始时被设为宿主对象，所以在全局代码中的变量就是宿主对象的属性。Scope Chain在执行时由JS引擎自动维护，编译型的引擎也会创建相应的运行时环境来做此事。Scope Chain一般在函数调用或者执行进入with块的时候改变。</div>
&nbsp;
<p>说起来麻烦,用起来其实很简单.</p>
<p>&nbsp;</p>
<p><strong>还有一点是在JavaScript里继承这个词不是很准确,连祖先都随时可以被修改,这那是继承,明显是颠覆嘛!所以我觉得用Mixin</strong>
</p>
<p><strong>混入来说更合适,也无所谓,反正大家都知道在JavaScript里说的都是一回事.</strong></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214248#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 18:49:53 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214248</link>
        <guid>http://achun.javaeye.com/blog/214248</guid>
      </item>
      <item>
        <title>固有对象和非固有对象的成员,值类型赋值,非值型引用的差异</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214228" style="color:red;">http://achun.javaeye.com/blog/214228</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>n这是个麻烦的话题,文字很不好组织,不知道我是否能组织好语言</p>
<p>&nbsp;</p>
<p><span style="color: #ff6600;"><strong>固有对象</strong>
</span>
:</p>
<p><strong><span style="color: #ff6600;">未定义</span>
 </strong>
<strong><span style="color: #ff6600;">空值</span>
</strong>
 <strong><span style="color: #ff6600;">布尔值</span>
 </strong>
<strong><span style="color: #ff6600;">字符串</span>
 </strong>
<strong><span style="color: #ff6600;">数值 </span>
</strong>
<strong><span style="color: #ff6600;">通用对象 </span>
</strong>
<strong><span style="color: #ff6600;">数组 </span>
</strong>
<strong><span style="color: #ff6600;">函数</span>
</strong>
等都是(其他一些和我们的话题有些远,就不说了)</p>
<p>&nbsp;</p>
<p><strong><span style="color: #ff6600;">未定义</span>
 </strong>
<strong></strong>
和 <strong></strong>
<strong><span style="color: #ff6600;">空值</span>
</strong>
 <strong></strong>
的不同:</p>
<ol>
<li><strong><span style="color: #ff6600;">未定义</span>
 </strong>
<strong></strong>
是个值,是个关键字,表示一个对象没有值</li>
<li><strong></strong>
<strong><span style="color: #ff6600;">空值</span>
</strong>
 <strong></strong>
是个值,是个关键字,它的值就是 空 null,表示一个对象的值是null</li>
</ol>
<p>这个说法可能不够标准不过:</p>
<pre name="code" class="js">typeof undefined;//undefined
typeof null;//object</pre>
<p>JavaScript是面向对象的,所有的值都应该有一个类型,可是唯独undefined是个特殊的.undefined是关键字</p>
<p>null是值,也是对象,也是关键字.理由是:</p>
<pre name="code" class="js">Function=5;//可以这样
null=6;//不行,这就是为什么说null是关键字了,一个特殊的对象,undefined也有这个特性</pre>
<p>也就是说,Function,Array,Object都是一个函数对象,可以改变,undefined,null是关键字,不能改变.</p>
<p><span style="color: #ff6600;"><strong>非固有对象</strong>
</span>
:</p>
<p>由固有对象构造出的对象就是非固有对象.我们还是简称对象更容易描述些.对象都有值,也许值是null或者undefined.</p>
<pre name="code" class="js">var str='string';//等同
var str=new String('string');//等同
var str=String('string');</pre>
<p>这三句都做了同样的事情.可以这样描述:</p>
<ol>
<li>创建了一个对象,他的名字是:str</li>
<li>创建了一个字符串型的对象,他没有名字(<strong>匿名</strong>
),他的值是:string<br />
</li>
<li>令str指向这个<strong>匿名</strong>
对象:str 的类型和值也就同这个<strong>匿名</strong>
对象一样了</li>
</ol>
<p>当然JavaScript引擎是否优化这个实现,使得这个说法站不住脚,已经不重要了.概念是这样的.</p>
<p>&nbsp;</p>
<pre name="code" class="js">var obj={str:5,o:{v:'dfd'}};</pre>
<p>用同样的描述方法我们来说说:</p>
<ol>
<li>创建了一个对象,他的名字是:obj</li>
<li>创建了一个匿名对象
<pre name="code" class="js">{str:5,o:{v:'dfd'}}</pre>
</li>
<li>令obj指向这个<strong>匿名</strong>
对象:obj 的类型和值也就同这个<strong>匿名</strong>
对象一样了</li>
</ol>
<p>请使用FireFox+FireBUG来测试.console是FireBUG的调试API</p>
<pre name="code" class="js">var obj1={n:5,o:{v:'obj1v'}};
var obj2=obj1;
obj2=3;
console.dir(obj1);//obj1没有改变
obj2={};
console.dir(obj1);//obj1没有改变
obj2=obj1;
obj2.o={v:'obj2v'};
console.dir(obj1);//obj1改变了
</pre>
<p>第1次,obj1没有改变,是因为</p>
<pre name="code" class="js">obj2=3;</pre>
<p>重新创建了一个匿名对象3,改变了obj2的指向<strong></strong>
</p>
<p>第2次的情况和第1次一样.</p>
<p>第3次</p>
<ol>
<li>创建了一个匿名对象<br />
<pre name="code" class="js">{v:'obj2v'}</pre>
</li>
<li>令obj2.o指向这个匿名对象的值</li>
</ol>
<p><strong></strong>
</p>
<p>那为什么obj1.o也变了?让我们再看看</p>
<pre name="code" class="js">var obj2=obj1;
</pre>
<p>在JavaScript里由于obj1是一个<strong>非值型</strong>
对象这样的赋值是引用,对于<strong>引用</strong>
变量obj2,所有对obj2的<strong>成员操作</strong>
都会施加到obj1的成员上.</p>
<pre name="code" class="js">var obj3='string';
obj1=obj3;
</pre>
<p>向这样的操作,对于obj1来说不是成员操作,所有obj2不会改变.</p>
<p>再回头看看上面的描述,和<a href="../../../blog/214121" target="_blank">关于类型</a>
中的</p>
<p><span style="color: #ff6600;"><strong>无法对</strong>
<strong>值类型赋予新的可变成员</strong>
</span>
</p>
<p>是对应的,因为你<span style="color: #ff6600;"><strong>无法对</strong>
<strong>值类型赋予新的可变成员</strong>
</span>
,自然就不会有<strong>成员操作</strong>
(当然指的是新成员,这话还不够严谨,prototype过来的算不算),因此说:(注意前提,不讲prototype的情况)</p>
<p>不存在值类型成员操作,只存在非值型成员操作,<strong>成员操作具有传染性</strong></p>
<pre name="code" class="js">var o1={v:'dfd'};
var obj={str:5,o:o1};//obj.o引用o1
var o2=obj;//o2引用obj,
o2.o={};//成员操作
console.dir(obj);//传染了,obj.o改变
console.dir(o1);//o1不是obj的成员,不变
var obj1={str:5,o:o1};//obj1.o引用o1
var o3=obj1;
o2.o.v='aaa';//v可就是实实在在的{v:'dfd'}中的v呀
console.dir(o1);//o1变了
</pre>
<p>&nbsp;o1不是obj的成员?当然,o1和obj.o只不过都指向{v:'dfd'}罢了.再举个例子</p>
<pre name="code" class="js">var o={};
o.f=function(){return 1;};
var oo=o;
oo.f=function(){return 2;};//仍然是成员操作,传染
o.f();//2</pre>
&nbsp;
<p>&nbsp;</p>
<p><span style="color: #ff0000;"><strong>其实如果你学习过c/c++了解指针操作的话,我这个解释根本是多余的</strong>
</span>
</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214228#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 16:52:36 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214228</link>
        <guid>http://achun.javaeye.com/blog/214228</guid>
      </item>
      <item>
        <title>关于类型</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/214121" style="color:red;">http://achun.javaeye.com/blog/214121</a>&nbsp;
          发表时间: 2008年07月12日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>ecma-262规范对JavaScript的类型描述:</p>
<ol>
<li><strong><span style="color: #ff6600;">未定义</span>
</strong>
 一个顶级属性，保存了未定义的值;仅有一个值<code>undefined</code>
(关键字)
也是一个原始值</li>
<li><strong><span style="color: #ff6600;">空值</span>
</strong>
 一个特殊的关键字，代表空值;仅有一个值<code>null</code>
也是一个原始值</li>
<li><strong><span style="color: #ff6600;">布尔值</span>
</strong>
 有两个值，称为 <strong>true</strong>
 和 <strong>false<br />
</strong>
</li>
<li><strong><span style="color: #ff6600;">字符串</span>
</strong>
 字符串类型是所有有限的零个或多个16位无符号整数值（&ldquo;元素&rdquo;）的有序序列.空字符串长度为零.用非负数值索引这些位置.第一个元素在位置0，下一个元素在位置1，依此类推。</li>
<li><strong><span style="color: #ff6600;">数值</span>
</strong>
 数值类型采用的是IEEE-754 的64位双精度数值格式,其中特殊的值<br />
<strong>NaN</strong>
:表示算术表达式返回非数字值的特殊值,<strong>NaN</strong>
 不与任何值相等，包括其本身.<br />
<strong><tt>+Infinity</tt>
</strong>
:正无穷<br />
<strong><tt>-Infinity</tt>
</strong>
:负无穷<br />
<strong>+0</strong>
:正零,这是由于双精度数值格式造成的<br />
<strong>-0</strong>
:负零,这是由于双精度数值格式造成的</li>
<li><strong><span style="color: #ff6600;">对象</span>
</strong>
 对象是未排序是属性容器。每个属性由名字、值和一个<strong>特征</strong>
的集合组成.</li>
<li><strong><span style="color: #ff6600;">引用</span>
</strong>
 <span><strong>内部</strong>
引用类型不是语言的数据类型.</span>
<span>引用</span>
的值仅被用于表达式求值的中间值，且不能被对象的属性存储<br />
<span>引用</span>
是到对象的属性的引用,<br />
</li>
<li><strong><span style="color: #ff6600;">列表</span>
</strong>
 <span><strong>内部</strong>
列表类型不是语言的数据类型.</span>
<span>列表</span>
的值仅被用于表达式求值的中间值，且不能被对象的属性存储<br />
列表类型被用于解释参数列表的求值,列表类的值是简单的已排序值的序列</li>
<li><strong><span style="color: #ff6600;">完结</span>
</strong>
 <span><strong>内部</strong>
完结类型不是语言的数据类型.</span>
<span>完结</span>
的值仅被用于表达式求值的中间值，且不能被对象的属性存储<br />
完结类型被用于解释非本地控制调度的语句的行为</li>
</ol>
<p>用mozilla.org网站对JavaScript类型的描述,看上去会更容易理解些.</p>
<p><strong>值类型:</strong>
包括<strong><span style="color: #ff6600;">未定义</span>
</strong>
 <strong><span style="color: #ff6600;">空值</span>
</strong>
 <strong><span style="color: #ff6600;">布尔值</span>
</strong>
 <strong><span style="color: #ff6600;">字符串</span>
</strong>
 <strong><span style="color: #ff6600;">数值</span>
</strong>
</p>
<p><strong>非值型:</strong>
 当然除了值类型就都是非值类型了,不过对于ecma-262规范的定义方法,6-9的定义看上去有些陌生,让我们用不陌生的方式来做个明确的<strong>非值型列表:</strong>
</p>
<ol>
<li><strong><span style="color: #ff6600;">通用对象</span>
</strong>
 Object<br />
</li>
<li><strong><span style="color: #ff6600;">数组 </span>
</strong>
Array</li>
<li><strong><span style="color: #ff6600;">函数 </span>
</strong>
Function</li>
<li><strong><span style="color: #ff6600;">日期和时间 </span>
</strong>
Date</li>
<li><strong><span style="color: #ff6600;">数学库 </span>
</strong>
Math<br />
</li>
<li><strong><span style="color: #ff6600;">正则表达式 </span>
</strong>
RegExp</li>
</ol>
<p>如果对应ecma-262规范的定义方法,这些都属于,对象(6,Object这个词被用了两次,会不会造成认识上的混乱呀),而我们要明白 <strong><span style="color: #ff6600;">Date,Math,RegExp </span>
</strong>
<span style="color: #ff6600;"><span style="color: #000000;">更像是<strong><span style="color: #ff6600;">库</span>
</strong>
<span style="color: #000000;">,也就是说是让我们直接使用的</span>
</span>
<strong>库</strong>
</span>
<span style="color: #ff6600;"><strong><span style="color: #ff6600;">对象</span>
</strong>
<span style="color: #000000;">,</span>
</span>
</p>
<p><strong>值类型</strong>
和<strong>非值型</strong>
的典型区别就是:</p>
<ol>
<li><strong><span style="color: #ff6600;">定义一个变量</span>
</strong>
,它的右侧(值)是一个<br />
<strong>值类型</strong>
 那么你将得到一份<strong>拷贝</strong>
,JavaScript 引擎为变量分配了一个新的内存空间,并且复制右侧的值.<strong><br />
非值型</strong>
 那么你将得到一份<strong>引用</strong>
,JavaScript 引擎为变量分配了一个引用,指向右侧的值.<strong><br />
非值型都是引用</strong>
要明白变量赋值后,就变成<strong>对象</strong>
了.那么下面的描述就要针对<strong>对象</strong>
了,<br />
<span style="color: #000000;"><strong>也就是说所谓的<span style="color: #ff6600;">定义变量</span>
就是<span style="color: #ff6600;">定义对象</span>
然后指向这个对象.<br />
</strong>
</span>
至于<strong>值类型</strong>
 JavaScript 内部实现是否是&quot;引用&quot;,我们已经不关心了.在我们使用的立场上不是引用.
</li>
<li><strong><span style="color: #ff6600;">改变一个对象</span>
</strong>
,如果这个对象是一个<strong><br />
值类型</strong>
 那么这个对象的值会被改变,其他的对象值不受影响<strong><br />
非值型</strong>
 那么这个对象的值会被改变,其他的对象值不受影响</li>
<li><span style="color: #ff6600;"><strong>无法对</strong>
<strong>值类型赋予新的可变</strong>
</span>

<strong><span style="color: #ff6600;">对象(成员)</span>
</strong>
<span style="color: #ff6600;">
<span style="color: #000000;">例如</span>
<span style="color: #000000;">:注意我说的是可变<br />
</span>
</span>
<pre name="code" class="js">var str='string';
str.foo='new string';//这一句是不能生效的</pre>
&nbsp;<span style="color: #ff6600;"><span style="color: #000000;">就算这样也不行:<br />
</span>
</span>
<pre name="code" class="js">String.prototype.foo='newstring';
var str='string';
alert(str.foo);//提示newstring
str.foo='foo';
alert(str.foo);//仍然提示newstring,IE,FireFox测试过

String.prototype.foo=function(){return 'newstring';};
var str='string';
alert(str.foo());//提示newstring
str.foo=function(){return 'newfoo';};
alert(str.foo());//仍然提示newstring,IE,FireFox测试过
</pre>
&nbsp;
<br />
</li>
<li><strong><span style="color: #ff6600;">改变一个对象的</span>
</strong>
<strong><span style="color: #ff6600;">对象(成员)</span>
</strong>
<strong>
</strong>
,如果这个对象是一个:<br />
<strong>值类型</strong>
 不生效,原因见前面的第3点<strong><br />
非值型</strong>
 那么所有和这个对象同样引用的对象的此成员值会被改变(<strong>这一句有问题,不适用于固有对象,我想找到一个正确的一句话描述</strong>
)<br />
<pre name="code" class="js">var o1={m1:3,m2:{m22:4}};
var o2=o1;
o2.m1=4;
o2.m2=4;
alert(o1.m1);//4
alert(o1.m2);//4
var o1={m1:3,m2:{m22:4}};
var o2=o1;
o1.m1=4;
o1.m2=4;
alert(o2.m1);//4
alert(o2.m2);//4</pre>
&nbsp;
<br />
</li>
</ol>
<p><strong><span style="color: #ff6600;">function</span>
</strong>
:一等公民(first-class),注意<strong>function</strong>
!=<strong>Function</strong>
</p>
<p>这些概念描述起来就是那么的绕嘴,前面已经说了<strong>Function</strong>
是一种类型,那<strong>function</strong>
呢?<strong>function</strong>
是个关键字,可以定义<strong>Function</strong>
这种类型的对象,<strong>Function</strong>
是类型当然不能定义一个对象了.</p>
<pre name="code" class="js">function func(){}//创建一个Function类型的对象func
Function func(){}//当然错误了
func=new Function;//创建一个对象func,它的是由Function构造的</pre>
<p>由Function构造?对:</p>
<pre name="code" class="js">alert(typeof Function);//function</pre>
<p>Function是一个JavaScript内建函数,这个函数可以<strong>构造函数类型的对象</strong>
,</p>
<p>这里的词汇 Function 有多个含义(其实没有必要这么抠概念)</p>
<ol>
<li>在我们描述一个对象时用于说明此对象的类型是函数</li>
<li>是一个JavaScript内建对象,它可以构造函数类型的对象,它的类型是函数</li>
</ol>
<p>大家不都是说new关键字是来构造一个新的对象的么?前面不是有个new么?</p>
<pre name="code" class="js">//不用new也可以
var func=Function();
var func=Function('return 1;');
alert(func());//1</pre>
<p>&nbsp;原来<span style="color: #ff6600;"><strong>只有函数能构建对象</strong>
<span style="color: #000000;">,当然</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;">为了书写的方便</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;">JavaScript也提供了其他的便捷定义方式</span>
</span>
</p>
<pre name="code" class="js">var obj={};//便捷方式
var obj=Object();
var obj={foo:3};//便捷方式
var obj=Object({foo:3});
</pre>
<p>&nbsp;同理,Array,Date,RegExp,都是JavaScript内建函数,Math不是函数,是一组数学函数的对象集合</p>
<dl><dd>
</dd>
</dl>
<dl><dd>
</dd>
</dl>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/214121#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 12 Jul 2008 11:16:21 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/214121</link>
        <guid>http://achun.javaeye.com/blog/214121</guid>
      </item>
      <item>
        <title>jCT 第三版简要文档</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/213858" style="color:red;">http://achun.javaeye.com/blog/213858</a>&nbsp;
          发表时间: 2008年07月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-size: medium;"><strong>JavaScript Common Templates 第三版简要文档</strong>
<br />
</span>
<br />
<strong>文档文法描述</strong>
:<br />
<br />
  对于要描述的对象使用如下文法<br />
<strong>name:type||example description<br />
</strong>
<br />
<strong>调用</strong>
:创建一个jCT的实例,此实例具有自己解析/执行模板的能力</p>
<pre name="code" class="js">var jct = new jCT(txt,path);</pre>
<p>
<strong>参数</strong>
:<br />
<br />
    txt:&quot;&quot;         模板原文本对应属性Fn.Src<br />
<br />
    path:&quot;&quot;        模板文件的url所在路径(不是url)对应属性Fn.Path<br />
<br />
<strong>建立</strong>
:解析模板使模板代码化</p>
<pre name="code" class="js">jct.Build([如果直接执行,传入执行的数据对象])</pre>
<p>
<strong>例子</strong>
:</p>
<pre name="code" class="js">jct.Build(obj) </pre>
<p>
<br />
    同效果</p>
<pre name="code" class="js">jct.Build().Exec(obj);</pre>
<p>注意:如果带参数的话,是否执行Exec会受ReBuild扩展影响,参见ReBuild扩展</p>
<p>
<strong>执行</strong>
:执行模板,默认返回模板执行后的文本数据,可以通过 Exec 扩展语法制定</p>
<pre name="code" class="js">jct.Exec([执行的数据对象])</pre>
<p>
<strong>默认参数</strong>
:<br />
<br />
    D              如果没有制定Exec扩展语法的话,此参数是 Exec 的默认参数,表示传入的数据<br />
<br />
<strong>保留字串</strong>
:<br />
<br />
  ...              再使用Exec扩展语法时用于替换主体过程的占位符<br />
<br />
<strong>jCT的实例保留方法和属性</strong>
:</p>
<pre name="code" class="js">  Fn={             用于保留jCT实例创建,执行时的数据,有些是为了方便调试
    A:[]           SRC的模板数组形式表示
    D:{}           用于保留执行(Exec)模板时候传入的参数
    V:[]           在执行(Exec)模板过程当中生成结果的数组形式
    EXEC:[]        Build模板的时候生成的主体过程数组形式
    RUN:()         由 Run 扩展语法获得的只运行一次函数
    ERROR:{}       Build异常时的错误信息.
    Path:&quot;&quot;        保留模板的URL路径,由调用模板的函数提供，目的是考虑到这个可能会有很多的用途。
    Src:&quot;&quot;         模板原文本,由调用模板的函数提供
    src:&quot;&quot;         经过清理后的模板文本
    Tag:{          当前选定的模板标签风格,是一个指向Tags内某个风格的引用,结构如下
      block:{      jCT模板块标记设定
        begin:&quot;&quot;   标记的开始字符串
        end:&quot;&quot;     标记的结束字符串
      }
      exp:{}       jCT模板取值表达式设定
      ext:{}       jCT模板扩展语法标记设定,参见见扩展语法一节
      clean:{}     jCT模板清理标记设定
    }
    Tags:{         所有支持的模板标签风格,内置三种风
      comment:{    //注释标签风格
        block:{begin:''},
        exp:{begin:'+-',end:'-+'},
        ext:{begin:'/*+',end:'*/'},
        clean:{begin:'',end:''}
      },
      script:{     //脚本标签风格
        block:{begin:'',end:''},
        exp:{begin:'+-',end:'-+'},
        ext:{begin:'/*+',end:'*/'},
        clean:{begin:'',end:''}
      },
      code:{       //code标签风格
        block:{begin:'',end:''},
        exp:{begin:'+-',end:'-+'},
        ext:{begin:'/*+',end:'*/'},
        clean:{begin:'',end:''}
      }
    }
    Clean:()       清理模板,参数对应属性的TAG
    Parse:()       模板的解析
    Slice:()         模板分段函数
  }
  Exec:()          执行模板,参见Exec扩展
  Build:()          构建模板方法
  ReBuild:()     在Build期间执行,参见ReBuild扩展
  GetView:()    便捷的获取 return this.Fn.V.join(&quot;&quot;);

</pre>
<p><strong>扩展语法</strong>
:jCT模板使用的是原生的 JavaScript 语法,为了达到模板的高度可制定性设计了扩展语法</p>
<p>&nbsp;</p>
<pre name="code" class="js">  Exec:            自定义的构建 Exec 方法的主体内容
    &lt;script type=&quot;jct&quot;&gt;/*+Exec*/
      var D=arguments[0]||{};
      ...
      $('#mainbody').html(this.GetView());
    &lt;/script&gt;
    &lt;script type=&quot;jct&quot;&gt;/*+Exec*/
      var D=arguments[0]||{};
      with(D){...}
      $('#mainbody').html(this.GetView());
    &lt;/script&gt;
  ReBuild:      当执行Build时发生,如果定义了ReBuild并且有任何值返回,Build都会忽视传入的参数
    下面的例子没有返回值,那么会执行foo(),如果使用jct.Build(obj),那么jct.Exec(obj)会被执行
    &lt;script type=&quot;jct&quot;&gt;/*+ReBuild*/
      foo();
    &lt;/script&gt;
    下面的例子有返回值,那么会执行foo(),如果使用jct.Build(obj),那么jct.Exec(obj)不会被执行
    &lt;script type=&quot;jct&quot;&gt;/*+ReBuild*/
      foo();
      return true;
    &lt;/script&gt;

  Run:            扩展语法获得的只运行一次
    &lt;script type=&quot;jct&quot;&gt;/*+Run*/
      foo();
    &lt;/script&gt;
  Child:           定义一个子jCT实例
    &lt;script type=&quot;jct&quot;&gt;/*+Child childname*/&lt;/script&gt;
      Templates Source Code
    &lt;script type=&quot;jct&quot;&gt;/*-Child childname*/&lt;/script&gt;
  ...:             保留字串也可以算作扩展语法,只能出现在 Exec扩展语法中
</pre>
<p>&nbsp;</p>
<p>(因为贴在代码里格式较整齐,所以就利用了一下)</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/213858#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 11 Jul 2008 11:47:44 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/213858</link>
        <guid>http://achun.javaeye.com/blog/213858</guid>
      </item>
      <item>
        <title>Action By Class,利用Element 的class触发行为</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/212054" style="color:red;">http://achun.javaeye.com/blog/212054</a>&nbsp;
          发表时间: 2008年07月06日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>做Web应用，页面上的元素(Element)，常常要进行一些特殊的处理，</p>
<p>比如增加特效，处理innerHTML等等。</p>
<p>举个例子：</p>
<p>jQuery有一个插件<a href="http://nixbox.com/lavalamp.php" target="_blank">lavaLamp</a>
,可以做出漂亮的菜单。</p>
<p>使用的时候，除了写好css,设置好style,就是调用：</p>
<pre name="code" class="js">$(elm).lavaLamp(options);
/*elm是对应的元素，具体写法可以用#ID等jQuery选择器，options就是参数了参加lavaLamp的说明*/</pre>
<p>&nbsp;对于这个需求，这个用法是无可非议的。</p>
<p>但是向这样要先筛选元素然后再进行不同除了的需求，在某些应用中可能有大量的需求。</p>
<p>如果一个个的写选择器，为元素设置特殊的ID或属性是很麻烦的。</p>
<p>我这里有一个简单的方法来处理这个问题（此方法我已经用了2年了，非常安逸），就是通过设置源文件相关元素(html 标签)的class属性来解决此类问题。类似上面的需求html代码如下:</p>
<pre name="code" class="html">&lt;ul class=&quot;lavaLampBottomStyle abc abc.lavaLamp({fx:'easeOutBack',speed:700})&quot;&gt;
	&lt;li&gt;&lt;a&gt;测试&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a&gt;测试&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</pre>
<p>&nbsp;这是lavaLamp的最简单形式，lavaLampBottomStyle用来设置菜单的样式。</p>
<pre name="code" class="html">abc abc.lavaLamp({fx:'easeOutBack',speed:700})</pre>
<p>&nbsp;</p>
<p>就是用了触发生效lavaLamp效果的设置。</p>
<p>可能你已经明白了，里面的abc是用来声明一个特殊的标记。表示这个class中有Action By Class的方法。而abc.lavaLamp({fx:'easeOutBack',speed:700})就是激活lavaLamp的语法。</p>
<p>这个语法要生效我写了个jQuery扩展Action By Class------abc：</p>
<pre name="code" class="js">$.extend($.fn, {
	abc: function(prefix) {
		prefix=(prefix ||'abc')+'.';
		//for (var i=this.length - 1;i&gt;=0;i--) {//这个有讲究，后面再说，次序问题
		for (var i=0 ;i&lt;this.length;i++) {
			var cna = this[i ].className.split(/\s+/);
			var self=this[i];//预留eval做接口
			var selfjQ = $(this[i]);//预留eval做接口的jQuery对象
			for (var j=0; j&lt;cna.length; j++) {
				if (prefix!=cna[j].slice(0,prefix.length) || cna[j].indexOf('(')&lt;1 || cna[j].slice(cna[j].length-1)!=')') continue;
				var fn=cna[j].slice(0,cna[j].indexOf('('));
				var option=cna[j].slice(fn.length+1,cna[j].length-1);
				option=option.replace(/&amp;/g,' ')||undefined;
				fn = fn+'(this[i],'+option+')';
				//selfjQ.removeClass(cna[j]);
				//try {
					//alert(('$.'+fn));
					window.eval(('$.'+fn));
				//catch (ex){alert('abc error:'+fn)};
			}
		}
		this.removeClass(prefix.slice(0,-1));
	}
});
$.abc = {};
$.extend($.abc, {
	lavaLamp:function(elm,options){
		$(elm).lavaLamp(options);
	}
);</pre>
<p>注意：代码是直接从我的扩展中帖出来的，有写东西是为了调试用的，有些东西是我试验用的。读者只需要明白原理，可以自己写一个。</p>
<p>这个扩展很简单就是：</p>
<pre name="code" class="js">$('.abc').abc()</pre>
<p>对应abc的代码你可以看到，$('.abc')或的了具有abc class的Elements。abc分析class name 中以&ldquo;abc.&rdquo;(当然也可以用prefix定义其他的，用来区分次序)打头的class,其实也就是Action命令了。调用相关的$.abc.xxxx</p>
<p>通过这个方法，无需费心定义大量不同的ID了（这个很烦的），调用也一句就触发了。</p>
<p>&nbsp;</p>
<p>思考：</p>
<p>1.其实经过2年的使用我觉得实际当中这个方法可以优化的，不过用的是契约式编程，不一定能被大家普遍接受，就不提了。</p>
<p>2.关于前面说的问题，其实是在复杂的应用当中action触发的次序是有要求的，开始的时候我是用递增或递减循环来解决的，后来就改用设置prefix来触发了，比如:</p>
<p>&nbsp;</p>
<pre name="code" class="js">abc abc.lavaLamp({fx:'easeOutBack',speed:700});//如果和其他的abc配合有次序的要求的话，可以写
abc2 abc2.lavaLamp({fx:'easeOutBack',speed:700});
</pre>
<p>调用次序写两个就行了:</p>
<pre name="code" class="js">$('.abc').abc();
$('.abc2').abc('abc2');
</pre>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/212054#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 06 Jul 2008 15:49:10 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/212054</link>
        <guid>http://achun.javaeye.com/blog/212054</guid>
      </item>
      <item>
        <title>测试,探讨jMixin模式</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/211907" style="color:red;">http://achun.javaeye.com/blog/211907</a>&nbsp;
          发表时间: 2008年07月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>首先,我自己都不知道自己想要什么结果,测试了之后才知道有没有价值.</p>
<pre name="code" class="js">var jMixin = function(){
	if (arguments.length&gt;2) return;
	var ths=this;
	var callee=arguments.callee;
	var caller=arguments.callee.caller;
	if (arguments.length==0) {
		ths.jMixin=callee;
		return;
	}
	if (arguments.length==1){
		var args=arguments[0];
		if (caller!==null) ths = caller;
	}else{
		ths=arguments[0];
		var args=arguments[1];
	}
	if (ths==window || ths==undefined) ths={};
	if (arguments.length==1 &amp;&amp; caller==null)
		ths.jMixin=callee;
	for(var prop in args) ths[prop]=args[prop];
	return ths;
}
var o=jMixin();
jMixin(o,{c:2});
var oo=jMixin({o:1});
jMixin(oo,{c:2});
var o2=jMixin(o);
var foo={};
jMixin(foo,{c:2});

var foonewnone=new jMixin();
var foonew=new jMixin(o);
var foonew2=new foonew.jMixin({c:5});</pre>
&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/211907#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 05 Jul 2008 18:49:55 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/211907</link>
        <guid>http://achun.javaeye.com/blog/211907</guid>
      </item>
      <item>
        <title>都变了样!我这样用jCT模板.</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/210621" style="color:red;">http://achun.javaeye.com/blog/210621</a>&nbsp;
          发表时间: 2008年07月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>在写这篇文章的时候我相信很多朋友都不明白我在说什么,会奇怪我这样的思路,问题就在这里,我的这种思路很难被认同.但是这种思路开发起来真的很快.请耐心看完所有的文章.</strong>
</p>
<p>&nbsp;</p>
<p>jCT发展到目前的第三版.除了jCT本身的变化外.我在使用的时候整个设计思路也都改变了.</p>
<p>对于模板技术来说,绝大多数是平面化,顺序化.也就是说</p>
<p>1.模板的结构和页面表现的结构一致--------------------<strong><span style="color: #ff6600;">平面化</span>
</strong>
</p>
<p>2.模板成为视图的时候数据的装配是顺序进行的--------<strong><span style="color: #ff6600;">顺序化</span>
</strong>
(这个说法看了我下面的实现就会明白)</p>
<p>&nbsp;</p>
<p>下面是我准备重新写的nicEditor打包工具模板部分.(注意&lt;!---xxx--&gt;是jCT的模板语法,&lt;!--xx--&gt;是我写的注释)</p>
<pre name="code" class="html">&lt;!--1:下面一段用来确定页面的布局--&gt;
&lt;div id=&quot;&quot; class=&quot;&quot;&gt;&lt;center class=&quot;fsh2 cwhite&quot;&gt;选择 NicEdit 模块&lt;/center&gt;&lt;/div&gt;
&lt;div id=&quot;&quot; class=&quot;&quot;&gt;
	&lt;span&gt;合并GIF图标文件:&lt;/span&gt;
	&lt;input type='text' name=&quot;iconsfile&quot; value=&quot;nicEditIcons.gif&quot;/&gt;
&lt;/div&gt;
&lt;div id=&quot;navmenu&quot; class=&quot;&quot; /&gt;
&lt;div id=&quot;nelist&quot; class=&quot;&quot;&gt;nE List&lt;/div&gt;
&lt;!--这里用jCT重构语法,确定了执行的过程--&gt;
&lt;!---
	/*+Main*/
function(D){
	...//这一句将被jCT生成的实例主体过程替换
	$('#mainbody').html(this.CTV.join(&quot;&quot;));//把结果也就是上面的布局写入到#mainbody Element
	$('#mainbody .abc').abc();//这是我写的一个jQuery插件 Action By Class name,可以忽视它
	this.navmenu('#navmenu');//调用导航菜单
	this.nelist();//调用从服务器取得的nicEditor的模块列表
}
--&gt;
&lt;!--1:布局结束--&gt;
&lt;!--jCT的Run语法,Run里的代码只运行一次.这里的例子相当于动态的定义了一个函数--&gt;
&lt;!---/*+Run*/
$.extend(App,{
test:function(){
	alert($('img').attr('value'));
	return false;
}
});
--&gt;
&lt;!--2:导航菜单部分, abc abc.lavaLamp(...) 是jQuery插件 Action By Class name 的执行方法--&gt;
&lt;!---/*+Child navmenu*/--&gt;
&lt;ul class=&quot;lavaLampBottomStyle bgc4 cwhite fwbold fsh4 abc abc.lavaLamp({fx:'easeOutBack',speed:700})&quot;&gt;
	&lt;li class=&quot;inline&quot;&gt;&lt;a onclick=&quot;return App.test();&quot;&gt;测试&lt;/a&gt;&lt;/li&gt;
	&lt;li class=&quot;inline&quot;&gt;&lt;a onclick=&quot;return App.test();&quot;&gt;下载&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!--道理同前面的重构--&gt;
&lt;!---/*+Main*/
function(){
	...
	var el=arguments[0];
	if (!el) return this.CTV.join(&quot;&quot;);
	$(el).html(this.CTV.join(&quot;&quot;)).find('.abc').abc();
}
--&gt;
&lt;!---/*-Child navmenu*/--&gt;
&lt;!--2:导航菜单部分结束--&gt;

&lt;!--3:nicEditor的模块列表--&gt;
&lt;!---/*+Child nelist*/--&gt;
&lt;table class=&quot;dlTable&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot;&gt;
	&lt;tbody&gt;
		&lt;!---for(var I=0;I&lt;nelist.length;I++){--&gt;
		&lt;tr class=&quot;core&quot;&gt;
			&lt;td&gt;
				&lt;img style=&quot;width:30px;height:30px;&quot; class=&quot;checkbox&quot; src=&quot;+-App.pixelGif-+&quot; name=&quot;plugins[]&quot; value=&quot;+-nelist[I]-+&quot; /&gt;
				&lt;input name=&quot;plugins[]&quot; value=&quot;+-nelist[I]-+&quot; type='checkbox' class=&quot;none&quot; /&gt;
			&lt;/td&gt;
			&lt;td class=&quot;pluginName&quot;&gt;+-nelist[I]-+&lt;/td&gt;
		&lt;/tr&gt;
		&lt;!---}--&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;!--道理同前面的重构,不过里面用到了一个thisCallback,后面叙述--&gt;
&lt;!---/*+Main*/
function(D){
	if(arguments.callee.caller!=thisCallback)
		return jsonQueue({nelist:0},this);
	with(D){...}
	$('#nelist').html(this.CTV.join(&quot;&quot;));
	$('#nelist table img').each(function(){
		$(this).click(function(){
			var ck=!$(this).next('input').attr('checked');
			if (ck){
				$(this).next('input').attr('checked','checked');
				$(this).addClass('checkboxon');
			}else{
				$(this).next('input').removeAttr('checked');
				$(this).removeClass('checkboxon');
			}
		}).click();
	});
}
--&gt;
&lt;!---/*-Child nelist*/--&gt;
&lt;!--3:nicEditor的模块列表结束--&gt;

</pre>
<p>&nbsp;</p>
<p>可以看到,传统的<strong><span style="color: #ff6600;">平面化</span>
</strong>
在我这个例子了已经不复存在了.jCT重构语法为自由布局提供了可能.</p>
<p><strong><span style="color: #ff6600;">顺序化</span>
</strong>
 被 <strong><span style="color: #ff6600;">thisCallback</span>
</strong>
 (这个名词我还是不满意)彻底打破.</p>
<p>&nbsp;</p>
<p>关于 thisCallback 到底是什么东西请看:</p>
<p><a href="../../blog/209575" target="_blank">http://achun.javaeye.com/blog/209575</a>
</p>
<p><a href="../../blog/210023" target="_blank">http://achun.javaeye.com/blog/210023</a>
</p>
<p><span>jsonQueue就是这种想法的一个实例:</span>
</p>
<pre name="code" class="js">//回调函数,保持原来的this指针
function thisCallback(func,thiss,args){
	func.apply(thiss,args);
}
//jsonQuene合并细粒度队列回调
function jsonQueue(queue,thiss,ask){
	if (ask){
		var ask='确定执行这个操作么?'+(options.ask===true?'':options.ask);
		if(false==confirm(ask)) return false;
	}
	var func=arguments.callee.caller;

	var data=JSON.stringify(queue);
	(function (func,data){
	jQuery.ajax({
		url: R('/'),
		dataType:'json',
		data:data,
		type:'POST',
		error:function(xml){
			alert('Error : actionQuene');
		},
		success:function(a){
			thisCallback(func,thiss,[a]);
		}
	});
	})(func,data);
	return false;
}</pre>
<p>其他信息参见 </p>
<h3><a href="../../../blog/200417" target="_blank">降低前后台业务逻辑上的耦合度,前后台细粒度数据通讯的方法</a>
</h3>
<p>当然我这种用法有些极端(不必要),但怎么说呢.对于这个例子完全可以把3部分写到一起.不过我喜欢的开发形式.jCT和thisCallback为这种提供了可能.</p>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/210621#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 02 Jul 2008 14:58:42 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/210621</link>
        <guid>http://achun.javaeye.com/blog/210621</guid>
      </item>
      <item>
        <title>善用arguments.callee.apply,让递归兼容Mixin,正确继承this</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/210023" style="color:red;">http://achun.javaeye.com/blog/210023</a>&nbsp;
          发表时间: 2008年07月01日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>javascript 中递归的使用也是常见的.比如遍历DOM树.</p>
<p>在我们熟悉的js框架(jQuery,prototype等)中都有递归的身影.</p>
<p>Minin在很多语言里都有实现,对于动态的javascript实现更是简单,只不过是成员赋值就行了.</p>
<p>那么这两者有什么联系?兼容又从何而来?</p>
<p>代码说话:</p>
<pre name="code" class="js">function foo1(c){
  alert(c+a +':'+(this.constructor));//这里的信息足以说明不同了
  a++;
  if (a&gt;1) return;//跳出递归
  foo1(c);//直接递归
}
function foo2(c){
  alert(c+a +':'+(this.constructor));//这里的信息足以说明不同了
  a++;
  if (a&gt;1) return;//跳出递归
  arguments.callee.apply(this,arguments);//兼容Mixin的递归
}

var a=0;//为了跳出递归设置的变量
foo1('foo1:');
var a=0;
foo2('foo2:');
var f={};
f.ff=foo1;//这就是javascript最简单形式的Mixin了
var a=0;
f.ff('foo1Mixin:');
f.ff=foo2;
var a=0;
f.ff('foo2Mixin:');
</pre>
<p>&nbsp;</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/210023#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 01 Jul 2008 09:42:47 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/210023</link>
        <guid>http://achun.javaeye.com/blog/210023</guid>
      </item>
      <item>
        <title>[原创]伪同步调用ajax(伪阻塞)</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/209575" style="color:red;">http://achun.javaeye.com/blog/209575</a>&nbsp;
          发表时间: 2008年06月30日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="color: #ff0000;"><strong></strong>
</span>
</p>
<p>如果在一个函数中，我们需要的数据是要从ajax获取。如果用<span style="color: #ff6600;">ajax同步</span>
的方法，浏览器会挂起，这是一个很讨厌的事情。</p>
<p>而<span style="color: #ff6600;">ajax异步</span>
在浏览器中的实现是立即返回的，而我们要的数据还没有被获取。</p>
<p>&nbsp;</p>
<p>那用<span style="color: #ff6600;">ajax异步</span>
的方法怎么做才能达到我们的目的呢？让我们一步步实现伪同步.</p>
<p>先给个简单的方法:</p>
<pre name="code" class="js">function foo(data){
  if(undefined==data)
    return ajaxQueue({...},{callback:arguments.callee});
  ......someting......
}</pre>
<p>也就是说:</p>
<p>函数foo内部有ajax异步(ajaxQueue就是入口)的请求,而且ajax后的结果对foo的内部(someting)执行有影响,因此需要在foo内部进行判断<strong><span style="color: #ff9900;">是否ajax异步请求已经完成</span>
</strong>
,或者说<strong><span style="color: #ff9900;">调用者是否是ajax异步请求</span>
</strong>
.</p>
<p>上面代码中用了一个简单的判断</p>
<pre name="code" class="js">if(undefined==data)</pre>
<p>而</p>
<pre name="code" class="js">{callback:arguments.callee}</pre>
<p>&nbsp;</p>
<p>就是告诉ajaxQueue取到数据后，再回调foo了.</p>
<p>不过这个方法有问题，也就是借用了foo 函数的参数值，在某些场合也许就不适用了。因此这个方法是有问题的，ajaxQueue的实现也就失去了讨论的意义。</p>
<p>&nbsp;</p>
<p>首先让我们完善上面的方法:<strong><span style="color: #993300;">注意闭包的用法<span style="color: #888888;">(也不知道会不会造成内存泄漏)</span>
</span>
</strong>
</p>
<pre name="code" class="js">function ajaxCallback(queue,args){
	var func=arguments.callee.caller;
	var length=queue.length;
	for (var i=0;i&lt;queue.length;i++)
		(function(){
		var o=queue[i];
		var _old = o.complete;
		o.complete = function(){
			if ( _old ) _old.apply( this, arguments );
			length--;
			if (0==length) {
				func.apply(ajaxCallback,args);
			}
		};
		jQuery.ajax(o);
		})();
}</pre>
<p>&nbsp;调用:</p>
<pre name="code" class="js">function foo(ddd){
 if(this!==ajaxCallback){
   return ajaxCallback([
    {url:'/1.txt',complete:function(){alert(1);}},
    {url:'/1.txt',complete:function(){alert(2);}}],
    arguments);
 }
 alert(arguments.length);
 alert(ddd)
}
foo(3);</pre>
<p>&nbsp;</p>
<p>这里面还有一个问题,就是虽然没有借用参数，但是借用了this（我是不是绕的弯弯太多了，直奔正解不就行了，其实这是我解决这个时候的思路，自己记录一下）.对OO的编程可就有产生了新的麻烦。</p>
<p>改一下:</p>
<pre name="code" class="js">function ajaxCallback(queue,args){
	var func=arguments.callee.caller;
	var length=queue.length;
	for (var i=0;i&lt;queue.length;i++){
		(function (){
			var o=queue[i];
			var _old = o.complete;
			o.complete = function(){
				if ( _old ) _old.apply( this, arguments);
				length--;
				if (0==length) {
					Callback(func,args[0],args[1]);
				}
			};
			jQuery.ajax(o);
		})();
	}
}
function Callback(func,self,args){
	func.apply(self,args);
}</pre>
&nbsp;
<p>测试:</p>
<pre name="code" class="js">function foo(ddd){
 if(arguments.callee.caller!=Callback){
   return ajaxCallback([
    {url:'/1.txt',complete:function(){alert(1);}},
    {url:'/1.txt',complete:function(){alert(2);}}],
    [this,arguments]);
 }
 alert(ddd);
 alert(this);
}
foo(3);
var f={};
f.foo=foo;
f.foo(3);</pre>
<p>这回好了。不占参数，this也得到了正确（其实是调用的时候主动传过去的）传递.</p>
<p>ajax 伪同步实现.</p>
<p><strong><span style="color: #ff0000;">备注</span>
</strong>
:<strong>您需要明白的是,我这里说的同步指的是调用ajax的函数实现了伪阻塞,关于多ajax请求伪同步的方法有队列法,比如jQuery的插件<a href="http://jquery.com/plugins/project/ajaxqueue" target="_blank">ajaxQueue</a>
</strong>
,<strong>从某种意义上说我的这个方法也可以实现,不过既然人家工作的很好,就不费这个力气了.</strong>
</p>
<p>暂时思路只能到这里,进一步要靠实践了.</p>
<p>&nbsp;</p>
<p>更新.感觉函数的名字起的不好,改了下,而且增加了不需要回调的判断:</p>
<pre name="code" class="js">//多ajax请求队列,支持完结回调
function ajaxQueue(queue,thiss,argss,other){
	if (arguments.length&lt;1) return false;
	if (!argss) argss=[];
	var args=[];
	for (var i=0;i&lt;argss.length ;i++ )
		args.push(argss[i]);
	if (other)
		for (var i=0;i&lt;other.length ;i++)
			args.push(other[i]);
	var func=arguments.callee.caller;
	(function (a,func,thiss,args){
		var o=a.shift();
		//增加了判断是否要回调
		if (!o) return thiss?thisCallback(func,thiss,args):false;
		var self=arguments.callee;
		var _old = o.complete;
		o.complete = function(){
			if ( _old ) _old.apply( this, arguments);
			self(a,func,thiss,args);
		};
		jQuery.ajax(o);
	})(queue,func,thiss,args);
	return false;
}
//回调函数,保持原来的this指针
function thisCallback(func,thiss,args){
	if (func.constructor == Function)
		func.apply(thiss,args);
	return false;
}</pre>
&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/209575#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 30 Jun 2008 09:15:15 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/209575</link>
        <guid>http://achun.javaeye.com/blog/209575</guid>
      </item>
      <item>
        <title>jCT 第三版预览</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/208304" style="color:red;">http://achun.javaeye.com/blog/208304</a>&nbsp;
          发表时间: 2008年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>重新进行了设计,抛弃了所有重新定义javascript固有语法的方法,这样也就是<strong>无招胜有招</strong>
了,</p>
<p>而且可方便自定义<strong>标记</strong>
,没有精力写注解和用法了.直接贴源代码(初稿)吧:(请在FF下测试,还没有调整IE的兼容性)</p>
<p>细心的朋友应该可以看出来,不同标记之间是可以转换的.</p>
<pre name="code" class="js">/**
 * javascript Common Templates(jCT) 3(第3版)
 * http://code.google.com/p/jsct/
 *
 * licensed under the MIT license.
 *	http://www.opensource.org/licenses/mit-license.php
 *
 * Author achun (achun.shx at gmail.com)
 * Create Date: 2008-6-23
 * Last Date: 2008-6-26
 * Revision:3.8.6.26
 * 预定义变量:
 		D............用于生成函数的输入参数,表示提供给模板的数据.可以通过设置Main改变此名称
 * 保留属性:有些属性的保留纯粹是为了方便调试
		CTA..........SRC的模板数组形式表示
		CTD..........用于保留执行(Exec)模板时候传入的参数
		CTV..........在执行(Exec)模板过程当中生成结果的数组形式
		Fn...........继承自jCT的几个属性和方法
		MAIN.........Build模板的时候生成的主体过程数组形式
		PATH.........保留模板的URL路径,由调用模板的函数提供，保留这个的目的是考虑到这个参数可能会有很多的用途。
		SRC..........模板原文本,由调用模板的函数提供
		TAG..........模板标签风格,来自Fn的引用
		ERROR........Build异常时的错误信息.
 * 保留方法:
		Build........构建模板的Exec方法,参数对应属性的TAG
		Clean........清理模板,参数对应属性的TAG
		Exec.........执行模板
 * 保留字串:
		...          再使用Main时用于替换主体过程的占位符
 * 调用:
		var jct = jCT(txt,path,tag);
		txt..........对应属性SRC
		path.........对应属性PATH
		tag..........对应属性TAG
 */
function jCT3(txt,path,by){
	var self=function(){
		return arguments.callee.Exec.apply(arguments.callee,arguments);
	};
	by=by||'comment';//默认的标记风格,到底是用script还是comment呢?
	self.Fn={};
	for (var prop in jCT3.Fn)
		self.Fn[prop] = jCT3.Fn[prop];
	self.SRC=txt;
	self.PATH=path;
	self.TAG=self.Fn[by];
	self.CTA=[];
	self.CTV=[];
	self.CTD={};
	self.Clean=function(){
		this.Fn.src=this.SRC;
		this.Fn.path=this.PATH;
		this.Fn.clean(this.TAG.clean);
		return this.Fn.src;
	};
	self.Build=function(){
		this.Clean();
		var fn=this.Fn;
		this.MAIN=[];
		fn.path=this.PATH;
		var ext=fn.parse(this,this.MAIN);
		var jctbody=this.MAIN.join('\n');
		if (ext.run) window.eval(ext.run);
		if (ext.main) {
			var func=ext.main.replace('{...}','\n{this.CTV=[];'+jctbody+'\n}\n');
		}else{
			var func='function(D){if(!D) D={};this.CTD=D;with(D){this.CTV=[];'+jctbody+'}\nreturn this.CTV.join(&quot;&quot;);}';
		}
		try{
			this.Exec = eval('false||'+func);
		}catch (ex){
			this.Exec = function(){return 'jCT Parse Error';};
			this.ERROR={message:ex.message + '\n'+ (ex.lineNumber || ex.number),src:func};
		}
		return this;
	};
	self.Build();
	return self;
}
jCT3.Fn={
	clean:function(tn){
		var a=[];
		var p=[0,0,0,0,0];
		var e=this.src.length;
		while (this.slice(tn,p[4],p,e))
			a.push(this.src.slice(p[0],p[1]));
		a.push(this.src.slice(p[4]));
		this.src = a.join('');
	},
	parse:function(self,jctbody){
		var tag = self.TAG;
		var cta = self.CTA;
		var p=[0,0,0,0,0];
		var e=this.src.length;
		var main='';
		var run='';
		while (this.slice(tag.tag,p[4],p,e)){//语法分2段
			var p1=[0,0,0,0,p[0]];
			while (this.slice(tag.exp,p1[4],p1,p[1])){//第1段取值表达式
				jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
				cta.push(this.src.slice(p1[0],p1[1]));
				jctbody.push('this.CTV.push('+this.src.slice(p1[2],p1[3])+');');
			}
			jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
			cta.push(this.src.slice(p1[4],p[1]));
			//处理第2段
			if (this.slice(tag.ext,p[2],p1,p[3])){///*+*/处理
				jctbody.push('this.CTV.push('+this.src.slice(p1[0],p1[1])+');');
				var str=this.src.slice(p1[2],p1[3]);
				var tmp=str.indexOf(' ');
				var par='',sta='';
				if (tmp&gt;0){
					par=str.slice(tmp+1);
					sta=sta.slice(0,tmp);
				}else
					sta=str;
				var foo=this.src.slice(p1[4],p[3]);
				switch(sta){
					case 'Main':main=foo;break;
					case 'Run':run+=foo+&quot;\n&quot;;break;
					case 'Child':
						var p2=[];
						var child=tag.tag.begin+'/*-'+str+'*/'+tag.tag.end;
						tmp = this.src.indexOf(child,p[4]);
						if (tmp&gt;0){
							self[par]=jCT3(txt.slice(p[4],tmp),this.path);
							p[4] = tmp + child.length;							
						}					
						break;
				}
			}else{
				jctbody.push(this.src.slice(p[2],p[3]));
			}
		}
		var p1=[0,0,0,0,p[4]];
		while (this.slice(tag.exp,p[4],p1,e)){//第1段取值表达式
			jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
			cta.push(this.src.slice(p1[0],p1[1]));
			jctbody.push('this.CTV.push('+this.src.slice(p1[2],p1[3])+');');
		}
		jctbody.push('this.CTV.push(this.CTA['+cta.length+']);');
		cta.push(this.src.slice(p1[4]));
		return {main:main,run:run};
	},
	slice:function(tn,b1,p,max){//把string第2段分成2段
		var begin=tn.begin;
		var end=tn.end;
		var e1,b2,e2;
		e1=this.src.indexOf(begin,b1);
		if (e1&lt;0 || e1&gt;=max) return false;
		b2=e1+begin.length;
		if (b2&lt;0 || b2&gt;=max) return false;
		e2=this.src.indexOf(end,b2);
		if (e2&lt;0 || e2&gt;=max) return false;
		p[0]=b1;p[1]=e1;
		p[2]=b2;p[3]=e2;
		p[4]=e2+end.length;
		return true;
	},
       //下面就是几个自定义标记的配置了
	comment:{//注释标记风格
		tag:{begin:'&lt;!---',end:'--&gt;'},
		exp:{begin:'+-',end:'-+'},
		ext:{begin:'/*+',end:'*/'},
		clean:{begin:'&lt;!--clean--&gt;',end:'&lt;!--clean --&gt;'}
	},
	script:{//脚本标记风格
		tag:{begin:'&lt;script type=&quot;jct&quot;&gt;',end:'&lt;/script&gt;'},
		exp:{begin:'+-',end:'-+'},
		ext:{begin:'/*+',end:'*/'},
		clean:{begin:'&lt;script type=&quot;jct&quot; /&gt;',end:'&lt;script type=&quot;jct&quot; /&gt;'}
	},
	code:{//code标记风格
		tag:{begin:'&lt;code lang=&quot;jct&quot;&gt;',end:'&lt;/code&gt;'},
		exp:{begin:'+-',end:'-+'},
		ext:{begin:'/*+',end:'*/'},
		clean:{begin:'&lt;code lang=&quot;jct&quot; /&gt;',end:'&lt;code lang=&quot;jct&quot; /&gt;'}
	}
};</pre>
&nbsp;
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/208304#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 26 Jun 2008 17:31:03 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/208304</link>
        <guid>http://achun.javaeye.com/blog/208304</guid>
      </item>
      <item>
        <title>jCT 第三版计划</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/207212" style="color:red;">http://achun.javaeye.com/blog/207212</a>&nbsp;
          发表时间: 2008年06月23日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>jCT 第三版的设计目标：</p>
<p>&nbsp;</p>
<p>0.保留二版的原有功能<br />
1.解决编辑器中高亮语法的问题<br />
2.在线修改模板成为可能(配合其他工具)<br />
3.即改即用(配合其他工具)，应该叫及时编译JIT</p>
<p>4.更精简的实现</p>
<p>&nbsp;</p>
<p>为达到上述目标，计划采用如下技术手段：</p>
<p>&nbsp;</p>
<p>1.语法标签变更：</p>
<p>&nbsp;</p>
<pre name="code" class="html">&lt;script type="jct"&gt;
&lt;/script&gt;

&lt;code lang="jct"&gt;
&lt;/code&gt;</pre>
<p>&nbsp;2.属性增加：src</p>
<p>&nbsp;3.语法变更：完全采用javascript原始语法</p>
<p>&nbsp;4.扩充语句:所有扩冲均采用：/*+扩充语句*/Javascript块注释包括</p>
<p>&nbsp;</p>
<p>对jct还不了解的朋友也许不知道我在说什么，看看<a href="http://achun.javaeye.com/category/33268" target="_self">jCT专题</a>
吧.</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/207212#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 23 Jun 2008 20:25:31 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/207212</link>
        <guid>http://achun.javaeye.com/blog/207212</guid>
      </item>
      <item>
        <title>nicEdit inline,让我们重新考虑提交的数据来源</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/206878" style="color:red;">http://achun.javaeye.com/blog/206878</a>&nbsp;
          发表时间: 2008年06月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>一直以来，大家做web，从B向S提交复杂数据用的都是form.</p>
<p>为什么？这还用想，天经地义，form就是干这个的。</p>
<p>但是，现在更多的<strong>ajax</strong>
应用提交的时候仅仅是用form来创建提交数据，提交行为如何实现已经不用我们担心了。</p>
<p>nicEdit的<strong>inline</strong>
特性为我们创建提交数据提供了新的选择。</p>
<p>问：</p>
<p>ajax提交的数据<strong>一定要用</strong>
form创建吗？--------------------------------------不！</p>
<p>除了textarea就不能从div,p...其他Element中来取要提交的数据吗？------能！</p>
<p>&nbsp;</p>
<p>ajax提交当然不完全依赖form或者form元素了，ajax提交关系的是数据，不关系数据的来源，数据的来源是可以用程序的方法制定的。</p>
<p>&nbsp;</p>
<p>那么我们有了nicEdit的<strong>inline</strong>
特性，就可以<span style="color: #ff6600;"><strong>抛弃textarea</strong>
</span>
了，因为她真的很多余，至于是否抛弃form这个到不是关键，因为提交数据是用程序的方法制定，当然你可以从form，或者div,或者运算出数据了。至于具体的提交过程是否使用form(因为文件提交的原因，这个问题很复杂和具体的应用有关)是提交代码实现的问题。</p>
<p>&nbsp;</p>
<p>如果我们可以把<span style="color: #ff6600;"><strong>文件提交分离</strong>
</span>
出来处理（当然并不适合所有的需求，但是事实是还是无文件提交的时候多）。那可以说form可以下岗了。</p>
<p>&nbsp;</p>
<p>下面的问题就是设计一个<span style="color: #ff6600;"><strong>从Element</strong>
<strong>提取</strong>
</span>
<span style="color: #ff6600;"><strong>提交数据</strong>
</span>
的组件了（当然便利的form元素还是要用），呵呵相信不同的程序员会有不同的设计的。</p>
<p>偶打算基于jQuery设计一个。</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/206878#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 22 Jun 2008 18:20:35 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/206878</link>
        <guid>http://achun.javaeye.com/blog/206878</guid>
      </item>
      <item>
        <title>javascript的值,对象,原型</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/206218" style="color:red;">http://achun.javaeye.com/blog/206218</a>&nbsp;
          发表时间: 2008年06月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>探讨一下,如有纰漏请指正.</p>
<p>认识在前面:先给出我们讨论的结果</p>
<p>===========================================</p>
<p>javascript是基于原型(<strong>prototype-based</strong>
)的语言.</p>
<p>javascript具有面向对象(<span style="color: #000000;"><strong>Object-Oriented</strong>
</span>
)的编程风格.</p>
<p><strong>变量不一定是对象(undefined,null等就是特例,但是NaN是个对象)</strong>
</p>
<p><strong>对象一定有值,也有成员(函数,属性)</strong>
</p>
<p><strong>Object不是顶级的,因为可以delete Object</strong>
</p>
<p><strong>顶级</strong>
的有:</p>
<p style="background-color: #ffffff; padding-left: 30px;"> <strong><span style="color: #000000;">Array Object<br />
Boolean Object<br />
Date Object<br />
Function Object<br />
Math Object<br />
Number Object<br />
RegExp Object<br />
String Object</span>
</strong>
</p>
<p><strong>new</strong>
运算符具有一定的<strong>魔术性,这个说法我语言上还组织不好.</strong>
</p>
<p>==========================================</p>
<p>首先我用了词:<strong>原型</strong>
</p>
<p>马上您就知道为什么这么说了.</p>
<p>javascript是基于对象(<strong><span style="color: #000000;">Object-based</span>
</strong>
)的吗?<strong>不是</strong>
</p>
<p>javascript是面向对象(<span style="color: #000000;"><strong>Object-Oriented</strong>
</span>
)的吗?<strong>是</strong>
,要清楚这句话指的是编程方法类似面向对象的编程,但是也有很多不同的地方.</p>
<p>那我们看看<a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Class-Based_vs._Prototype-Based_Languages" target="_blank">Mozilla官方的说法</a>
</p>
<div class="quote_title"> 写道</div>
<div class="quote_div">A prototype-based language, such as JavaScript,
does not make this distinction: it simply has objects. A
prototype-based language has the notion of a prototypical object, an
object used as a template from which to get the initial properties for
a new object. Any object can specify its own properties, either when
you create it or at run time. In addition, any object can be associated
as the prototype for another object, allowing the second object to
share the first object's properties. </div>
<p>&nbsp;javascript是基于原型(<strong>prototype-based</strong>
)的语言.</p>
<p>&nbsp;</p>
<p>那么我们在描述,研究这个语言的时候就会牵扯到这几个问题.</p>
<p><strong>值和对象</strong>
:</p>
<pre name="code" class="js">var obj={};
var num=9;
var str='string'
var arr=[];
</pre>
<p>&nbsp;很明显上面的几个变量都是一个对象,那<strong>变量一定是对象吗</strong>
?</p>
<pre name="code" class="js">var foo;</pre>
<p>&nbsp;foo是一个变量,但是foo不是对象.对象有个<strong>事实上</strong>
的特征就是,<strong>对象一定有成员</strong>
(属性或方法).</p>
<p>&nbsp;foo就没有任何成员,他的值是<strong>undefined</strong>
,而<strong>undefined</strong>
的定义是:</p>
<div class="quote_title"> </div>
<div class="quote_div">undefined is a property of the global object, i.e. it is a variable in global scope.<br />
The initial value of undefined is the primitive value undefined. <br />
<br />
undefined 属性是 Global 对象的一个成员，该属性在脚本引擎初始化后可用。如果已声明了一个变量但还没有初始化，那么该变量的值就是 undefined。</div>
<p>&nbsp;也就是说<strong>undefined</strong>
是一个顶级共有属性,用关键字描述<strong>undefined</strong>
其实更确切.</p>
<p>&nbsp;现在我们举几个<strong>值对象(</strong>
javascript的其他类型的还有,就不提了<strong>)</strong>
</p>
<pre name="code" class="js">'isstring'.constructor;//String()
true.constructor;//Boolean()
9.0.constructor;//Number();这下对了吧csf178
(9).constructor;//Number();匿名对象
9.constructor;//SyntaxError;经csf178指正,这是浮点数转换造成的语法冲突
[].constructor;//Array()
{}.constructor;//fireFox :SyntaxError;IE : Object();注意javascript定义中{}是代码块和对象定义,不是Operator
({}).constructor;//Object();匿名对象
</pre>
<p>&nbsp;其实值对象这个说法不是很合适.就像上面的前3个确实是值.第4个(9)其实是一个<strong>匿名的Number对象</strong>
,</p>
<p>但是接下来的两句就有意思了.{}和[]竟然还有如此的区别.而且fireFox和IE实现也不同.(其实从优先级上可以找到一些答案,可惜不同实现有差异)</p>
<p><a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Literals" target="_blank">Object Literals</a>
中明确指出{}.xxx这种用法是错误的,所以fireFox出SyntaError是正常的.MS的jscript文档我没有看过,不知道如何解释这个.</p>
<p>那我们如何来评论javascript的这些特性呢?</p>
<p><span style="text-decoration: line-through;">抛弃面向对象这个说法吧,javascript真的不适合.</span>
<span style="text-decoration: line-through;">javascript就是这样的不严格,但是很实用.</span>
</p>
<p>经csf178指正后,看来javascript仍旧是OO的.但是是<strong>prototype-based</strong>
的OO,不是Class-based的OO.</p>
<p>也就是说在javascript里所有的对象都有原型,<a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Predefined_Core_Objects" target="_blank">官方给出的原型</a>
</p>
<p>(好在我写这个帖子的时候就是为了要搞清楚这3者的关系)</p>
<p>总结:<strong>变量不一定指向对象</strong>
(貌似废话),<strong>对象一定有值</strong>
</p>
<p><strong>原型</strong>
:</p>
<p>是<strong>对象一定有原型constructor</strong>
</p>
<p>这一点从可以从javascript的constructor的定义中找到根据.</p>
<p>请注意上面例子中所有的constructor都是以函数给出的,其实</p>
<p><strong>原型constructor一定是一个函数形式的定义</strong>
</p>
<pre name="code" class="js">javascript:function fun(){};
new fun.constructor;//anonymouse();
(new fun).constructor;//fun();
new fun().constructor;//fun();
(new fun()).constructor;//fun();

</pre>
<p>&nbsp;为什么这样?其实这很正常,看看<a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Operators#Operator_Precedence">javascript运算符的优先级</a>
就明白了.当然,你不能死照优先级来看语法的合法性,解释起来会很绕嘴的.</p>
<pre name="code" class="js">new Function().constructor;//Function()
new Function.constructor;//anonymous()
new (Function.constructor);//anonymous()
new (Function().constructor);//anonymous()

</pre>
<p>&nbsp;这几个例子优先级就明显了.</p>
<p>(下面的几行是经csf178指正后,反思的结果)</p>
<p>回头再看看<a href="http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:Predefined_Core_Objects" target="_blank">官方给出的原型</a>
里面唯独却少了最重要的Object,我们知道Object一定是个对象(javascript里没有class),Object又不在Core里,那Object是从哪里来的呢?</p>
<pre name="code" class="js">Object().constructor;//Object()
Object.constructor;//Function()</pre>
<p>原来Object是由系统自Function 创建的.怎么证明呢?</p>
<pre name="code" class="js">alert(Object);//Object()
delete Object;//true
Object;//ReferenceError: Object is not defined</pre>
<p>但是你不能delete Function.</p>
<p><strong>Function就是一切</strong>
</p>
<p>(反思到这里了)</p>
<p>因此我们讨论javascript对象的时候不要用<span style="color: red;">class-based OO</span>
的概念去靠(经csf178指正),找<strong>原型</strong>
<strong>constructor</strong>
是关键</p>
<p>当然javascript提供了更直观的<strong>prototype</strong>
属性来实现OO方法的问题.</p>
<p><strong>new</strong>
这个运算符具有一定的<strong>魔术性</strong>
</p>
<pre name="code" class="js">function fun1(){this.n=3;}
function fun2(){this.n=3;return {};}
var foo1=new fun1;//{n:3}
var foo2=new fun2;//{}</pre>
<p>&nbsp;也就是说<strong>原型</strong>
<strong>constructor</strong>
的return值是对new有影响的.这就是new的魔术性</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/206218#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 20 Jun 2008 14:55:55 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/206218</link>
        <guid>http://achun.javaeye.com/blog/206218</guid>
      </item>
      <item>
        <title>降低前后台业务逻辑上的耦合度,前后台细粒度数据通讯的方法</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/200417" style="color:red;">http://achun.javaeye.com/blog/200417</a>&nbsp;
          发表时间: 2008年06月05日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><strong>问题的提出</strong>
:</p>
<p>jCT模板属于前后台分离的设计.</p>
<p>对于前后台分离的设计.</p>
<p>S根据B提出的请求,发送原始数据,S不需要对表现层有任何控制,降低了B,S的耦合度.</p>
<p>这种降低了B,S的耦合度方法,本质上是降低了<span style="color: #ff6600;"><strong>数据内容</strong>
</span>
上的<span style="color: #ff6600;"><strong>耦合度</strong>
</span>
,仅仅把表现层的控制数据分离出去了.</p>
<p>由于请求和数据直接影响到表现,<strong><span style="color: #ff6600;">表现</span>
</strong>
是<span style="color: #ff6600;"><strong>业务逻辑</strong>
</span>
的最直接体现,但是<span style="color: #000000;">这量词不能画等号.因此我们用<span style="color: #ff6600;"><strong>表现逻辑</strong>
</span>
</span>
这个词.暗示表现和业务逻辑是关联比较密切的.</p>
<p><span style="color: #ff6600;"><span style="color: #000000;">当</span>
</span>
<span style="color: #ff6600;"><strong>表现逻辑</strong>
<span style="color: #000000;">变化的时候,势必要</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;">改变</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;">后台<strong><span style="color: #ff6600;">数据内容</span>
</strong>
的组合结构,我们的问题就是</span>
</span>
</p>
<p><span style="color: #000000;">如何降低前后台</span>
<span style="color: #ff6600;"><strong>表现逻辑<span style="color: #000000;">(</span>
</strong>
</span>
<span style="color: #000000;"><strong>业务逻辑)</strong>
</span>
<span style="color: #000000;">上的耦合度</span>
</p>
<p>&nbsp;</p>
<p><strong>附加举例</strong>
说明问题:</p>
<p>常见的页面上有访问排名,如果我们要增加或减少一个排名的表现的话,<strong><span style="color: #ff6600;">表现</span>
</strong>
是要改的,后台<span style="color: #ff6600;"><span style="color: #000000;"><strong><span style="color: #ff6600;">数据内容</span>
</strong>
<span style="color: #ff6600;"><span style="color: #000000;">也要同期改,这就是耦合度高的问题.</span>
</span>
</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"></span>
</span>
</span>
</p>
<p>当然,对于新增的表现,采取多次和后台通讯也是一种解决方法,不过这怎加了通讯的压力,有可能怎加表现的复杂度.</p>
<p><span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"><span style="color: #000000;">我们要达到<strong>只需要</strong>
</span>
</span>
</span>
</span>
<strong><span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"><span style="color: #000000;">改</span>
</span>
</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"><span style="color: #000000;">表现,不用改</span>
</span>
</span>
</span>
<span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"><span style="color: #000000;">后台</span>
</span>
</span>
</span>
</strong>
<span style="color: #ff6600;"><span style="color: #000000;"><span style="color: #ff6600;"><span style="color: #000000;">,并且不增加通讯次数的目标.</span>
</span>
</span>
</span>
</p>
<p>&nbsp;</p>
<p><strong>问题分析</strong>
:</p>
<p><span style="color: #ff6600;"><strong>表现逻辑</strong>
</span>
最终体现在原始数据的变化上.</p>
<p>业务逻辑对数据的细粒度化是比较容易实现的,就是把数据的请求最小化,然后把<strong><span style="color: #ff6600;">多个请求</span>
</strong>
获得的数据组合输出就行了.这在设计中是常见的.最简单的就是按请求的次序<span style="color: #ff6600;"><strong>请求队列</strong>
</span>
,输出<strong>关联数组结构</strong>
的数据就行了.</p>
<p>那要解决的问题就是,前台如何在一次通讯中发出<span style="color: #ff6600;"><strong>请求队列</strong>
<span style="color: #000000;">,后台如何正确解析</span>
</span>
<span style="color: #ff6600;"><strong>请求队列</strong>
<span style="color: #000000;">的问题.</span>
</span>
</p>
<p>&nbsp;</p>
<p><strong>解决方案</strong>
:</p>
<p>这里我直接给出我的方案,</p>
<p><strong>利用POST方法和GET参数的配合.</strong>
</p>
<p>在实际使用POST和GET方法的时候我们通常是用<strong>参数名=值</strong>
,这种<strong>值对</strong>
的形式提交,事实上http协议并没有限定死这种形式,我们这种形式对http协议来说只不过是一串字符串罢了.用<strong>ajax</strong>
方法提交数据的时候是可以直接传送以<strong>JSON形式</strong>
的数据的,这就是纯字符串了.<strong>JSON</strong>
对数据的表现能力是毋庸置疑的.经后台解析后才对象化的.</p>
<p>我们可以把<span style="color: #ff6600;"><strong>请求队列</strong>
<span style="color: #000000;">以</span>
</span>
<strong>JSON</strong>
形式与后台通讯,后台完成<span style="color: #ff6600;"><strong>请求队列</strong>
</span>
<span style="color: #ff6600;"><span style="color: #000000;">解析.当然对于<strong>ajax</strong>
来说使用<strong>POST</strong>
方法</span>
</span>
</p>
<p>无疑是很好的,因为<strong>POST</strong>
方法其实是兼容<strong>GET</strong>
的,<strong>ajax</strong>
请求中的<strong>url</strong>
参数就是<strong>GET</strong>
方法的实现.那<strong>GET参数</strong>
在这里有什么用途呢?<strong>共用参数</strong>
的传递(这个语言描述就到这里,做个应用的朋友应该已经明白了).</p>
<p>&nbsp;</p>
<p>我一直用PHP编程,php获得POST过来的JSON数据是很容易的</p>
<pre name="code" class="cpp">$json=file_get_contents('php://input');
$json=json_decode($json,true);</pre>
<p>&nbsp;到此<span style="color: #ff6600;"><strong>请求队列</strong>
<span style="color: #000000;">的数据通信解决了,后台获取解决了,解析呢?这恐怕要和你的应用有关了.解决起来类似于如下结构</span>
</span>
</p>
<pre name="code" class="cpp">$OUT=array();
foreach($requireQueue as $Q){
   switch($Q['REQUIRE']){
   case 'gamelist':
      $OUT['gamelist']=foo();
   }
}</pre>
&nbsp;
<p>其中的gamelist这种业务逻辑上的请求就是细粒度的实现了.可以看出,在业务逻辑确定的情况下,表现只需要改变请求的队列就可以获取正确的数据了.</p>
          <br/>
          <span style="color:red;">
            <a href="http://achun.javaeye.com/blog/200417#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 05 Jun 2008 10:45:02 +0800</pubDate>
        <link>http://achun.javaeye.com/blog/200417</link>
        <guid>http://achun.javaeye.com/blog/200417</guid>
      </item>
      <item>
        <title>jCT更新,添加重构功能:main,entry,outlet</title>
        <author>achun</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://achun.javaeye.com">achun</a>&nbsp;
          链接：<a href="http://achun.javaeye.com/blog/198950" style="color:red;">http://achun.javaeye.com/blog/198950</a>&nbsp;
          发表时间: 2008年05月31日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>扩充了3个重构功能的语法.同时取消了 FixDat,ViewBefore,ViewAfter</p>
<p>目的:更灵活的适应应用的变化</p>
<p><strong>main:</strong>
自定义jCT生成对象的内部实现,用了语法,下面两个就可以不用了</p>
<p><strong>entry:</strong>
 自定义jCT生成对象的内部实现的入口部分</p>
<p><strong>outlet:</strong>
 自定义jCT生成对象的内部实现的出口部分
</p>
<p>首先</p>
<p>jCT生成的函数结构类似如下:</p>
<pre name="code" class="js">function (CTD) {//这就是entry部分
    if (!CTD) {
        CTD = {};
    }
    this.CTD = CTD;
    with (CTD) 
   {//这就是{...},body部分
       var __CTV__ = [];
        __CTV__.push(this.CTA[0]);
    }
    return __CTV__.join(&quot;&quot;);//这就是出口部分
    //这里还有个自定义局部函数部分
}</pre>
<p>&nbsp;重构功能使用者自己定义除了{...}body的部分,main方法的例子</p>
<pre name="code" class="js"><span class="com">&l