prototype Element學習筆記(篇一)_prototype

來源:互聯網
上載者:User
先說一下Element對DOM擴充的技術思路,我也是看了一天的代碼,這才有了點心得。
使用prototype,我們最常用的莫過於$('div1')之類的代碼。從而獲得擴充後的element對象,然後,我們就可以用它的各種擴充出來的方法了,如:
$('div1').addClassName('loading').show();
所以,我們研究Element的擴充正應當以此為入口。
function $(element) {
if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i < length; i++)
elements.push($(arguments[i]));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);
}
這個函數一個巧妙的遞迴就可以處理多個參數的情況,實在令我讚歎啊。代碼中的關鍵是:Element.extend(element),在extend之前,element還僅僅是一個普通的DOM對象,extend之後就被擴充了,可見,秘密就在extend之中。
既然是Element.extend(element),那麼,我們當然不能單獨去研究extend,還是得先瞭解一下Element是何物。
(function() {
   var element = this.Element;
   this.Element = function(tagName, attributes) {
     attributes = attributes || { };
     tagName = tagName.toLowerCase();
     var cache = Element.cache;
     if (Prototype.Browser.IE && attributes.name) {
       tagName = ' <' + tagName + ' name="' + attributes.name + '">';
       delete attributes.name;
       return Element.writeAttribute(document.createElement(tagName), attributes);
     }
     if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
     return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
   };
   Object.extend(this.Element, element || { });
}).call(window);
這種代碼比較有個性,基本結構是:(function(){……}).call(window);所以,看到這個結構,就要曉得,省略符號部分出現的this都是指向window的。
var element=this.Element;這行不難理解,但是,關鍵是this.Element這時還沒有被定義。後面則是定義一個類:window.Element類,它有兩個參數:tagName、attributes。它的作用就是建立一個元素,並把一個純潔的指定標籤對應的DOM對象放入緩衝。建立元素後,並且寫入指定的屬性值。這兒要提醒一下:
writeAttribute、readAttribute這兩個函數功能顯然,讀、寫屬性,但是,它的代碼並不簡單啊,它的複雜性主要源於不同的瀏覽器中,讀、寫屬性的方法的不同。
這是Element類的建構函式的定義,它之後的Element.cache = { };緩衝,什麼的緩衝,不大好描述,各種標籤的純潔版DOM元素對象的緩衝?這話說得太噁心了。後面緊跟著就是一個:Element.Methods={……},在這裡,幾乎定義了所有的擴充方法。這裡的擴充方法都有一個特徵,代碼中沒有一個用this的,都是老老實實傳進去一個element引用。這是一個伏筆,為什麼要定義成這樣,是有原因的。且容後交待。
現在Element大概說了一下,就得講一講Element.extend了。
Element.extend = (function() {
   if (Prototype.BrowserFeatures.SpecificElementExtensions)
     return Prototype.K;
  var Methods = { }, ByTag = Element.Methods.ByTag;
  var extend = Object.extend(function(element) {
     if (!element || element._extendedByPrototype ||
     element.nodeType != 1 || element == window) return element;
    var methods = Object.clone(Methods),
     tagName = element.tagName, property, value;
    // extend methods for specific tags
     if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
    for (property in methods) {
       value = methods[property];
       if (Object.isFunction(value) && !(property in element))
         element[property] = value.methodize();
     }
    element._extendedByPrototype = Prototype.emptyFunction;
     return element;
  }, {
      refresh: function() {
       // extend methods for all tags (Safari doesn't need this)
       if (!Prototype.BrowserFeatures.ElementExtensions) {
         Object.extend(Methods, Element.Methods);
         Object.extend(Methods, Element.Methods.Simulated);
       }
     }
   });
  extend.refresh();
   return extend;
})();
第一行的原理我不大肯定,不說,下面的代碼看似複雜,待我抽出它的大概結構來:
var extend=Object.extend(function(element){……},{refresh:function(){……}});
extend內,第一個函數作用是從XXXX.Methods中擷取方法,並複製到本element中。這兒主要基於這樣的考慮:
一、元素如果是一個Form,就得從Form.Methods取方法
二、元素如果是表單內的可輸入元素,就得從Form.Element中取方法
三、所有元素都應當從Element.Methods中取得通用方法(後面的refresh所考慮的)。
也就是說,這兒要考慮多種情況,本來應當是個if語句的事,但是,這兒巧妙地設計了一個Element.Methods.ByTag。從而解決了這個問題。
if (Object.isFunction(value) && !(property in element))
element[property] = value.methodize();
如果Methods中的成員不是函數或者函數在element中已存在,則不會覆蓋。這兒到了關鍵了,那個value.methodize(),這時,前面的伏筆生效了,methodize的作用就是把當前調用者傳遞進方法。且作為第一個參數傳入。它的使用方法一般是:
obj.methodname=functionname.methodize();
這樣,調用時,obj對象就會作為第一個參數傳入functionsname這個函數。
到此為止,這個extend函數中的大概思路應當清晰了,現在還有一個問題沒有清楚:根據元素的tagName來獲得應當從哪個Methods獲得擴充,那麼,我們有必要瞭解一下ByTag的詳情,尋找一下,找到了:
Object.extend(Element.Methods.ByTag, {
"FORM": Object.clone(Form.Methods),
"INPUT": Object.clone(Form.Element.Methods),
"SELECT": Object.clone(Form.Element.Methods),
"TEXTAREA": Object.clone(Form.Element.Methods)
});
ok,差不多就這樣了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.