Prototype使用學習手冊指南之base.js

文章出處:http://www.ijavascript.cn/prototype/manual-notes-for-prototype-base.js-32.html


一看名字就知道Class是基類了,先說下此類的作用,然後給大家細細的分析下base.js中的代碼
類的創建與繼承:

Class.create(): 創建一個類,例如 person=Class.create()

Object.extend(destination, source): 把source中方法屬性copy到destination(使用for propertyin source),需要注意的是,javascript中除了基本類型(Number, Boolean)外都是引用類型,所以這種copy一般只是copy引用而已,destination和source還是指向同一個方法或對象屬性(function array object)

這面向對象的編程中,一般通過Class.create新建一個類,如果這個類繼承於領一個類,一般使用Object.extend(class.prototype, parentClass.prototype)或者Object.extend(class.prototype, aparentClassInstance)

Object構造函數的擴展:

Object是其他對象實例的構造函數(var a=new Object()),也是所有其他類的父類,對Object直接擴展(注意不是擴展Object.prototype,擴展Object.prototype相當於添加實例方法)相當於爲Object類添加靜態方法

Object.inspect(object): 調用object的inspect(如果定義了)或toString方法,返回一個對象的字符串表示

Object.keys(object): 返回一個對象的所有屬性和方法名稱組成的數組, 例如Object.keys(document.body)

Object.values(object):返回一個對象的所有屬性和方法的值組成的數組, 例如Object.values(docuement)

Object.clone(object): 返回一個對象的clone版本,其實是執行Object.extent方法把object中的方法屬性copy到一個新對象中,然後返回這個對象

函數綁定:

定義了Function對象的兩個方法,bind和bindAsEventListener,這兩個方法是一個函數的兩個方法,對於java、c#程序員來說,看到這個也許感到很驚訝,因爲在他們看來函數只是一個程序語句組織結構而已—>怎麼還有方法,而且還可以擴展?

這也是javascript等腳本語言相對於java等一個非常強大的功能,函數也是一個對象,函數名就是這個對象的名稱,只要你願意,你也可以使用new Function(…)來定義函數,所以爲函數定義方法也就很正常不過了

這兩個函數的主要作用是爲了解決使用javascript面向對象風格編程中this的引用問題,在javasctipt中this關鍵字 始終指向調用該函數的對象或者指向使用call,apply方法指定的對象(具體這方面的知識可以自己google一下,以下系列對prototype的介紹也假設讀者對javascript語言比較熟悉了,如果不熟悉可以找本 javascript權威指南這本書看看)

要理解這個問題首先要理解 始終指向這個問題,就是this這個關鍵字比較特殊,不能把他當成一般的變量名看待,最常見的一個錯誤就是在返回函數的調用中使用this,例如return function(){this.aMethod()}, 當你下次調用這個返回的匿名方法時,這個this引用的內容又指向了調用這個函數的對象了,記住的一點的this是個關鍵字,不是變量名,不會產生閉包

對Number的擴展(注意num也可以看成對象,其實是在使用的時候系統自動打包成Number對象):

toColorPart:把數字轉換爲可以用於表示color的16進制值:例如 7.toColorPart()=>”07″,28.toColorPart()=>”1C”

succ: 返回num++, 但不改變num本身的值,其實就是 return this+1

times:對從0到這個數字輪流調用一個函數, 例如function a(n){docuement.write(n)}, 10.times(a), 將顯示012345678910, 注意函數也是一個對象,而且與其他對象並沒有實質的區別

Try對象:

Try對象提供了一個很有趣的功能, 先看一下如下的代碼:
var Ajax = {
  getTransport: function() {
    return Try.these(
      function() {return new XMLHttpRequest()},
      function() {return new ActiveXObject(’Msxml2.XMLHTTP’)},
      function() {return new ActiveXObject(’Microsoft.XMLHTTP’)}
    ) || false;
  }
}
Try對象提供了一個方法these, 這個方法接受一個函數類型的參數列表,然後輪流執行這些函數,當其中一個函數沒有產生錯誤時,就停止執行,並且返回這個函數返回的值,自己慢慢體會吧

PeriodicalExecuter(週期性執行器)對象

這個對象是對setInterval方法的簡單封裝,使用方法如下
var a=new PeriodicalExecuter(callback, frequency) //callback: 執行的函數名 frequency: 每次執行的時間間隔
a.stop()
//一看名字就知道Class是基類了
var Class = {
create: function() {
//this.initialize並沒有定義,但看名字就知道是初始化,arguments傳遞參數
return function() { 
this.initialize.apply(this, arguments);
}
}
}
//抽象類?
var Abstract = new Object();
//爲Object對象添加靜態方法extend,將source的域、方法(對js來說是一回事)拷貝到destination,也就實現了繼承
Object.extend = function(destination, source) {
for (property in source) {
destination[property] = source[property];
}
return destination;
}
//再來一個類方法,這樣調用dest=Object(dest,src)和desc=desc.extend(src)就一樣了
Object.prototype.extend = function(object) {
return Object.extend.apply(this, [this, object]);
}
/*
爲函數類添加bind類方法,應該是對別的對象應用自己,比如ObjectA.someFunction.bind(ObjectB)
補充:這個是prototype的一個核心方法
犀牛書:The first argument to both call( ) and apply( ) is the object on which the function is to be invoked; this //argument becomes the value of the this keyword within the body of the function. 

*/
Function.prototype.bind = function(object) {
var __method = this;
return function() {
__method.apply(object, arguments);
}
}
//同上,這就是經常用到的瀏覽器事件綁定。對於call和apply方法的區別,犀牛書是這麼解釋的:
//The apply( ) method is like the call( ) method, except that the arguments to be passed to the function are specified //as an array,所以基本上就是形式區別。
Function.prototype.bindAsEventListener = function(object) {
var __method = this;
return function(event) {
__method.call(object, event || window.event);
}
}
//返回hex顏色表示,這都想到了哈哈
Number.prototype.toColorPart = function() {
var digits = this.toString(16);
if (this < 16) return '0' + digits;
return digits;
}
//Try類
var Try = {
//就一個方法these,注意到prototype的類定義基本上用的都是對象直接量,應該高手都是這樣寫的吧
//這個方法就是把傳過來的函數一一調用,返回第一個可用的。
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
//lambda估計也是一個和foobar一樣的詞,記得還有一篇rfc是專門講解foo的由來的,哎別人的文化阿
var lambda = arguments[i];
try {
returnValue = lambda();
//如果第i個方法沒有拋異常,這裏就跳出循環了,贊
break;
} catch (e) {}
}
return returnValue;
}
}

/*--------------------------------------------------------------------------*/
//上面這條線是他畫的。。。。

//這裏創建對象就用到了最開始那個,不明白什麼意思,也許這樣比new Object()好看?
//看名字就可以知道,定時執行
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
//到這裏纔看出來Class方法的initialize是怎麼回事,同時也就可以解釋爲什麼不用new Object()而用Class.create()了
//這樣每次new一個對象都可以調用構造函數,厲害
//這裏的兩個參數,一個是回調函數,也就是定時執行的函數,另一個就是頻率了,單位秒
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this.currentlyExecuting = false;
//設置了參數之後調用registerCallback,往下看
this.registerCallback();
},
//調用window對象的setInterval方法,this.onTimerEvent是什麼?往下看。。。
registerCallback: function() {
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
//也就是套了一層殼,加了一個try...finally塊
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try { 
this.currentlyExecuting = true;
this.callback(); 
} finally { 
this.currentlyExecuting = false;
}
}
}
}

/*--------------------------------------------------------------------------*/

//這個名字好奇怪
function $() {
var elements = new Array();
//循環參數
for (var i = 0; i < arguments.length; i++) {
var element = arguments[i];
//ft,原來就是getElementById。。。。這個簡化一般都得做的,但是用這個名字。。。哈哈,有創意
if (typeof element == 'string')
element = document.getElementById(element);
//一個參數的話就不返回數組了
if (arguments.length == 1) 
return element;
//push...照犀牛書的說法,低版本ie應該不支持吧?
//Availability
//JavaScript 1.2; JScript 5.5; ECMAScript v3 
elements.push(element);
}
return elements;
}
TAG: prototype指南 prototype教程 
kimi post in Prototype框架 at 2007-09-08 17:31:04. 
永久地址:http://www.ijavascript.cn/prototype/manual-notes-for-prototype-base.js-32.html 
在百度中搜索《Prototype使用學習手冊指南之base.js》。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章