jquery源碼解析

  • jquery是前端常用的庫,它的源碼也是十分的精妙,我本著敬畏之心來分析它,jquery 代碼未壓縮總共有11009行,這么多的代碼一行一行的看下去不知道要看到猴年馬月,為何不換一種方式,我們先掌握它的主干,以后有時(shí)間再去研究它的各個(gè)分支,在此,我們采用猜想實(shí)驗(yàn)法

  • 第一個(gè)問題:$(),$.each(),$('body')等,為什么他們這樣寫就有效果,大家可以想到了 $肯定是個(gè)函數(shù),$('body')就是執(zhí)行這個(gè)函數(shù),那么所謂的$.each,$.ajax 應(yīng)該是這個(gè)函數(shù)的屬性或是方法,那么來嘗試寫一個(gè)最簡單的構(gòu)造函數(shù)

    var hQuery =function (selector, context){
        
    }
    hQuery.prototype=  {
        sayHello:function(){
            console.log('hello world')
        }
    }
    window.$= hQuery //將函數(shù)hQuery綁定全局對(duì)象window的屬性
    

這樣 $()就等同于 執(zhí)行 函數(shù) hQuery(),但是這時(shí)還是不行,我們只能用 new $('div')來生成不同的實(shí)例對(duì)象來操作,那怎么才能把new 給去調(diào),那么我們肯定是想到的思路是 我讓 hQuery 返回一個(gè)新的對(duì)象,不就不用 new 來生成了新的對(duì)象,好吧,我們來試一試,
var hQuery =function (selector, context){
return this
}
hQuery.prototype= {
sayHello:function(){
console.log('hello world')
}
}

  • return this 執(zhí)行后發(fā)現(xiàn)失敗了,原來this指向的不是函數(shù)構(gòu)造函數(shù)本身,this 指向的是全局對(duì)象window,怎么辦才能讓它返回一個(gè)新的對(duì)象,要不試一試 返回 對(duì)象的原型,于是我們繼續(xù)嘗試
    var hQuery =function (selector, context){
    return hQuery.prototype
    }
    hQuery.prototype= {
    sayHello:function(){
    console.log('hello world')
    }
    }

  • 這樣執(zhí)行后雖然返回了一個(gè)對(duì)象,但是生成的所有對(duì)象都是繼承hQuery.prototype,對(duì)象都是一樣的,這不是我們的通過構(gòu)造函數(shù)返回不同的對(duì)象的目標(biāo),又失敗了,怎么辦,于是我們想到能不能在原型里綁定個(gè)方法函數(shù)(構(gòu)造函數(shù)也能生產(chǎn)實(shí)例),并返回函數(shù)方法的原型,
    var hQuery= function(selector,context){
    return new hQuery.prototype.init.(selector,context)
    };

    hQuery.prototype = {
        init:function(selector,context){
          console.log(this === hQuery.prototype);//false
            return this //此時(shí)this指向init{}
      },
        sayHello:function (){
          console.log('hello world')
        }
    };
    window.hQuery= window.$= hQuery
    
  • 執(zhí)行后還是不行,不同的對(duì)象是生成了,可是不能調(diào)用hQuery的原型的方法,怎么才能讓生成的init屬性的構(gòu)造函數(shù)生成的對(duì)象繼承hQuery.prototype里的方法了,于是讓前者繼者后者的原型試一試
    var hQuery= function(selector,context){

       return new hQuery.prototype.init(selector,context)
     };
     hQuery.prototype = {
     constructor:hQuery,
     init:function(selector,context){
         this.selector= selector;
         this.context=context;
       },
           sayHello:function(){
               console.log('hello')
           }
     };
     hQuery.prototype.init.prototype = hQuery.prototype
     window.hQuery= window.$= hQuery
    
  • 執(zhí)行后成功了,成功的生成不同的對(duì)象,這是因?yàn)閕nit 方法構(gòu)造函數(shù)經(jīng)過new 后生成了不同的函數(shù),同時(shí)它的原型此時(shí)指向了hQuery.prototype,也繼承了hQuery的方法,我們終于實(shí)現(xiàn)了$()傳入?yún)?shù)的不同,生成不同的對(duì)象,公用一套方法。

  • 原型鏈圖

1.png
  • 雖然已經(jīng)這種方法已經(jīng)實(shí)現(xiàn)了,你也就應(yīng)該知道了jquery鏈?zhǔn)秸{(diào)用的原理了把,就是給我往hQuery.prototype上添加公用的方法,再用return this,把對(duì)象返回出來,然后按這樣的流程執(zhí)行下個(gè)方法
    var hQuery= function(selector,context){
    return new hQuery.prototype.init(selector,context)
    };
    hQuery.prototype = {
    constructor:hQuery,
    init:function(selector,context){
    this.selector= selector;
    this.context=context;
    },
    sayHello:function(){
    console.log('hello')
    return this;
    },
    addClass:function(el){
    console.log('addClass: '+el)
    return this;
    }
    };
    hQuery.prototype.init.prototype = hQuery.prototype
  • 所以每個(gè)方法必須要return this(init構(gòu)造函數(shù)生成的對(duì)象) 后才能讓下一個(gè)方法繼續(xù)執(zhí)行。
  • 但是到現(xiàn)在還沒有實(shí)現(xiàn)$.ajax,$.each,這種形式的調(diào)用,不過現(xiàn)在實(shí)現(xiàn)這個(gè)太簡單了,我直接在函數(shù)上添加方法不就行了
    hQuery.ajax =function (){
    console.log('ajax execute!')
    };
    $.ajax()
  • 可是感覺太丑了,不美觀,必須一個(gè)一個(gè)方法這樣把它添加上,參考jquery的拷貝extend,做個(gè)超級(jí)簡單版本
    hQuery.extend = hQuery.prototype.extend =function (obj){
    for( var key in obj){
    this[key]=obj[key]
    }
    };
  • 此時(shí)extend方法遍歷了傳遞參數(shù)0bj的所有屬性,并把obj的屬性屬性賦值給 hQuery.prototype或hQuery.extend,我們直接使用extend 的方法添加方法和屬性
    hQuery.extend({
    isArray: Array.isArray,
    ajax:function(){}
    });
    hQuery.prototype.extend({
    addClass:function(){console.log('add class....')},
    sayHello:function(){
    console.log('hello'+this.selector)
    }
    })
  • 到此為止,我們終于實(shí)現(xiàn)了jquery的超級(jí)簡單傻瓜版,全部代碼如下:
    var hQuery= function(selector,context){
    return new hQuery.prototype.init(selector,context)
    };
    hQuery.prototype = {
    constructor:hQuery,
    init:function(selector,context){
    this.selector= selector;
    this.context=context;
    },
    sayHello:function(){
    console.log('hello')
    return this;
    },
    addClass:function(el){
    console.log(this)
    console.log('addClass: '+el)
    return this;
    }
    };
    hQuery.prototype.init.prototype = hQuery.prototype
    hQuery.extend = hQuery.prototype.extend =function (obj){
    for( var key in obj){
    this[key]=obj[key]
    }
    };
    hQuery.extend({
    isArray: Array.isArray,
    ajax:function(){}
    });
    hQuery.prototype.extend({
    saySelector:function(){
    console.log(this.selector)
    }
    })
  • 后記:jquery博大精深,自己只是懂了最最簡單的實(shí)現(xiàn),今后還要認(rèn)真學(xué)習(xí)和分析它的源碼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.jQuery是如何尋找到DOM或者很多方法 $符號(hào)選擇標(biāo)簽,然后進(jìn)行事件監(jiān)聽或者DOM操作 可以把$,看成一個(gè)...
    大淀桑浮不起來閱讀 1,047評(píng)論 1 10
  • 繼續(xù)咱們的jQuery源碼解析。 (function(){ 原文中此處為鏈接,暫不支持采集 (96,2...
    web_無笙閱讀 482評(píng)論 2 1
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡單...
    舟漁行舟閱讀 8,116評(píng)論 2 17
  • 今天,更新有點(diǎn)晚, 但是干貨不怕晚, 接著昨天講得講, 把第一段講的沒講完的繼續(xù)講解。 (function(){ ...
    web_無笙閱讀 440評(píng)論 0 2
  • 入門前端也一年了,從來沒有仔細(xì)看過jquery的源碼,最近一直在搞angular4,抽點(diǎn)時(shí)間寫下這個(gè) 這是jque...
    我是上帝可愛多閱讀 645評(píng)論 0 4

友情鏈接更多精彩內(nèi)容