【jQuery源码】整体架构
jQuery源碼可以精簡為以下內容:
方框上面的代碼根據Jq注釋我們可以知道是對AMD規范的支持。
jQuery整體上被包裹在一個匿名函數中,這個匿名函數再作為另一個匿名函數的參數被傳入,形參factory。
?
一、自調用函數
整個部分被自調用函數包裹,通過定義一個匿名函數,創建了一個“私有”的命名空間,該命名空間的變量和方法,不會破壞全局的命名空間。
自調用函數中的第一個參數相當于window,通過傳入window變量,使得window由全局變量變為局部變量,當在jQuery代碼塊中訪問window時,不需要將作用域鏈回退到頂層作用域,這樣可以更快的訪問window;這還不是關鍵所在,更重要的是,將window作為參數傳入,可以在壓縮代碼時進行優化。
第二個參數為包裹jQuery的匿名函數,在匿名參數中被調用——factory()。
?
二、jQuery的無new構建
jQuery框架的核心就是從HTML文檔中匹配元素并對其執行操作、
例如:
$().find().css() $().hide().html('....').hide().從上面的寫法上至少可以發現2個問題
1. jQuery對象的構建方式
2 .jQuery方法的調用方式
?
分析一:jQuery的無new構建
JavaScript是函數式語言,函數可以實現類,類就是面向對象編程中最基本的概念
var aQuery = function(selector, context) {//構造函數 } aQuery.prototype = {//原型name:function(){},age:function(){} }var a = new aQuery();a.name();這是常規的使用方法,顯而易見jQuery不是這樣玩的
jQuery沒有使用new運行符將jQuery顯示的實例化,還是直接調用其函數
按照jQuery的抒寫方式
$().ready() $().noConflict()要實現這樣,那么jQuery就要看成一個類,那么$()應該是返回類的實例才對
所以把代碼改一下:
var aQuery = function(selector, context) {return new aQuery(); } aQuery.prototype = {name:function(){},age:function(){} }通過new?aQuery(),雖然返回的是一個實例,但是也能看出很明顯的問題,死循環了!
?
那么如何返回一個正確的實例?
在javascript中實例this只跟原型有關系
那么可以把jQuery類當作一個工廠方法來創建實例,把這個方法放到jQuery.prototye原型中
var aQuery = function(selector, context) {return aQuery.prototype.init(); } aQuery.prototype = {init:function(){return this;}name:function(){},age:function(){} }當執行aQuery() 返回的實例:
很明顯aQuery()返回的是aQuery類的實例,那么在init中的this其實也是指向的aQuery類的實例
問題來了init的this指向的是aQuery類,如果把init函數也當作一個構造器,那么內部的this要如何處理?
var aQuery = function(selector, context) {return aQuery.prototype.init(); } aQuery.prototype = {init: function() {this.age = 18return this;},name: function() {},age: 20 }aQuery().age //18這樣的情況下就出錯了,因為this只是指向aQuery類的,所以需要設計出獨立的作用域才行
?
jQuery框架分隔作用域的處理
jQuery = function( selector, context ) {// The jQuery object is actually just the init constructor 'enhanced'return new jQuery.fn.init( selector, context, rootjQuery );},很明顯通過實例init函數,每次都構建新的init實例對象,來分隔this,避免交互混淆
那么既然都不是同一個對象那么肯定又出現一個新的問題
例如:
var aQuery = function(selector, context) {return new aQuery.prototype.init(); } aQuery.prototype = {init: function() {this.age = 18return this;},name: function() {},age: 20 }//Uncaught TypeError: Object [object Object] has no method 'name' console.log(aQuery().name())拋出錯誤,無法找到這個方法,所以很明顯new的init跟jquery類的this分離了
?
怎么訪問jQuery類原型上的屬性與方法?
???? 做到既能隔離作用域還能使用jQuery原型對象的作用域呢,還能在返回實例中訪問jQuery的原型對象?
實現的關鍵點
// Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn;通過原型傳遞解決問題,把jQuery的原型傳遞給jQuery.prototype.init.prototype
換句話說jQuery的原型對象覆蓋了init構造器的原型對象
因為是引用傳遞所以不需要擔心這個循環引用的性能問題
var aQuery = function(selector, context) {return new aQuery.prototype.init(); } aQuery.prototype = {init: function() {return this;},name: function() {return this.age},age: 20 }aQuery.prototype.init.prototype = aQuery.prototype;console.log(aQuery().name()) //20?
三、鏈式調用
DOM鏈式調用的處理:
1.節約JS代碼.
2.所返回的都是同一個對象,可以提高代碼的效率
?
通過簡單擴展原型方法并通過return this的形式來實現跨瀏覽器的鏈式調用。
利用JS下的簡單工廠模式,來將所有對于同一個DOM對象的操作指定同一個實例。
這個原理就超簡單了
aQuery().init().name()分解 a = aQuery(); a.init() a.name()把代碼分解一下,很明顯實現鏈式的基本條件就是實例this的存在,并且是同一個
aQuery.prototype = {init: function() {return this;},name: function() {return this} }所以我們在需要鏈式的方法訪問this就可以了,因為返回當前實例的this,從而又可以訪問自己的原型了
aQuery.init().name()優點:節省代碼量,提高代碼的效率,代碼看起來更優雅
?
四、插件接口
jQuery支持自己擴展屬性,這個對外提供了一個接口,jQuery.fn.extend()來對對象增加方法
從jQuery的源碼中可以看到,jQuery.extend和jQuery.fn.extend其實是同指向同一方法的不同引用
jQuery.extend = jQuery.fn.extend = function() { jQuery.extend 對jQuery本身的屬性和方法進行了擴展,擴展工具方法下的插件jQuery.fn.extend 對jQuery.fn的屬性和方法進行了擴展,擴展jquery對象下的插件通過extend()函數可以方便快速的擴展功能,不會破壞jQuery的原型結構
jQuery.extend = jQuery.fn.extend = function(){...}; 這個是連等,也就是2個指向同一個函數,怎么會實現不同的功能呢?這就是this 力量了!
針對fn與jQuery其實是2個不同的對象,在之前有講述:
- jQuery.extend 調用的時候,this是指向jQuery對象的(jQuery是函數,也是對象!),所以這里擴展在jQuery上。
- 而jQuery.fn.extend 調用的時候,this指向fn對象,jQuery.fn 和jQuery.prototype指向同一對象,擴展fn就是擴展jQuery.prototype原型對象。
- 這里增加的是原型方法,也就是對象方法了。所以jQuery的api中提供了以上2中擴展函數。
?
?
轉載于:https://www.cnblogs.com/shytong/p/5311108.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的【jQuery源码】整体架构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Bootstrap学习遇到的role属性
- 下一篇: 第四套人民币尾四同号