首先說明這不是一篇完整解讀ExtJS和jQuery所有方面差異的文章,只是針對我個人剛看了兩天的jQuery產生的一些疑問的整理。之前用過一段時間ExtJS,了解ExtJS的一些機制。現在做移動開發,又選定了jquery mobile,要寫控件,所以需要了解jquery。(不過換工作之后應該不會再用jQuery了,坑估計是短期內填不上了)
1、jQuery是個什么東西?Ext是什么東西?(此處不是指兩個框架,而是指我們在寫程序的時候,經常用到的兩個關鍵字--暫時稱之為關鍵字)
之前用的是ExtJS,Ext是個Object,通過字面量創建的,Ext.js文件里,3.3.1版:
Js代碼4.0版本,此處global == window:
Js代碼既然Ext是個Object,那jQuery是不是也是個Object呢?NO,來分析下源碼,jquery.js:
Js代碼此處大概明白了,jQuery是個Function,并且由于此處調用jQuery的時候,有個return,所以var v = jQuery(xxx)和var v = new jQuery(xxx)調用后,v都是同一個函數的實例。在《javaScript高級程序設計》第18章第一節有提到過這種技巧,叫做作用域安全的構造函數,不過書上提到的形式稍有差異:
Js代碼這樣var p = Person('a',21)和var p = new Person('a',21) ,p就都是Person實例了,如果去掉if判斷和else后邊的內容,第一種調用p是undefined。
在jquery.js最后,把變量jQuery賦值給了$,后續可以通過$這種簡寫使用jQuery,算是一個簡寫的別名吧:
Js代碼此處先挖個坑,構造函數中(如此處的Person)的this到底怎么理解?
2、jQuery和Ext在這兩個關鍵字都怎么使用的,有何異同?
2.1、Ext是個對象,是一個命名空間,跟java里頭的package類似,使用Ext下邊的方法、Function/類的時候,就像使用一個對象的屬性一樣,如工具方法Ext.apply、Ext.applyIf可以直接調用,構造函數Ext.json.DataStore,前邊加new創建實例。關于這么做的好處,了解java package的好處的都知道那么一些吧,我只還記得避免命名沖突。
2.2、jQuery首先是個Function,既然是個Function,那個就可以new,可以像Function一樣調用,以下將解析幾種jQuery調用方法的源碼:
jQuery(xxx)的時候,轉調到
Js代碼具體調用時候就需要分析jQuery.PRototype.init函數了。
2.2.1、jQuery(function(){}),當傳入是function的時候,init方法片段:
Js代碼此處rootjQuery默認又等于jQuery(document);ready實際上就是在為document注冊load事件,源碼:
Js代碼bindReady方法是通過attachEvent/addEventListener為document注冊了load事件。
Java代碼2.2.2、jQuery(DOMElement)當傳入參數是一dom element的時候,init方法片段:
Js代碼把dom元素放到了new出來的init對象上,此處this應該是一個對象,應該是個Object的,但是從Chrome調試看,此時this竟然顯示為jQuery.fn.jQuery.init[0],Object.prototype.toString.call(this)結果是”[object Object]”,是個對象,為何顯示這么奇怪呢?在FF里,this顯示為[],按照道理說,對象應該不會這么顯示的才對。
此處把元素賦值為this[0]可以在后續訪問元素的時候,直接用返回實例的[0]來訪問,如果是多個元素,則可以用下標一個個的訪問,后邊看到selector的時候會看到。同時由于后邊把init的原型指向了jQuery的原型,所以這里this的原型方法都是jQuery.prototype的方法:
Js代碼挖坑,關于原型方法,實例的關系。
2.2.3、如果傳入是body,jQuery(“body”),返回只有一個body元素
Js代碼2.2.4、jQuery(selector),如jquery.mobile.js中initializePage中$(“:jqmData(role=’page’)”)
Js代碼如果傳入的context為空,就從當前對象查找find(selector)否則就從rootjQuery查找,這里rootjQuery是個實力,所以此方法調用就是調用的原型上的find方法:
Js代碼此處又調用到了jQuery.find方法,注意,jQuery是一個Function,這個find跟rootjQuery不同,jQuery.find是function的一個屬性,非嚴格意義上可以簡單的認為類似于java的靜態方法。此find方法實則是Sizzle本身:
jQuery.find = Sizzle;
具體實現還要看selector的內容,可能是getTagByName或者querySelectorAll,如getTagByName(‘name’)、querySelectorAll(“[data-role=’page’]”)。
2.2.5、jQuery()如果傳入為空,則返回不包含元素的jQuery對象:
Js代碼2.2.6、jQuery(jQuery()),也就是傳一個jQuery實例進去,會創建一個新對象,然后把老對象的內容拷貝到新對象里頭。
綜上,jQuery()返回的是一個jQuery.prototype.init函數的實例,但是由于這個函數的原型指向了jQuery函數的原型,jQuery.prototype上的方法也可以直接在這個實例上調用。同時jQuery會被當成一個數組來使用,根據下標索引提取滿足參數的dom元素。
2.3、jQuery接著:-)也起到命名空間的作用。
雖然jQuery是個function,但是可以在function上添加屬性(這么叫準確么?)然后就可以直接jQuery.method()、jQuery.filed的調了。這里jQuery至少起到了一個命名空間的作用。
既然說到命名空間了,就不得不說jQuery的原型和function的方法,jQuery.method()類似靜態方法,可以通過
Js代碼兩種方法來添加。原型方法則通過jQuery.fn.extend / jQuery.prototype.extend來添加。
3、jQuery和Ext都怎么實現繼承的,有什么異同?各有什么優勢?
Javascript是一門基于對象的語言,但不是面向對象,也就是說語言層面沒有提供繼承的語法,但是可以通過應用層面實現繼承。由于把這種實現放到了應用層面,所以實現就變得五花八門了,可以通過拷貝、原型鏈等。了解兩種繼承的調用方式對理解下邊說到的實現原理是很有幫助的。
3.1、Ext(3.x)的繼承跟《JavaScript高級程序設計》里講到的寄生組
新聞熱點
疑難解答