jQuery的無new建立方法

來源:互聯網
上載者:User

標籤:

一般我們去寫一個架構,會採用什麼樣的設計呢?比如設計一個jQuery架構,一般我們會建立一個函數對象

function jQuery(params){  //建構函式}
jQuery.prototype.init = function(params){
  //初始化操作
}jQuery.prototype.html = function(html){  //實作類別似設定innerHTML的操作}var jq = new jQuery("#id");jq.init();jq.html("test");

我想這是我們最常見的使用方式,這種方式需要new一個新的執行個體,然後再進行初始化操作,然後才能繼續操作,很顯然這樣會比較繁瑣而且代碼較多,而jQuery中的使用方法卻非常簡潔:

擷取指定元素:$("#id")/$(".class")/$("body").html("test");

建立html片段$("<div></div>").html("test");

設定文檔載入完成後的方法$(function(){XXX});

等等,為何jQuery的使用方法如此簡單,這是因為jQuery設計的是一種無new的建立方法,這是jQuery獨特的設計思路之一。

我們開啟jQuery初始化的這塊代碼,發現基本結構是這樣子的(提取主要架構部分源碼):

(function( window, undefined ) {        var jQuery = function( selector, context ) {        return new jQuery.fn.init( selector, context, rootjQuery );    };    jQuery.fn = jQuery.prototype = {        constructor: jQuery,        init: function( selector, context, rootjQuery ) {

                if ( !selector ) {
                     return this;
                 } 

                if ( typeof selector === "string" ) {
                    if ( match && (match[1] || !context) ) {
                        return this;
                    } else if ( !context || context.jquery ) {
                        return ( context || rootjQuery ).find( selector );
                    } else {
                        return this.constructor( context ).find( selector );
                    }
                } else if ( selector.nodeType ) {
                     return this;

                } else if ( jQuery.isFunction( selector ) ) {
                     return rootjQuery.ready( selector );
                }

                if ( selector.selector !== undefined ) {
                     this.selector = selector.selector;
                     this.context = selector.context;
                 }

                 return jQuery.makeArray( selector, this );

        },
     html:function(value){
      //實作類別似innerHTML操作
     } } jQuery.fn.init.prototype = jQuery.fn;

})( window );

1. 首先把代碼封裝在一個匿名函數裡面,防止汙染全域環境,然後建立一個對象jQuery,這個對象接受兩個參數selector,context,其中selector就是我們通常傳入的 #id,.class等字串,這個對象函數裡面並沒有做什麼邏輯而是直接返回了一個原型上的init方法,然後把參數傳了進去。

2. init方法接受了3個參數,然後在內部進行了各種判斷,根據不同的情境,返回一個不同的執行個體對象,類似一個Factory 方法。

3. 將jQuery.fn.init的原型掛載到jquery的原型上。

4. 將jQuery的constructor還原為jQuery

init方法的內部邏輯我們後面再看,首先看下為何jQuery要這樣做?

首先jQuery在建構函式裡面就執行了new方法並執行了init方法,將new和init兩步直接合并成一步,而且內建new操作,不需要使用者再去進行new的操作,但是為何要使用一個原型上的init方法,而不是在自身自己new出一個對象呢?

想象一下如果jQuery這樣寫

 var jQuery = function( selector, context ) {
     //做上面的各種情境判斷 return new jQuery( selector, context, rootjQuery ); }

這樣寫會存在一個問題,jQuery函數內部new一個新的jQuery,然後會一直這樣new下去無限迴圈,陷入死迴圈。為了防止這種情況的出行,jQuery將這部分邏輯放在了原型中的一個init方法,由init方法來進行Factory 方法的處理,return new jQuery.fn.init( selector, context, rootjQuery ),這樣就避免了死迴圈的問題,而且實現了一步到位的初始化。

但是這樣寫還存在一個問題,init方法裡面的return this是指向的jQuery的執行個體對象,那他將無法訪問jQuery的原型對象,比如說jQuery.prototype.html方法,因為html的方法是jQuery.prototype上的所以init方法無法訪問這個函數,為瞭解決這個問題,我們看到之前的源碼有最後一行:

 jQuery.fn.init.prototype = jQuery.fn;

其中jQuery.fn就是jQuery.prototpye,也就等價於

jQuery.prototpye.init.prototype = jQuery.prototpye;

這句話的意思是,把init的方法的原型改為指向jQuery的原型,這樣new init的出來的執行個體對象也就等價於new jQuery的執行個體對象,所以也就可以訪問jQuery的原型方法了。

jQuery.prototype.init和jQuery的原型指向的是同一個對象,這樣不管是init還是jQuery去修改原型對象都是等價的,這樣就實現了上面提到的問題。

最後,jQuery再把constructor還願回來到jQuery,防止建構函式指向錯誤,引起調用問題,為何要這樣處理呢?因為我們是把jQuery的prototype直接覆蓋成了一個新的執行個體對象,所以jQuerty的constructor就變成了{}的建構函式Object,所以需要將constructor還原為真正的jQuery。

對比下兩種原型改寫方式:

//方式1
jQuery.prototype.html = function(value){}
//方式2jQuery.prototype = { html:function(value){}}

兩種方式看起來好像沒啥區別,但其實區別很大,第一種是給jQuery的prototype新增一個方法,這種方式是不會影響jQuery的constructor,還是function jQuery(),

而第二種方式是直接覆蓋了jQuery的prototype,這種情況下的constructor會被直接改寫為{html:function(value)}這個執行個體對象的建構函式,也就是function Object()

所以需要重設一下jQuery的constructor

jQuery的無new建立方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.