日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

【jQuery源码】整体架构

發(fā)布時(shí)間:2025/5/22 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【jQuery源码】整体架构 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  jQuery源碼可以精簡(jiǎn)為以下內(nèi)容:

  方框上面的代碼根據(jù)Jq注釋我們可以知道是對(duì)AMD規(guī)范的支持。

  jQuery整體上被包裹在一個(gè)匿名函數(shù)中,這個(gè)匿名函數(shù)再作為另一個(gè)匿名函數(shù)的參數(shù)被傳入,形參factory。

?

一、自調(diào)用函數(shù)

  整個(gè)部分被自調(diào)用函數(shù)包裹,通過(guò)定義一個(gè)匿名函數(shù),創(chuàng)建了一個(gè)“私有”的命名空間,該命名空間的變量和方法,不會(huì)破壞全局的命名空間。

  自調(diào)用函數(shù)中的第一個(gè)參數(shù)相當(dāng)于window,通過(guò)傳入window變量,使得window由全局變量變?yōu)榫植孔兞?#xff0c;當(dāng)在jQuery代碼塊中訪問(wèn)window時(shí),不需要將作用域鏈回退到頂層作用域,這樣可以更快的訪問(wèn)window;這還不是關(guān)鍵所在,更重要的是,將window作為參數(shù)傳入,可以在壓縮代碼時(shí)進(jìn)行優(yōu)化。

  第二個(gè)參數(shù)為包裹jQuery的匿名函數(shù),在匿名參數(shù)中被調(diào)用——factory()。

?

二、jQuery的無(wú)new構(gòu)建

  jQuery框架的核心就是從HTML文檔中匹配元素并對(duì)其執(zhí)行操作、

  例如:

$().find().css() $().hide().html('....').hide().

  從上面的寫法上至少可以發(fā)現(xiàn)2個(gè)問(wèn)題

  1. jQuery對(duì)象的構(gòu)建方式

  2 .jQuery方法的調(diào)用方式

?

分析一:jQuery的無(wú)new構(gòu)建

  JavaScript是函數(shù)式語(yǔ)言,函數(shù)可以實(shí)現(xiàn)類,類就是面向?qū)ο缶幊讨凶罨镜母拍?/p> var aQuery = function(selector, context) {//構(gòu)造函數(shù) } aQuery.prototype = {//原型name:function(){},age:function(){} }var a = new aQuery();a.name();

  這是常規(guī)的使用方法,顯而易見(jiàn)jQuery不是這樣玩的

  jQuery沒(méi)有使用new運(yùn)行符將jQuery顯示的實(shí)例化,還是直接調(diào)用其函數(shù)

  按照jQuery的抒寫方式

$().ready() $().noConflict()

  要實(shí)現(xiàn)這樣,那么jQuery就要看成一個(gè)類,那么$()應(yīng)該是返回類的實(shí)例才對(duì)

  所以把代碼改一下:

var aQuery = function(selector, context) {return new aQuery(); } aQuery.prototype = {name:function(){},age:function(){} }

  通過(guò)new?aQuery(),雖然返回的是一個(gè)實(shí)例,但是也能看出很明顯的問(wèn)題,死循環(huán)了!

?


那么如何返回一個(gè)正確的實(shí)例?

  在javascript中實(shí)例this只跟原型有關(guān)系

  那么可以把jQuery類當(dāng)作一個(gè)工廠方法來(lái)創(chuàng)建實(shí)例,把這個(gè)方法放到j(luò)Query.prototye原型中

var aQuery = function(selector, context) {return aQuery.prototype.init(); } aQuery.prototype = {init:function(){return this;}name:function(){},age:function(){} }

  當(dāng)執(zhí)行aQuery() 返回的實(shí)例:

  很明顯aQuery()返回的是aQuery類的實(shí)例,那么在init中的this其實(shí)也是指向的aQuery類的實(shí)例

  問(wèn)題來(lái)了init的this指向的是aQuery類,如果把init函數(shù)也當(dāng)作一個(gè)構(gòu)造器,那么內(nèi)部的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

  這樣的情況下就出錯(cuò)了,因?yàn)閠his只是指向aQuery類的,所以需要設(shè)計(jì)出獨(dú)立的作用域才行

?


jQuery框架分隔作用域的處理

jQuery = function( selector, context ) {// The jQuery object is actually just the init constructor 'enhanced'return new jQuery.fn.init( selector, context, rootjQuery );},

  很明顯通過(guò)實(shí)例init函數(shù),每次都構(gòu)建新的init實(shí)例對(duì)象,來(lái)分隔this,避免交互混淆

  那么既然都不是同一個(gè)對(duì)象那么肯定又出現(xiàn)一個(gè)新的問(wèn)題

例如:

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())

  拋出錯(cuò)誤,無(wú)法找到這個(gè)方法,所以很明顯new的init跟jquery類的this分離了

?


怎么訪問(wèn)jQuery類原型上的屬性與方法?

???? 做到既能隔離作用域還能使用jQuery原型對(duì)象的作用域呢,還能在返回實(shí)例中訪問(wèn)jQuery的原型對(duì)象?

實(shí)現(xiàn)的關(guān)鍵點(diǎn)

// Give the init function the jQuery prototype for later instantiation jQuery.fn.init.prototype = jQuery.fn;

  通過(guò)原型傳遞解決問(wèn)題,把jQuery的原型傳遞給jQuery.prototype.init.prototype

  換句話說(shuō)jQuery的原型對(duì)象覆蓋了init構(gòu)造器的原型對(duì)象

  因?yàn)槭且脗鬟f所以不需要擔(dān)心這個(gè)循環(huán)引用的性能問(wèn)題

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

?

三、鏈?zhǔn)秸{(diào)用

  DOM鏈?zhǔn)秸{(diào)用的處理:

  1.節(jié)約JS代碼.

  2.所返回的都是同一個(gè)對(duì)象,可以提高代碼的效率

?

  通過(guò)簡(jiǎn)單擴(kuò)展原型方法并通過(guò)return this的形式來(lái)實(shí)現(xiàn)跨瀏覽器的鏈?zhǔn)秸{(diào)用。

  利用JS下的簡(jiǎn)單工廠模式,來(lái)將所有對(duì)于同一個(gè)DOM對(duì)象的操作指定同一個(gè)實(shí)例。

  這個(gè)原理就超簡(jiǎn)單了

aQuery().init().name()分解 a = aQuery(); a.init() a.name()

  把代碼分解一下,很明顯實(shí)現(xiàn)鏈?zhǔn)降幕緱l件就是實(shí)例this的存在,并且是同一個(gè)

aQuery.prototype = {init: function() {return this;},name: function() {return this} }

  所以我們?cè)谛枰準(zhǔn)降姆椒ㄔL問(wèn)this就可以了,因?yàn)榉祷禺?dāng)前實(shí)例的this,從而又可以訪問(wèn)自己的原型了

aQuery.init().name()

  優(yōu)點(diǎn):節(jié)省代碼量,提高代碼的效率,代碼看起來(lái)更優(yōu)雅

?

四、插件接口

  jQuery支持自己擴(kuò)展屬性,這個(gè)對(duì)外提供了一個(gè)接口,jQuery.fn.extend()來(lái)對(duì)對(duì)象增加方法

從jQuery的源碼中可以看到,jQuery.extend和jQuery.fn.extend其實(shí)是同指向同一方法的不同引用

jQuery.extend = jQuery.fn.extend = function() { jQuery.extend 對(duì)jQuery本身的屬性和方法進(jìn)行了擴(kuò)展,擴(kuò)展工具方法下的插件jQuery.fn.extend 對(duì)jQuery.fn的屬性和方法進(jìn)行了擴(kuò)展,擴(kuò)展jquery對(duì)象下的插件

  通過(guò)extend()函數(shù)可以方便快速的擴(kuò)展功能,不會(huì)破壞jQuery的原型結(jié)構(gòu)

  jQuery.extend = jQuery.fn.extend = function(){...}; 這個(gè)是連等,也就是2個(gè)指向同一個(gè)函數(shù),怎么會(huì)實(shí)現(xiàn)不同的功能呢?這就是this 力量了!

  針對(duì)fn與jQuery其實(shí)是2個(gè)不同的對(duì)象,在之前有講述:

  • jQuery.extend 調(diào)用的時(shí)候,this是指向jQuery對(duì)象的(jQuery是函數(shù),也是對(duì)象!),所以這里擴(kuò)展在jQuery上。
  • 而jQuery.fn.extend 調(diào)用的時(shí)候,this指向fn對(duì)象,jQuery.fn 和jQuery.prototype指向同一對(duì)象,擴(kuò)展fn就是擴(kuò)展jQuery.prototype原型對(duì)象。
  • 這里增加的是原型方法,也就是對(duì)象方法了。所以jQuery的api中提供了以上2中擴(kuò)展函數(shù)。
1 jQuery.extend = jQuery.fn.extend = function() { 2 var src, copyIsArray, copy, name, options, clone, 3 target = arguments[0] || {}, 4 i = 1, 5 length = arguments.length, 6 deep = false; 7 8 // Handle a deep copy situation 9 //判斷第一個(gè)參數(shù)是否為boolean類型,也就是是否深度嵌套對(duì)象 10 if ( typeof target === "boolean" ) { 11 deep = target; 12 13 // skip the boolean and the target 14 //跳過(guò)第一個(gè)boolean參數(shù) 15 target = arguments[ i ] || {}; 16 i++; 17 } 18 19 // Handle case when target is a string or something (possible in deep copy) 20 // 處理奇怪的情況,比如 jQuery.extend( 'hello' , {nick: 'casper}) 21 if ( typeof target !== "object" && !jQuery.isFunction(target) ) { 22 target = {}; 23 } 24 25 // extend jQuery itself if only one argument is passed 26 if ( i === length ) { 27 target = this; 28 i--; 29 } 30 31 for ( ; i < length; i++ ) { 32 // Only deal with non-null/undefined values 33 if ( (options = arguments[ i ]) != null ) {//opitions為一個(gè)個(gè)參數(shù)對(duì)象 34 // Extend the base object 35 for ( name in options ) { 36 src = target[ name ]; 37 copy = options[ name ]; 38 39 // Prevent never-ending loop 40 //防止自引用 41 if ( target === copy ) { 42 continue; 43 } 44 45 // Recurse if we're merging plain objects or arrays 46 //深拷貝 47 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { 48 if ( copyIsArray ) {//被拷貝屬性值是個(gè)數(shù)組 49 copyIsArray = false; 50 clone = src && jQuery.isArray(src) ? src : []; 51 52 } else { 53 clone = src && jQuery.isPlainObject(src) ? src : {}; 54 } 55 56 // Never move original objects, clone them 57 //遞歸拷貝 58 target[ name ] = jQuery.extend( deep, clone, copy ); 59 60 // Don't bring in undefined values 61 } else if ( copy !== undefined ) {//淺拷貝,屬性值不是自定義 62 target[ name ] = copy; 63 } 64 } 65 } 66 } 67 68 // Return the modified object 69 return target; 70 };

?

?

轉(zhuǎn)載于:https://www.cnblogs.com/shytong/p/5311108.html

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的【jQuery源码】整体架构的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。