<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>songofhawk</title>
    <description></description>
    <link>http://songofhawk.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>BPM真的令人憎恨吗</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/228869" style="color:red;">http://songofhawk.javaeye.com/blog/228869</a>&nbsp;
          发表时间: 2008年08月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>InfoQ上登了这么一篇文章: <a href="http://www.infoq.com/cn/news/2007/12/developers-hate-bpm" title="为什么Java开发者憎恨BPM" class="quote_title" target="_blank">为什么Java开发者憎恨BPM</a></p>
<p>&nbsp;</p>
<p>作为一名在专业BPM公司工作做了3年的技术人员，我马上被标题吸引了。通读全文之后，觉得虽然组织和文法有点乱，内容还是蛮有些道理的，总结起来，BPM被开发者&ldquo;憎恨&rdquo;的原因有下面几点：</p>
<ol>
<li>强迫开发者使用点击和拖拽的方式为流程和UI建模，从而失去了编码的灵活性和维护效率</li>
<li>追求让业务人员自己建模，而实际上没有哪个业务人员愿意做这种事</li>
<li>一些BPM建模工具功能简陋，不能解决现实的业务问题</li>
<li>没有免费或开源的版本，因此很难对它们进行评估</li>
<li>一些BPM产品就像早期的UML建模工具一样，只能用来&ldquo;画画图&rdquo;，最终要让系统运行起来，还需要编码，而且编码工作量不小</li>
<li>BPM产品通常缺乏Java开发领域常见的测试工具，自动部署脚本等&ldquo;基础设施&rdquo;，从而严重影响开发效率</li>
<li>上面的所有问题并不仅仅是BPM的问题，而是存在于更广泛的领域，比如BRMS（业务规则建模系统）、MDD（模型驱动开发）、DDD（领域驱动开发）</li>
</ol>
<p>这些问题中，我们的合作伙伴也曾提到过几条。开发人员，尤其是熟悉了J2EE架构的开发人员们，往往对这种自动化的&ldquo;反动&rdquo;开发方式非常抵触<img src="../../../images/smiles/icon_confused.gif" alt="" /></p>
<p>&nbsp;</p>
<p>那让我们来逐一分析一下：</p>
<ol>
<li>可视化建模：其实从4GL时代起，UI的可视化建模，就成了企业应用软件开发环境的标准配置，j2ee领域也不例外，没人愿意纯用代码一点一点调整界面效果；在这方面不存在需不需要的问题，应当关注的是建模环境是否直观、方便，以及人机交互方式的灵活程度；至于业务流程的可视化建模，实际上出自同样的需求&mdash;&mdash;直观表达、方便调整，只是由于推出时间尚短，开发人员还没有形成使用习惯，各个厂商的产品也都不够成熟；</li>
<li>业务人员建模：老实说，在现阶段，我也认为这只是一个&ldquo;美好&rdquo;的愿望罢了，哪个业务人员愿意给自己找这个麻烦呢；不过，话说回来，使用BPM模型与业务人员沟通，绝对是有效的方式；特别是组合BPM与UI，快速搭建的系统原型，往往可以精准地定位需求；</li>
<li>BPM套件构建的系统不能符合业务要求：这个问题得从两方面看，一方面，有些BPM产品确实过于简单，建模工具本身表达能力有限，又不能灵活扩展，面对实际业务当然束手束脚；另一方面，BPM产品诞生之初就是要解决跨部门、跨组织、多种角色和异构系统交互问题的，对于不适合的领域，比如图形处理、密集运算，本来就不擅长。所谓&ldquo;术业有专攻&rdquo;是也；</li>
<li>缺乏开源/免费产品，不利于评估：没错，BPM市场还年轻，产品开发工作量却不小，开源产品的成熟还是需要一段时间的，但基本上所有主流商业产品都是很配合客户评估（废话，呵呵），开源领域的jBPM也不妨尝试一下。</li>
<li>可视化模型只是&ldquo;表面功夫&rdquo;，实际需求还要编码来解决：诚然，没有不编码就能实现所有业务需求的magic tool，不过，编码的多少却并不仅仅是个量的问题；所谓优秀的BPM产品，就是要将属于流程的、易变的逻辑抽象出来，由模型来应对这部分（很多时候还会结合规则引擎，这里先不展开了），而让代码去处理较为固定的逻辑，特别是密集运算、大规模数据处理类的逻辑；</li>
<li>缺乏自动化测试和部署工具的支持：这的确是当前大多数BPM工具的通病，不过，随着产品成熟度的提高，问题正在逐步解决（比如<a href="http://www.cordys.com" title="Cordys公司" target="_blank">我们公司</a>的产品现在就提供自动化部署的支持，也能通过<a href="http://www.junit.org/" title="JUnit单位测试工具" target="_blank">JUnit</a>和<a href="http://www.soapui.org/" title="SOAPUI web服务测试工具" target="_blank">SOAPUI</a>进行单元测试）</li>
<li>不仅仅是BPM的问题：呵呵，这看上去更像优点，如果你认为领域建模是有意义的、模型驱动开发的思想是先进的，为什么不尝试一下BPM呢？</li>
</ol>
<p>总之，BPM不是银弹，它有自己的问题和缺点，但在适合的领域，它可以工作得很出色，随着整个产业的成熟，它还会越来越好。</p>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/228869#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, 17 Aug 2008 11:00:14 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/228869</link>
        <guid>http://songofhawk.javaeye.com/blog/228869</guid>
      </item>
      <item>
        <title>如何减少子类对超类的依赖——一个设计问题</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/177071" style="color:red;">http://songofhawk.javaeye.com/blog/177071</a>&nbsp;
          发表时间: 2008年03月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>一般来说，根据所谓好莱坞原则，我们不应该在子类中显示调用超类的方法，而是通过重写超类的方法来实现特殊的逻辑，以此来避免循环依赖。不过，调用超类中被重写的同名方法，通常是可以接受的，比如：</p><pre name="code" class="java">Class A
{
  public void go()
  {
     System.out.println(&quot;do by A&quot;);
  }
}

Class B extends A
{
  @Override
  public void go()
  {
     System.out.println(&quot;do by B&quot;);
     super.go();
  }
}</pre><p>&nbsp;</p><p>如果超类要做的事，总在子类之前，或者之后，是没有问题的，而一旦子类do的前后各需要一段公共的代码，这个办法就行不通了。</p><p>&nbsp;</p><p>于是我们干脆把一个方法拆成两个，其中一个&ldquo;大&rdquo;方法调用另一个&ldquo;小&rdquo;方法，由子类去重写那个小方法，这样子类干脆就不用掉父类的方法了，显得更加纯粹：</p><p>&nbsp;</p><pre name="code" class="java">abstract Class A
{
  public void go() //大方法
  {
     prepare()
     going();
     clearup()
  }

  abstract public void going(); //小方法

  protected void prepare()
  {
     System.out.println(&quot;prepare by A&quot;);
  }

  protected void clearup()
  {
     System.out.println(&quot;clearup by A&quot;);
  }
}

Class B extends A
{
  @Override 
  public void going() //重写小方法
  {
     System.out.println(&quot;do by B&quot;);
  }
}</pre><p>&nbsp;</p><p>问题是，如果Class B还有子类呢，它自己也需要在子类的执行逻辑前后插入一些东西，难道又把doing这个&ldquo;小&rdquo;函数拆开？这是不是太复杂了点？再说我都不知道怎么跟下面的&ldquo;小小&rdquo;函数起名字了<img title="wink" src="../../images/smiles/icon_wink.gif" border="0" alt="wink" />&nbsp;。当然，让子类反过来调Class B的函数更不好，不但违反了前面的&ldquo;Don't call me&rdquo;原则，而且本身就很麻烦&mdash;&mdash;每个子类都得写。</p><p>&nbsp;</p><p><strike>有没有更好的办法呢？</strike>&nbsp; 看来这个问题没写清楚，引起了一些误会，有必要进一步解释一下。首先，我这里并不是想验证或者实践某种模式，确实是一个实际的开发项目遇到了需要权衡的地方。</p><p>&nbsp;</p><p>目前我的设计大致是像下面的样子：</p><p>&nbsp;</p><p><img src="../../../upload/picture/pic/10802/2240c595-e694-3f4f-894d-1fa666a04f7b.png" border="0" height="377" alt="设计问题类图" width="474" /></p><p>&nbsp;</p><p>只所以选用继承结构，是因为子类所代表的几个概念与父类在自然意义上确实是&quot;is a&quot;的关系，并且在子类间是互斥的；而且A/B/C这几个类都很稳定，可能发生的变化主要是B可能会增加子类B3,B4，或者A会增加子类D,E之类的。</p><p>&nbsp;</p><p>使用它们的客户程序在获得一个实例之后，一般情况下只会调用它们的go方法，也就是说，不关心具体的实例是属于哪种类型的。当然，有很多方式都可以实现这个需求，而我关心的是，怎样才能让可能新增的B3、B4、D、E这些类实现起来最简单、可靠。所以，最终还是选择了逐步细分函数的方式。</p><p>&nbsp;</p><p>代码如下：</p><pre name="code" class="java">abstract Class A
{
  public void go() //大方法
  {
     prepare()
     going();
     clearup()
  }

  abstract public void going(); //小方法

  protected void prepare()
  {
     System.out.println(&quot;prepare by A&quot;);
  }

  protected void clearup()
  {
     System.out.println(&quot;clearup by A&quot;);
  }
}

abstract Class B extends A
{
  @Override 
  public void going() //重写小方法
  {
  	 beforeRun();
  	 run(); //小小方法
  	 afterRun();
  }
  
  abstract public void run();
  
  protected void beforeRun()
  {
  	 System.out.println(&quot;beforeRun by B&quot;);
  }

  protected void afterRun()
  {
  	 System.out.println(&quot;beforeRun by B&quot;);
  }
}

Class B1 extends B
{
  @Override 
  public void run() //重写小小方法
  {
     System.out.println(&quot;go by B1&quot;);
  }
}

Class B2 extends B
{
  @Override 
  public void run() //重写小小方法
  {
     System.out.println(&quot;go by B2&quot;);
  }
}

Class C extends A
{
  @Override 
  public void going() //重写小方法
  {
     System.out.println(&quot;go by C&quot;);
  }
}
</pre><p>&nbsp;</p><p>&nbsp;</p><p>这样，B在自己的层次，&ldquo;要求&rdquo;本类别的Class在go的时候，必须按顺序调用beforeRun和afterRun，新增的B?子类只需实现自己的run方法即可被正确使用；万一真有很特殊的情况，新的子类希望在go的时候不要调用beforeRun或者afterRun，那么用一个空函数覆写它们即可。</p><p>&nbsp;</p><p>反之，如果beforeRun/afterRun这样的函数需要B?子类来调用，那么绝大多数子类都要编写调用的代码，也包括将来可能扩充的，这显然造成了一定的代码重复。</p>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/177071#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, 27 Mar 2008 23:30:16 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/177071</link>
        <guid>http://songofhawk.javaeye.com/blog/177071</guid>
      </item>
      <item>
        <title>Javascript高级程序设计阅读笔记(4)——数组</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/104513" style="color:red;">http://songofhawk.javaeye.com/blog/104513</a>&nbsp;
          发表时间: 2007年07月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h3>对象</h3><h4>本地对象</h4><p>所谓&quot;native object&quot;，是指&ldquo;独立于宿主环境的ECMAScript实现提供的对象&quot;，目前即是ECMA-262标准定义的类：</p><p>Object&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Function&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; Array&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;String</p><p>Boolean&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RegExp</p><p>Error&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;EvalError&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; RangeError&nbsp;&nbsp;&nbsp; ReferenceError</p><p>SyntaxError&nbsp;&nbsp;&nbsp; TypeError&nbsp;&nbsp; URIError</p><h5>Array&nbsp;</h5><p>在我用过的所有语言中，Javascript中的数组是最爽的了（当然也只有JS是动态语言，呵呵）：&nbsp;既可以像普通数组一样访问，又可以像类实例一样调用它的属性和方法。像下面这样：</p><p>var testArray=[3,&quot;17&quot;,6.5];</p><p>alert(testArray.length);</p><p>从上面也可以看出，由于弱类型语言的特点，数组中的元素可以不必同类型，甚至不必有什么关系；当然，取出的时候也不必做什么类型转换&mdash;&mdash;这可比Java里又要定义超类或接口，又要来回来去地downcast/upcast方便多了。</p><p>数组的大小是完全动态的，需要使用的时候，直接赋值就好了。如：testArray[25]=&quot;red&quot;；这时，如果下标0-24还没有使用过，它们对应的元素会被置为<strong>null</strong>，而数组的length属性会变为26。这个特性说明，一个&ldquo;稀疏&rdquo;数组很会浪费空间的。</p><p>当然，企图在一个元素被赋值之前就使用的话，还是会出错的。</p><p>数组有两个很有用的方法：join和push，两者结合，可以大大提高字符串连接的效率，如下：</p><div class="dp-highlighter"><ol class="dp-c"><li class="alt"><span><span class="comment">//这段代码每次循环时把数字压栈，最后一次性连接成字符串 </span><span>&nbsp;&nbsp;</span></span> </li><li><span class="keyword">var</span><span>&nbsp;strArray=[]; &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;</span> </li><li><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;i=0,&nbsp;i&lt;=1000,&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strArray.push[i]; &nbsp;&nbsp;</span> </li><li><span>} &nbsp;&nbsp;</span> </li><li class="alt"><span>strArray.join(</span><span class="string">&quot;-&quot;</span><span>); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//下面这段用+来连接字符串，每次循环都会产生一个新的字符串对象，效率自然低得多；而且还要处理&ldquo;最后一个操作数&rdquo;的问题 </span><span>&nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;sTest=</span><span class="string">&quot;&quot;</span><span>; &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;</span> </li><li><span class="keyword">for</span><span>&nbsp;(</span><span class="keyword">var</span><span>&nbsp;i=0,&nbsp;i&lt;=1000,&nbsp;i++)&nbsp;{ &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(i&lt;1000)&nbsp;{ &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTest&nbsp;+=&nbsp;i+</span><span class="string">&quot;-&quot;</span><span>; &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span class="keyword">else</span><span>&nbsp;{ &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sTest&nbsp;+=&nbsp;i; &nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span> </li><li><span>} &nbsp;&nbsp;</span> </li></ol></div>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/104513#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>Tue, 24 Jul 2007 00:13:00 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/104513</link>
        <guid>http://songofhawk.javaeye.com/blog/104513</guid>
      </item>
      <item>
        <title>Javascript高级程序设计 阅读笔记（3）</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/101329" style="color:red;">http://songofhawk.javaeye.com/blog/101329</a>&nbsp;
          发表时间: 2007年07月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <h3>基础</h3><h4>运算符</h4><h5>void</h5><p>以前从来没用到过的运算符，它的好处是总返回undefined，这样当在超链接中调用的时候，就不会导致当前页面的重定向。例如：<span style="font-family: Arial">href=&quot;javascript:void(window.open('about blank'))&quot; （这当然是a标签的一个属性，不过直接写html代码会被当作一个真的超链接，只好这么写了）</span></p><h5>位运算</h5><p><span style="font-family: Arial"><br />js也支持位运算，当然很少会遇到，我只在Walter Zorn Graphic library里见到过。这是一个很牛的JS库，完全不借助任何插件实现跨浏览器的矢量图绘制，其中大量使用了位运算来提高性能。</span></p><p><span style="font-family: Arial">位运算符包括：与（&amp;），或（|），非（~），异或（^），左移（&lt;&lt;），有符号右移（&gt;&gt;），无符号右移（&gt;&gt;&gt;）</span></p><h5>逻辑运算符</h5><p><span style="font-family: Arial"><br />逻辑运算符本身很常见，需要注意的是哪些值会被自动转换为逻辑上的true or false：</span></p><p><span style="font-family: Arial">true：对象；除0以外的任何数字</span></p><p><span style="font-family: Arial">false：数字0；undefined；null；NaN<br /></span></p><span><p><span style="font-family: Arial">书中有个小bug：认为对undefined的变量进行逻辑非（!）运算会出错，实际上，只有该变量根本没有声明的情况下，才会出错。</span></p><h5>关系运算符</h5><p><span style="font-family: Arial">关系运算符包括大于（&gt;），小于（&lt;），大于等于（&gt;=），小于等于（&lt;=）。用于比较数字时，它们的结果都没有什么疑问，不过用于比较字符串的话，就要注意大小写的问题。</span></p><p><span style="font-family: Arial">比如：alert(&quot;Brick&quot;&lt;&quot;alphabet&quot;)就会显示true。这时因为大写字母的编码总是小于小写字母；另外，alert(&quot;23&quot;&lt;&quot;3&quot;)也显示true。不过，当混合比较字符串和数字的时候，js总是把字符串转换成数字，一般情况下，这样的结果比较合理，比如alert(&quot;23&quot;&lt;3)显示false。</span></p><span style="font-family: Arial"><p><span style="font-family: Arial">全等号（===）和非全等（!==）也是很少用到的运算符，不过当不想让js自作聪明地做类型转换的时候还是很有用的。</span></p></span></span>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/101329#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, 15 Jul 2007 22:40:00 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/101329</link>
        <guid>http://songofhawk.javaeye.com/blog/101329</guid>
      </item>
      <item>
        <title>Javascript高级程序设计 阅读笔记（2）</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/96554" style="color:red;">http://songofhawk.javaeye.com/blog/96554</a>&nbsp;
          发表时间: 2007年07月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>这篇本来早就该写了，一个是自己懒，另一个是上周javaeye网站好像有点问题，每次保存都丢一半文字，也不报错，搞得我郁闷之极。</p><h4>基础</h4><ul><li><strong>null</strong>：表示尚未存在的对象，注意，尽管尚未存在，也是个对象啊，所以用typeof检测一个null值变量的结果是Object；不过，为了便于写if语句，在js中，&quot;undefined==false&quot;, &quot;null=false&quot;, 因此，&quot;undefined==null&quot;。 </li><li><strong>整数</strong>：最容易犯的错误就是，忘了070其实是个八进制数，相当于十进制的56； </li><li><strong>浮点数</strong>：&ldquo;在进行运算之前，真正存储的是字符串&rdquo;&mdash;&mdash;这应该是解释执行的本质决定的吧&mdash;&mdash;直接后果是，alert(0.8)这样的语句可以正确输出，而alert(2*0.8)的输出就成了&quot;2.40000000000000003&quot; </li><li><strong>数字边界</strong>：数字有几个边界值，分别是Number.MAX_VALUE(最大值), Number.MIN_VALUE(最小值), Number.POSITIVE_INFINITY(正无穷), Number.NEGATIVE_INFINITY(负无穷), Infinity(无穷大，-Infinity，这个有点莫名其妙，不知道为啥又搞出一套)；特别地，还有一个isFinit(iNumber)函数来判断数字是否为无穷大。 </li><li><strong>NaN</strong>：一些需要数字作为参数的函数，当传入的实参无法转换为数字时，往往会返回这个值；关于NaN，最重要的就是要记住NaN!=NaN，因此判断一个变量是否为NaN，一定要使用isNaN(var)函数。 </li><li><strong>将字符串转换为数字</strong>：sVar.parseInt()是最常用的函数，也最容易出错，为了保险起见，最好每次调用的时候，都加上&ldquo;进制&rdquo;的参数，比如：a.parseInt(10)，就制定了按十进制转换字符串a；Number(sVar)也是一种转换方式，不同的是，它要求整个字符串都得是有效数字，因此Number(&quot;4.5.5&quot;)将返回NaN； </li><li><span style="font-family: Arial"><strong>判断变量类型</strong>：一般情况下，可以先用typeof 运算符，如果结果是&quot;object&quot;，再用instanceof来判断；奇怪的是，不知道是ECMAScript标准的问题还是IE实现的问题，instanceof不认为原始类型值的变量是对象，而使用constructor属性似乎可以应付所有类型的变量，如下：</span> </li></ul><div class="code_title">js 代码</div><div class="dp-highlighter"><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;temp=</span><span class="string">&quot;a&nbsp;string&nbsp;for&nbsp;test&quot;</span><span>; &nbsp;&nbsp;</span></span> </li><li><span class="comment">//下面这句返回&quot;string&quot; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span>alert(&nbsp;</span><span class="keyword">typeof</span><span>&nbsp;temp); &nbsp;&nbsp;</span> </li><li><span class="comment">//下面这句返回&quot;false&quot; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span>alert(temp&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;String); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//下面这句就回返&quot;true&quot;了 </span><span>&nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;temp2=</span><span class="keyword">new</span><span>&nbsp;String(</span><span class="string">&quot;another&nbsp;new&nbsp;string&quot;</span><span>); &nbsp;&nbsp;</span> </li><li class="alt"><span>alert(temp2&nbsp;</span><span class="keyword">instanceof</span><span>&nbsp;String); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//constructor属性是很好的替代品 </span><span>&nbsp;&nbsp;</span> </li><li><span class="comment">//下面这句返回&quot;true&quot; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span>alert(temp.constructor==String); &nbsp;&nbsp;</span> </li></ol></div>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/96554#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, 09 Jul 2007 00:44:00 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/96554</link>
        <guid>http://songofhawk.javaeye.com/blog/96554</guid>
      </item>
      <item>
        <title>Javascript高级程序设计 阅读笔记（1）</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/94381" style="color:red;">http://songofhawk.javaeye.com/blog/94381</a>&nbsp;
          发表时间: 2007年06月26日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-family: Arial">《Javascript高级程序设计》（Professional JavaScript for Web Developers），一本好书，非常适合做Web客户端开发的入门教材。</span></p><p>现在开发程序和以前有了很大不同，碰到新技术，都是先google一些sample code，然后照葫芦画瓢，就写起代码来了。尽管这不利于对技术的全面把握，却也是不得已的事情（哪个项目有时间等你慢慢由浅入深呢）。不过，等用了一段时间，会慢慢发现经常困扰自己的都是些基础问题，这时，就应该抽空读读书，梳理一下头脑中零散的知识了。所选的书既要全面系统地介绍相关知识，又要与实践充分结合。《Javascript高级程序设计》正是这样一本书。（怎么感觉像广告，呵呵）</p><p>下面记录一些阅读的收获，它们或者帮我弥补了知识的不足，或者印证了实践的手段，还有一些为以后进一步深入铺平了道路。</p><h4>渊源</h4><ul><li>Javascript的鼻祖是C--，哈，有趣的名字，本想表达简洁的含义，可惜程序员们未必领情 </li><li>Javascript诞生于Netscape，时过境迁啊 </li><li>Javascript的语言核心标准为ECMAScript，它还有个大名鼎鼎的同胞兄弟，Flash中的ActionScript </li><li>DOM也是不可或缺的一部分， </li><li>BOM也是，尽管很不标准，有些功能还非它不可 </li></ul><h4>基础</h4><ul><li>String类型的变量是被存放在栈（stack）里的，够惊人吧，可惜没说清到底是怎么实现的 </li></ul><p>&nbsp;</p><ul><li>undefined值不等同于未声明的值，不好理解吗，就是这样 </li></ul><p>&nbsp;</p><div class="code_title">js 代码</div><div class="dp-highlighter"><ol class="dp-c"><li class="alt"><span><span class="keyword">var</span><span>&nbsp;temp; &nbsp;&nbsp;</span></span></li><li><span class="comment">//temp已经声明,所以下面会显示true </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span class="keyword">if</span><span>&nbsp;(temp==undefined)&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span class="string">&quot;true&quot;</span><span>); &nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp; &nbsp;&nbsp;</span></li><li><span class="comment">//temp2还没有声明,所以下面会引发一个脚本错误 </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span class="keyword">if</span><span>&nbsp;(temp2==undefined)&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;alert(</span><span class="string">&quot;true&quot;</span><span>); &nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp; &nbsp;&nbsp;</span></li><li><span class="comment">//不过,typeof运算符却不会区分它们的差别, </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span class="comment">//下面的代码如果运行,都会显示&quot;undefined&quot; </span><span>&nbsp;&nbsp;</span></li><li><span class="comment">//不过,由于上面的脚本错误,这两句永远也不会运行了 </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span>alert(</span><span class="keyword">typeof</span><span>&nbsp;temp); &nbsp;&nbsp;</span></li><li><span>alert(</span><span class="keyword">typeof</span><span>&nbsp;temp2); &nbsp;&nbsp;</span></li></ol></div>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/94381#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>Tue, 26 Jun 2007 23:03:00 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/94381</link>
        <guid>http://songofhawk.javaeye.com/blog/94381</guid>
      </item>
      <item>
        <title>Javascipt中精确小数运算的实现</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/78941" style="color:red;">http://songofhawk.javaeye.com/blog/78941</a>&nbsp;
          发表时间: 2007年05月11日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p><span style="font-family: Arial">基于Web的应用程序，经常需要在页面中作些简单的计算，用作数据提交前的验证，或者给用户提供更友好的信息。但由于十进制小数并不总能用二进制小数精确表示，在进行小数运算时，经常会出现&ldquo;莫明其妙&rdquo;的误差，比如&ldquo;33*2.46=81.179999999999999&rdquo;之类的。如果要在页面上显示计算结果，特别是当这个结果表示金额的时候，误差通常是不可容忍的。</span></p><p><span style="font-family: Arial">网上有人说Javasript不能做精确运算，所以会出现误差云云。这当然是不对的，这种情况应该是由计算机二进制表示的本质决定的。应该说，Javascript的表现其实还好一些，因为在数字进行运算之前，我们总是可以得到它的精确表示（字符串）。</span></p><p><span style="font-family: Arial">解决问题的基本思路就是牺牲速度换精度，逐位进行运算，并且自己在程序逻辑中实现进位。为此，Java提供了BigDecimal类。而在Javascript中，我们就没这么幸运了，没有现成的类库可供使用。可能是制订规范的人也认为没必要使用JS来做&ldquo;科学计算&rdquo;吧。</span></p><p><span style="font-family: Arial">我以前做的项目中，经常会碰到计算金额总价、合计、总计之类的&ldquo;商业计算&rdquo;，对精确小数运算的需求还是比较迫切的，所以自己开发了一个小数运算的&ldquo;类&rdquo;。实现这个类的时候，使用了投机取巧的办法：把小数转换为整数，运算完成后，再转换回去。它唯一能解决的问题就是：避免十进制小数和二进制小数之间的转换误差；它不能提高运算的精度（有效数字），也不能扩大数字的表示范围。</span></p><p><span style="font-family: Arial">使用方法如下：</span></p><span style="font-family: Arial"><div class="code_title">js 代码</div><div class="dp-highlighter"><ol class="dp-c"><li class="alt"><span><span class="comment">//使用数字的literal表示，创建一个Decimal对象&nbsp; </span><span>&nbsp;&nbsp;</span></span> </li><li><span class="keyword">var</span><span>&nbsp;d1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Decimal(3.68);&nbsp; &nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//调用该对象的四则运算方法，得到一个新的Decimal对象 </span><span>&nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;res=d1.add(2.25);&nbsp; &nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//调用该对象的valueOf方法，得到数值 </span><span>&nbsp;&nbsp;</span> </li><li><span>alert(&nbsp;res.valueOf()&nbsp;);&nbsp;</span><span class="comment">//显示&nbsp;5.93&nbsp; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="comment">//或者调用该对象的toString方法，得到数值的字符串表示 </span><span>&nbsp;&nbsp;</span> </li><li><span>alert(&nbsp;res.toString()&nbsp;);&nbsp;</span><span class="comment">//显示&nbsp;5.93&nbsp; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span>&nbsp;&nbsp;</span> </li><li><span class="comment">//可用的运算方法对应四则运算的＋、－、&times;、&divide; </span><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="keyword">var</span><span>&nbsp;d1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Decimal(3.68); &nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;res=d1.add(2.25); &nbsp;&nbsp;</span> </li><li class="alt"><span>assertEquals(</span><span class="string">&quot;3.68+2.25&quot;</span><span>,&nbsp;</span><span class="string">&quot;5.93&quot;</span><span>,&nbsp;res.toString()); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="keyword">var</span><span>&nbsp;d1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Decimal(3.68); &nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;res=d1.minus(2.25); &nbsp;&nbsp;</span> </li><li class="alt"><span>assertEquals(</span><span class="string">&quot;3.68-2.25&quot;</span><span>,&nbsp;</span><span class="string">&quot;1.43&quot;</span><span>,&nbsp;res.toString()); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="keyword">var</span><span>&nbsp;d1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Decimal(2.22); &nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;res=d1.multiply(3.33); &nbsp;&nbsp;</span> </li><li class="alt"><span>assertEquals(</span><span class="string">&quot;2.22*3.33&quot;</span><span>,&nbsp;7.3926,&nbsp;res.valueOf()); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li><li class="alt"><span class="keyword">var</span><span>&nbsp;d1&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Decimal(6.66); &nbsp;&nbsp;</span> </li><li><span class="keyword">var</span><span>&nbsp;res=d1.divide(2.22); &nbsp;&nbsp;</span> </li><li class="alt"><span>assertEquals(</span><span class="string">&quot;6.66/2.22&quot;</span><span>,&nbsp;3,&nbsp;res.valueOf()); &nbsp;&nbsp;</span> </li><li><span>&nbsp;&nbsp;</span> </li></ol></div></span>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/78941#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, 11 May 2007 18:27:07 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/78941</link>
        <guid>http://songofhawk.javaeye.com/blog/78941</guid>
      </item>
      <item>
        <title>Date对象扩展</title>
        <author>songofhawk</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://songofhawk.javaeye.com">songofhawk</a>&nbsp;
          链接：<a href="http://songofhawk.javaeye.com/blog/69745" style="color:red;">http://songofhawk.javaeye.com/blog/69745</a>&nbsp;
          发表时间: 2007年04月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <p>近期做了一个POC，需要在浏览器端做一些日期的处理工作，除去其中跟公司产品相关的部分，其它的代码还是比较通用的，主要有两个功能：</p><ol><li>根据一个Date对象获取相对应的特殊时间点，比如一天、一个月或者一年的起止时间；</li><li>在一个Date对象上加减相应的时间值</li></ol><div class="code_title">js 代码</div><div class="dp-highlighter"><ol class="dp-c"><li class="alt"><span><span class="comment">/** </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;This&nbsp;file&nbsp;is&nbsp;a&nbsp;Date&nbsp;extension&nbsp;which&nbsp;can&nbsp;handle&nbsp;specified&nbsp;moments </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp; </span>&nbsp;</span></li><li><span></span></li><li class="alt"><span><span class="comment">/** </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;set&nbsp;the&nbsp;Date&nbsp;object&nbsp;to&nbsp;a&nbsp;specific&nbsp;local&nbsp;moment </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{enum}&nbsp;iMoment&nbsp;the&nbsp;specific&nbsp;moment,&nbsp;can&nbsp;reference&nbsp;those&nbsp;extened&nbsp;properties&nbsp;of&nbsp;Date. </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>Date.prototype.setToLocalMoment=</span><span class="keyword">function</span><span>(iMoment) &nbsp;&nbsp;</span></li><li><span>{ &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">switch</span><span>&nbsp;(iMoment)&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_DATE_START: &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(0,0,0,0); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_DATE_END: &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(23,59,59,999); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_MONTH_START: &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(0,0,0,0); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setDate(1); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_MONTH_END: &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(23,59,59,999); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//can&nbsp;not&nbsp;get&nbsp;the&nbsp;last&nbsp;day&nbsp;of&nbsp;a&nbsp;month&nbsp;directly, </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//so&nbsp;set&nbsp;to&nbsp;the&nbsp;first&nbsp;day&nbsp;in&nbsp;next&nbsp;month,&nbsp;and&nbsp;minus&nbsp;one&nbsp;day. </span><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//numDate&nbsp;is&nbsp;start&nbsp;from&nbsp;1,&nbsp;so&nbsp;0&nbsp;means&nbsp;the&nbsp;last&nbsp;day&nbsp;before&nbsp;1st&nbsp; </span><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setMonth(</span><span class="keyword">this</span><span>.getMonth()+1,&nbsp;0); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_YEAR_START: &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(0,0,0,0); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//numMonth&nbsp;is&nbsp;start&nbsp;from&nbsp;0,&nbsp;to&nbsp;11,&nbsp;but&nbsp;numDate&nbsp;is&nbsp;from&nbsp;1&nbsp;to&nbsp;31,&nbsp;weird&nbsp; </span><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setMonth(0,&nbsp;1); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">case</span><span>&nbsp;Date.MOMENT_YEAR_END: &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setHours(23,59,59,999); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">this</span><span>.setMonth(11,&nbsp;31); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">break</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">default</span><span>: &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;</span></li><li><span>} &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span class="comment">/** </span>&nbsp;</li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;plus&nbsp;the&nbsp;specific&nbsp;values&nbsp;to&nbsp;this&nbsp;Date&nbsp;object </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;All&nbsp;parameters&nbsp;are&nbsp;optional,&nbsp;if&nbsp;one&nbsp;of&nbsp;them&nbsp;is&nbsp;positive,&nbsp;it's&nbsp;plused,&nbsp;otherwise,&nbsp;it's&nbsp;minused.&nbsp; </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iYear </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iMonth </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iDate </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iHours </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iMinutes </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iSeconds </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*&nbsp;@param&nbsp;{int}&nbsp;iMilliseconds </span>&nbsp;</span></li><li><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>Date.prototype.plus=</span><span class="keyword">function</span><span>(iYear,iMonth,iDate,iHours,iMinutes,iSeconds,iMs) &nbsp;&nbsp;</span></li><li><span>{ &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilYear=</span><span class="keyword">this</span><span>.getFullYear();&nbsp;ilYear+=iYear?iYear:0; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilMonth=</span><span class="keyword">this</span><span>.getMonth();&nbsp;ilMonth+=iMonth?iMonth:0; &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilDate=</span><span class="keyword">this</span><span>.getDate();&nbsp;ilDate+=iDate?iDate:0; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilHours=</span><span class="keyword">this</span><span>.getHours();&nbsp;ilHours+=iHours?iHours:0; &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilMinutes=</span><span class="keyword">this</span><span>.getMinutes();&nbsp;ilMinutes+=iMinutes?iMinutes:0; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilSeconds=</span><span class="keyword">this</span><span>.getSeconds();&nbsp;ilSeconds+=iSeconds?iSeconds:0; &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;ilMs=</span><span class="keyword">this</span><span>.getMilliseconds();&nbsp;ilMs+=iMs?iMs:0; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">var</span><span>&nbsp;date=</span><span class="keyword">new</span><span>&nbsp;Date(); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;date.setFullYear(ilYear,&nbsp;ilMonth,&nbsp;ilDate); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;date.setHours(ilHours,ilMinutes,&nbsp;ilSeconds,ilMs); &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;date; &nbsp;&nbsp;</span></li><li><span>} &nbsp;&nbsp;</span></li><li class="alt"><span>Date.prototype.minus=</span><span class="keyword">function</span><span>(iYear,iMonth,iDate,iHours,iMinutes,iSeconds,iMs) &nbsp;&nbsp;</span></li><li><span>{ &nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">this</span><span>.plus(-iYear,-iMonth,-iDate,-iHours,-iMinutes,-iSeconds,-iMs); &nbsp;&nbsp;</span></li><li><span>} &nbsp;&nbsp;</span></li><li class="alt"><span class="comment">/** </span>&nbsp;</li><li><span><span class="comment">&nbsp;*&nbsp;extened&nbsp;properties&nbsp;of&nbsp;Date:&nbsp;to&nbsp;define&nbsp;a&nbsp;set&nbsp;of&nbsp;special&nbsp;moment&nbsp; </span>&nbsp;</span></li><li class="alt"><span><span class="comment">&nbsp;*/</span><span>&nbsp;&nbsp;</span></span></li><li><span>Date.MOMENT_DATE_START=100; &nbsp;&nbsp;</span></li><li class="alt"><span>Date.MOMENT_DATE_END=101; &nbsp;&nbsp;</span></li><li><span>Date.MOMENT_MONTH_START=110; &nbsp;&nbsp;</span></li><li class="alt"><span>Date.MOMENT_MONTH_END=111; &nbsp;&nbsp;</span></li><li><span>Date.MOMENT_YEAR_START=120; &nbsp;&nbsp;</span></li><li class="alt"><span>Date.MOMENT_YEAR_END=121; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li></ol></div>
          <br/>
          <span style="color:red;">
            <a href="http://songofhawk.javaeye.com/blog/69745#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, 10 Apr 2007 22:30:19 +0800</pubDate>
        <link>http://songofhawk.javaeye.com/blog/69745</link>
        <guid>http://songofhawk.javaeye.com/blog/69745</guid>
      </item>
  </channel>
</rss>