<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>geradle</title>
    <description></description>
    <link>http://geradle.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>prototype 1.5 RC2 $ 函数的解读</title>
        <author>geradle</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://geradle.javaeye.com">geradle</a>&nbsp;
          链接：<a href="http://geradle.javaeye.com/blog/38862" style="color:red;">http://geradle.javaeye.com/blog/38862</a>&nbsp;
          发表时间: 2006年12月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          最近闲的无聊，跟人打赌，看看能不能在一天时间内里面把prototype 1.5的 $函数读懂，赚顿饭吃吃，下面把理解贴出来，让大家看看算不算读懂了。<br />首先把想关代码贴一下。<br /><pre name="code" class="java">
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i &lt; length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return Element.extend(element);
}

if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element) return;
  if (_nativeExtensions || element.nodeType == 3) return element;

  if (!element._extended && element.tagName && element != window) {

    var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
    if (element.tagName == 'FORM')
      Object.extend(methods, Form.Methods);
    if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
      Object.extend(methods, Form.Element.Methods);

    Object.extend(methods, Element.Methods.Simulated);
    for (var property in methods) {
      var value = methods[property];
      if (typeof value == 'function' && !(property in element))
        element[property] = cache.findOrStore(value);
    }

  }

  element._extended = true;
  return element;
}

Element.extend.cache = {

  findOrStore: function(value) {

    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
}
Element.Methods = { ...}//代码太多，请参考prototype.js
</pre>下面为我的解读：<br />$函数可以接收多个参数，参数的类型可以为String或者用Element类扩展过的html element。当传入的为多个参数的时候，返回的为一个数组；单个参数为一个扩展过的element 或者null。<br /><br />接下来解读Element.extend(element)成为理解$函数返回对象的关键。Element为一个singleton对象，对其extend方法的理解，我认为难点主要集中于<pre name="code" class="java">element[property] = cache.findOrStore(value);</pre>的理解。这句话将cache.findOrStore返回的函数copy给elememt[property],使其成为element的一个方法。<br />然而这样做完全可以直接将<pre name="code" class="java">function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
</pre>copy给element[property]。<br />为什么还需要通过函数cache.findOrStore这个函数的调用呢。那么这个cache体现在哪里呢，进一步问为什么函数名叫findOrStore呢？<br />那么让我们仔细看看cache.findOrStore这个函数体。<br />该函数返回的是一个function，在返回这个function的时候。<span style="color: red">他首先查看this[value]是否存在，存在则返回this[value],否则新生成一个函数，赋值给this[value]再返回。</span>所以当你第二次调用这个函数的时候，他优先的查看是否this[value]具有值，我想这就是他取名于cache，并教findOrStore的意义吧。<br />接着让我再问一下，this[value]给那个对象动态添加了方法呢？根据JavaScript this关键字的含义，其应该存在于Element.extend.cache这个Object中。<br />BTW:value.apply(null, [this].concat($A(arguments)));中的this，为调用该方法的element。理解这一点是Extend.methods的方法理解的前提。<br />验证方法：你可以在findOrStore方法中增加一行alert(this[value]),当你第一遍使用$函数时他应该全部为undefined，当你第二遍使用的时候其将有值。更为简单的方法为直接alert(this['findOrStore']).<br />总结，Extend.cache充分体现了JS的特性。findOrStore方法设计的实在精妙。this指针真的比较难理解。
          <br/>
          <span style="color:red;">
            <a href="http://geradle.javaeye.com/blog/38862#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, 13 Dec 2006 14:17:19 +0800</pubDate>
        <link>http://geradle.javaeye.com/blog/38862</link>
        <guid>http://geradle.javaeye.com/blog/38862</guid>
      </item>
      <item>
        <title>补发：澄清Python的Open class</title>
        <author>geradle</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://geradle.javaeye.com">geradle</a>&nbsp;
          链接：<a href="http://geradle.javaeye.com/blog/34613" style="color:red;">http://geradle.javaeye.com/blog/34613</a>&nbsp;
          发表时间: 2006年11月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在这里对我在Why not python?这帖子中的一些错误的看法进行澄清，避免造成误导。<br />那个帖子地址为<a href="http://www.javaeye.com/topic/33665?page=1" target="_blank">http://www.javaeye.com/topic/33665?page=1</a><br />下面我把帖子大概描述一下：<br />首先：<br /><div class="quote_title">suninny 写道</div><div class="quote_div">要是Python也具备Closure(Block)的话我绝不会多瞧下Ruby。</div><br />接着：<br /><div class="quote_title">qiezi 写道</div><div class="quote_div"><br />我倒觉得相比起ruby来，python只能算是中规中矩，没多少出彩的地方。<br /><br />ruby我认为最强的地方是可以open一个类，扩充它。另一个强的地方是关键字，ruby的关键字很少，而且很多关键字可以当成方法名来用，限制很少，只要你愿意，可以随意地扩充ruby，把它看成是语言的一部分。<br /></div><br />接着<br /><div class="quote_title">geradle 写道</div><div class="quote_div"><br />Python也具有Open Class 的特色的呀，你也可以实现这样的功能的。 <br /><pre name="code" class="python">
class openclass():   
    def test():   
        print "test"  
open = openclass()   
open.test()   
def test1():   
    print "test1"  
open.test=test1   
open.test()   
</pre><br />还有那个method missing，python也有的。 <br /></div><br />最后<br /><div class="quote_title">charon 写道</div><div class="quote_div"><br />geradle的那个代码更多的是open object methods的功能，而且不像是python的代码，方法的第一个不是self啊 <br />python在open class和open object methods的实现上有非常微妙的差别，主要就是这个self引起的。针对class的修改是含self的（需要声明，但调用时不需要给出，解释器自动添加这个参数），并且影响到这个类所有的对象（包括以前生成的）；对object的属性的赋值是不带self的(解释器不会自动添加self参数)，并且只影响到被修改的对象。 <br />我估计和ruby的区别主要是python中function是first class造成的,而方法是函数的一个特例，从而产生绑定和非绑定的区别。但仔细思考之后，发现这个处理方式是自洽的 <br /></div><br />正是Charon的回复，让我觉得认真的学习一下Python method调用时候的是如何查找method的。结果不看不知道，一看下一跳，原来我原来关于python open class的想法是错误的。为什么是错误的呢？<br />先看看Ruby的Open class是怎么实现的。<div class="quote_title">引用</div><div class="quote_div"><br />Reading further on Ruby's object-oriented features, I found out in Programming Ruby that: <br /><br />Classes are never closed: you can always add methods to an existing class. This applies to the classes you write as well as the standard, built-in classes. All you have to do is open up a class definition for an existing class, and the new contents you specify will be added to whatever's there. <br />As a conseguence, you can always revise a method (changing its semantics) to an existing class no matter where you are. For instance, let consider the following example. <br /></div><br />可以看出Ruby的Open Class是基于声明的。你在类定义的时候就改变了其方法或者Attribute的sematic.<br />然而Python中是在运行时改变的，应该不能成为Open class或者可以叫做Open object:).当然这个称呼是不恰当的。或许有人会居然python可以实现和ruby Open Class一样的功能，为何还要在乎概念呢。<br />有两个理由：<br /><ul><br />Python中实现类似于Ruby Open Class的功能其实是Python把Function做为一等公民的另外一种表现，而不是所谓的Open Class.<br />为了介绍Python中Method与Function的差别，那样就可以更好的说明Charon前面试图说明的东西。<br /></ul><br />Python的Instance Object包含了data attributes  & methods, data attributes好理解，那么Methods呢？Methods是该实例变量的类中定义的Functions.为什么要要强调这个呢？因为在Method和Function的调用过程中存在着以下差别。当你调用Function的时候，Function接受的参数就是你传递的参数。而当你调用Method的时候，实际参数是你传入的参数和instance object的引用，示例代码如下：<br /><pre name="code" class="python">
>>>class method():
       def test(self):
	  print "method"	
>>> m = method()
>>> m.test
&lt;bound method method.test of &lt;__main__.method instance at 0x00B43BC0>>
>>> m.test()
method
>>> method.test
&lt;unbound method method.test>
>>> method.test(m)
method
>>> 
</pre><br />下面再列举一段代码说明Method与Function的差别：<br /><pre name="code" class="python">
>>> def test1():
	print "test1"
>>> test1
&lt;function test1 at 0x00B2FCF0>
>>> m.test=test1
>>> m.test
&lt;function test1 at 0x00B2FCF0>
>>> m.test()
test1
>>> method.test(m)
method
>>> 
</pre><br />为什么上面的<pre name="code" class="python">m.test()</pre>没有出错呢，难得前面提到的Method调用是参数传递规则不对？上面的规则是对的，没有出错因为此处的<pre name="code" class="python">m.test()</pre>调用不是Method的调用，而是Function的调用。<br />为什么说此处是Function的调用而不是Method的调用呢？<br />因为在<pre name="code" class="python">m.test=test1</pre>执行的时候，我们实际上是为instance object m创造了一个data attribute，并把他赋值为function test1.所以<pre name="code" class="python">m.test()</pre>实际为Function的调用！<br />这里还关系到一个python的Method/Function的调用规则：当你通过instance object调用函数或者方法时，Python首先搜索该object的data attribute，再搜索其Class，base class。所以此处为Function调用！这个规则可以参看一篇文章<a href="http://www.informit.com/articles/article.asp?p=28672&seqNum=4&rl=1" target="_blank">http://www.informit.com/articles/article.asp?p=28672&seqNum=4&rl=1</a>
          <br/>
          <span style="color:red;">
            <a href="http://geradle.javaeye.com/blog/34613#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, 16 Nov 2006 17:19:16 +0800</pubDate>
        <link>http://geradle.javaeye.com/blog/34613</link>
        <guid>http://geradle.javaeye.com/blog/34613</guid>
      </item>
  </channel>
</rss>