JQuery另類視角-動態擴充項物件

來源:互聯網
上載者:User

  大家都知道javascript是動態語言,它對動態支援是與身俱來的。

  例如:有一個employee對象,

function employee(){
    this.e_id = 0;
    this.e_name = "";
}

  現在需要為它動態新增"age"屬性和"toString()"方法,

var empObj = new employee();
empObj["age"] = 20;
empObj["toString"] = function() { return this.e_id.toString() + this.e_name; };

   一行簡單的代碼就承擔了這項工作,這是Javascript內建支援的,不過往往我們需要在這基礎上支援一定程度的擴充,所以會將這一行簡單的代碼抽成一個方法:

function dym_setprop(obj, key, value) {
    if (obj && key) {
        obj[key] = value;
    }
}

  看到這裡,我們先讓思路做個跳轉,跳到C#中的employee對象,如下:

 

  在物件導向的編程中,對外使用的都是屬性(Get/Set),那麼想想如何將這種方式簽入到Javascript中,現在讓我們跳回dym_setprop函數內,既在dym_setprop方法中不能使用obj[key]=value的直接賦值方式,而要支援Set。

function dym_setprop(obj, key, value, fn) {
    if (obj && key) {
        fn(obj, key, value);
    }
}

  參數fn,在dym_setprop中不直接操作任何對象,使用函數fn來代替相應的作業碼,則在這裡除了支援Set外,還有其他很大的自由空間。

      讓我們繼續深入dym_setprop方法,現在我們把關注點放在參數value上,大家都清楚value可以是實值型別,也可以是函數,對於實值型別來說,不用考慮其他東西直接賦值就可以了,對於函數來說就沒有這麼簡單,它支援兩種操作:

1、直接將函數賦給新擴充的屬性

2、將函數執行的傳回值賦給新擴充的屬性

function dym_setprop(obj, key, value, fn, exec, pass) {
    if (obj && key) {
        var temp = value;
        if (exec) {
            temp = value.call(obj, key, fn(obj, key));
        }
        fn(obj, key, temp, pass);
    }
}

      在這段代碼中參數exec充當了上面兩種操作選擇的角色,參數pass是一個額外的執行參數。除此之外,大家也許會對fn有些疑惑,因為上面有兩個地方使用了,區別只有參數個數不同,fn到底代表什嗎?!再次想下C#中的屬性,它是有Get/Set的,那麼在這裡fn(obj,key)就相當與Get,而fn(obj,key,temp,pass)就相當與Set。

  例如:看下面的代碼,對於fn的定義與使用,

employee.AccessProp = function(obj, key, value) {
    if (value) {
        obj[key] = value;
    }
    else {
        return obj[key];
    }
}

dym_setprop(empObj, "age", function(key, value) { return value + 10; }, employee.AccessProp, true);

      看了這麼多,也許大家覺得鬱悶,簡單的動態擴充項物件程式為什麼要以這種方式來編寫,有種沒事找事的感覺,其實不然,如果你只想做動態擴充項物件,那麼我建議你別採用上述dym_setprop的思路,但是如果你想從更加抽象的角度上思考,將dym_setprop內的程式作為一個流程執行的模板,那麼這是一個不錯的方式,因為dym_setprop內部不承擔任何具體代碼(obj[key]=value或obj[key])的執行,它都通過函數fn來代替,這樣對於具體執行來說有完全自由的空間。

   理解完上述的思路後,讓我們進入本文的核心,JQuery是如何?動態擴充項物件的?access函數, 

access函數

function access( elems, key, value, exec, fn, pass ) {
    var length = elems.length;
    
    // Setting many attributes
    if ( typeof key === "object" ) {
        for ( var k in key ) {
            access( elems, k, key[k], exec, fn, value );
        }
        return elems;
    }
    
    // Setting one attribute
    if ( value !== undefined ) {
        // Optionally, function values get executed if exec is true
        exec = !pass && exec && jQuery.isFunction(value);
        
        for ( var i = 0; i < length; i++ ) {
            fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
        }
        
        return elems;
    }
    
    // Getting an attribute
    return length ? fn( elems[0], key ) : null;
}

  仔細看完access函數的代碼,你一定發現它和dym_setprop的相試度很高,它只是多了一段代碼:

if ( typeof key === "object" ) {
   for ( var k in key ) {
    access( elems, k, key[k], exec, fn, value );
   }
   return elems;}

      很容易看出它其實就是用來支援object對象的動態擴充屬性。具體的執行流程通過來展示:

   到這裡已經寫完了,本文試著從自己的角度上去猜測JQuery的開發人員是如何設計出access函數的,讓它去支援動態擴充項物件,並且說明了access的執行流程。其實對於我的這種猜測不一定正確,不過不妨礙我對於JQuery的研究。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.