Extjs實作繼承的函數是一個很核心的函數Ext.extend,extend方法有兩個重構版本,第一個接受兩個參數,第一個是extend( Function superclass, Object overrides ) ,第二個是extend( Function subclass, Function superclass,Object overrides ) : Function,第二個版本是在subclass的基礎上。 superclass就是超類別的建構函數,overrides是一個對象,裡邊的屬性就是要覆寫父類別的屬性。繼承了父類別的子類別具有父類別的prototype中的所有方法。而子類別可以覆寫父類別的方法(override),更進一步,子類別的每個物件也可以覆寫父類別的方法。其實我覺得這個函數沒什麼作用,修改prototype的效果是等效的,當然,extjs的目的肯定是要把prototype這個神奇的東西完全屏蔽起來,使程式設計師能夠像處理其他語言一樣來處理Javascript。當然,即使如此,它的繼承和一般的繼承還是有些不同的,下面先看個例子,準備好一個Person類別:
Person = function(name) { this.name = name; this.fn = function() { alert('I am a person') }; } Person.prototype.print=function(){ alert('I am a person');} Person.prototype.showAge = function() { alert('I am older than 0'); } Person.prototype.showName = function() { alert('Show Name:'+this.name) }; var per = new Person('Tom'); per.showName();子类:Student = function(id) { this.id = id; } Student.prototype.showID = function() { alert(this.id); } //子类的方法
繼承:
Ext.extend(Student, Person);
stu.showName(); !!沒有結果! stu沒有name的定義stu.fn(); !!沒有結果stu.showID(); !!!還是沒有結果到此我們已經發現了一些不同:在父類的構造函數中的內容是不會繼承的,父類別的建構子不會被調用,子類別(prototype中)已有的方法也會遺失!繼續看下去,將Ext.extend下面的程式碼替換成:
var stu = new Student('01'); Student.override({ print: function() { alert('I am a student'); } }); stu.override({ print: function() { alert('I am a bad student,but I won\'t affect others'); } }); stu.print(); stu.showAge(); var stu2 = new Student(); stu2.print();
這裡的函數都能夠如預期輸出,showAge是執行的父類別的方法,stu.print是執行的stu.override中指定的方法,而stu2執行的是Student.override中指定的方法。到這裡,我們已經大概能猜出extend是如何實現的了。下面看它真正的原始碼,這個方法位於Ext.js中,程式碼和註解如下:extend : function(){
// inline overrides var io = function(o){ //注意这个方法的this,仅看这里并不知道这个this是什么,下面这个io会被赋值给sbp.override,也就是子类的prototype for(var m in o){ //从而每个子类的对象的override都会指向这个方法,如果子类对象调用了override,那么这个this就是子类的对象了。也就是 this[m] = o[m]; //上面的例子中stu.override表现出来的效果,仅对当前对象有效。从这里可以看出,override不仅仅是传统意义上的覆盖,完全也可以 } //用来添加新方法。 }; var oc = Object.prototype.constructor; return function(sb, sp, overrides){ if(Ext.isObject(sp)){ //是在检测当前使用的是哪个版本的重构函数。如果sp实际上是overrides,就做些替换工作,让变量的实际意义和名称相符合。 overrides = sp; sp = sb; sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; //这个没看懂…… } var F = function(){}, sbp, spp = sp.prototype; F.prototype = spp; //F是父类的一个“干净”拷贝,所谓干净,是指它不会把父类中在构造函数内部定义的属性带过来。 //例如 Person=function() // {this.privateFn=new function{ some code goes here}} //那么这个privateFn对子类是不可见的,所以在构造函数中利用this定义的属性都相当于是类的私有变量。 sbp = sb.prototype = new F(); //将子类的prototype设置为父类的prototype,继承的核心步骤。 sbp.constructor=sb; //设置正确的构造函数指向,见 JavaScript继承详解 sb.superclass=spp; //设置父类 if(spp.constructor == oc){ //没看懂……,这个是干嘛用的?望高人指点 spp.constructor=sp; } sb.override = function(o){ //子类的重写方法,这个重写方法是函数的重写方法。它修改的是prototype。 Ext.override(sb, o); //见最后。 }; sbp.superclass = sbp.supr = (function(){ //设置原型的父类 return spp; }); sbp.override = io; //给子类的prototype提供override方法,这样单个实体也可以覆盖,它修改的是实体对象。注意和上面的sb的override区分。 Ext.override(sb, overrides); //重写 sb.extend = function(o){return Ext.extend(sb, o);}; //给子类提供extend方法,以实现多重继承 return sb; //返回子类。 }; }();
下面是Ext.override的程式碼,比較明了的,和那個inline override相較,它就是修改後的prototype:override :
function(origclass, overrides){ if(overrides){ var p = origclass.prototype; Ext.apply(p, overrides); if(Ext.isIE && overrides.hasOwnProperty('toString')){ // 这个是什么?IE的特殊点? p.toString = overrides.toString; } } }
現在就可以開始正式介紹Extjs的事件模型了。和其他語言事件類似,首先要為一個類別定義事件,其他語言(例如C#)的事件一般有一個專門的event類型,event類型實際上可以看作是委託的數組,當然委託實際上是函數,添加時間監聽器(listener),就是想委託數組中加入委託(函數),所謂觸發事件就是把數組中的函數統統執行一遍。 Javascript也是類似的,只是Javascript的函數比那些語言強大靈活的多,因此也不需要什麼event型別了。 Javascript的事件看起來像是字串(它內部應該也是保留了一個陣列的),可以透過Observale.addEvents方法加入事件,透過Observale.fireEvent觸發事件,透過Observale.addListner增加事件監聽器。以下舉一個沒什麼意義卻能說明問題的例子。
Odder = function(min, max) { this.min = min; this.max = max; this.addEvents('onFindOdd'); } Ext.extend(Odder, Ext.util.Observable, { run: function() { for (var i = this.min; i < this.max; i++) { if (i % 2 != 0) { this.fireEvent('onFindOdd',i); } } } }); var p = new Odder(4, 8); p.addListener('onFindOdd',function(n){alert(n);}); p.run();
Odder是這麼一個類,它透過一個建構函數傳入一個範圍,然後尋找這個範圍內的所有奇數,每找到一個就觸發一個事件。給它加一個事件處理程序,把它找到的奇數alert出來。 要注意,這裡的事件處理程序的參數只能靠程式設計師自己保持一致,它不像委託那樣強型別。
以上是javascript如何實作extjs事件的原理實例詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!