欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jQuery中extend()和fn.extend()方法詳解

 更新時(shí)間:2015年06月03日 12:06:40   投稿:hebedich  
jQuery自定義了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能夠創(chuàng)建全局函數(shù)或者選擇器,而jQuery.fn.extend()方法能夠創(chuàng)建jQuery對(duì)象方法.

這兩個(gè)方法用的是相同的代碼,一個(gè)用于給jQuery對(duì)象或者普通對(duì)象合并屬性和方法一個(gè)是針對(duì)jQuery對(duì)象的實(shí)例,對(duì)于基本用法舉幾個(gè)例子:

html代碼如下:

復(fù)制代碼 代碼如下:

<!doctype html>
<html>
   <head>
      <title></title>
        <script src='jquery-1.7.1.js'></script>
   </head>
   <body>
    <img src=''/>
   </body>
</html>

下面寫(xiě)js里面的用法:

合并兩個(gè)普通對(duì)象

復(fù)制代碼 代碼如下:

      //給兩個(gè)普通對(duì)象合并屬性
      var obj1={name:'Tom',age:22};
      var obj2={name:'Jack',height:180};
      console.log($.extend(obj1,obj2));  //Object {name: "Jack", age: 22, height: 180}

給jQuery對(duì)象添加屬性或者方法

復(fù)制代碼 代碼如下:

$.extend({hehe:function(){alert('hehe');}});
 $.hehe();  //alert('hehe')

這個(gè)用法很重要,是jQuery內(nèi)部添加實(shí)例屬性和方法以及原型屬性和方法的實(shí)現(xiàn)方法也是編寫(xiě)jQuery插件的方法,下面是jQuery1.7.1中使用extend方法擴(kuò)展自己的方法和屬性

復(fù)制代碼 代碼如下:

jQuery.extend({
    noConflict: function( deep ) {
        if ( window.$ === jQuery ) {
            window.$ = _$;
        }
        if ( deep && window.jQuery === jQuery ) {
            window.jQuery = _jQuery;
        }
        return jQuery;
    },
    // Is the DOM ready to be used? Set to true once it occurs.
    isReady: false,
    // A counter to track how many items to wait for before
    // the ready event fires. See #6781
    readyWait: 1,
    .....

在這個(gè)例子中只傳入了一個(gè)對(duì)象參數(shù),那么默認(rèn)就把this當(dāng)做待合并修改的對(duì)象

給jQuery對(duì)象實(shí)例添加屬性或者方法

復(fù)制代碼 代碼如下:

 //針對(duì)jQuery實(shí)例擴(kuò)展合并
      console.log($('img').extend({'title':'img'}));//[img, img#img.img, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: "img", title: "img", constructor: function…]

只合并不修改待合并對(duì)象

復(fù)制代碼 代碼如下:

      var obj1={name:'Tom',age:22};
      var obj2={name:'Jack',height:180};
      console.log($.extend(obj1,obj2));   //Object {name: "Jack", age: 22, height: 180}
      console.log(obj1);                  //Object {name: "Jack", age: 22, height: 180}

默認(rèn)情況下,待合并對(duì)象跟返回結(jié)果一樣是被修改了的,如果僅僅想得到一個(gè)合并后的對(duì)象又不想破壞任何一個(gè)原來(lái)的對(duì)象可以使用此方法

復(fù)制代碼 代碼如下:

  var obj1={name:'Tom',age:22};
  var obj2={name:'Jack',height:180};
  var empty={};
  console.log($.extend(empty,obj1,obj2));   //Object {name: "Jack", age: 22, height: 180}
  console.log(obj1);                  //Object {name: "Tom", age: 22}

使用則遞歸合并或者叫深度拷貝

復(fù)制代碼 代碼如下:

 var obj1={name:'Tom',love:{drink:'milk',eat:'bread'}};
 var obj2={name:'Jack',love:{drink:'water',sport:'football'}};
 console.log(($.extend(false,obj1,obj2)).love);   //Object {drink: "water", sport: "football"}
 console.log(($.extend(true,obj1,obj2)).love);    //Object {drink: "water", eat: "bread", sport: "football"}

詳細(xì)的使用方法可以看參考手冊(cè)http://www.w3cschool.cc/manual/jquery/

下面來(lái)分析下1.7.1源碼中是怎么實(shí)現(xiàn)的:

復(fù)制代碼 代碼如下:

jQuery.extend = jQuery.fn.extend = function() {
    var options, name, src, copy, copyIsArray, clone,
        target = arguments[0] || {},
        i = 1,
        length = arguments.length,
        deep = false;
       ...
}

 首先是定義了一組變量,因?yàn)閰?shù)個(gè)數(shù)不確定所以就直接調(diào)用arguments對(duì)象訪問(wèn)傳遞的參數(shù)

  變量 options:指向某個(gè)源對(duì)象。
‰ ‰ 變量 name:表示某個(gè)源對(duì)象的某個(gè)屬性名。
‰ ‰ 變量 src:表示目標(biāo)對(duì)象的某個(gè)屬性的原始值。
‰ ‰ 變量 copy:表示某個(gè)源對(duì)象的某個(gè)屬性的值。
‰ ‰ 變量 copyIsArray:指示變量 copy 是否是數(shù)組。
‰ ‰ 變量 clone:表示深度復(fù)制時(shí)原始值的修正值。
‰ ‰ 變量 target:指向目標(biāo)對(duì)象。
‰ ‰ 變量 i:表示源對(duì)象的起始下標(biāo)。
‰ ‰ 變量 length:表示參數(shù)的個(gè)數(shù),用于修正變量 target。
‰ ‰ 變量 deep:指示是否執(zhí)行深度復(fù)制,默認(rèn)為 false。

為了更好地了解代碼實(shí)現(xiàn)這里以上面舉的一個(gè)例子作為演示觀察源代碼執(zhí)行情況

復(fù)制代碼 代碼如下:

      var obj1={name:'Tom',love:{drink:'milk',eat:'bread'}};
      var obj2={name:'Jack',love:{drink:'water',sport:'football'}};
      $.extend(true,obj1,obj2)

源碼分析

復(fù)制代碼 代碼如下:

// Handle a deep copy situation
    if ( typeof target === "boolean" ) {
        deep = target;
        target = arguments[1] || {};
        // skip the boolean and the target
        i = 2;
    }

判斷是不是深度復(fù)制,如果第一個(gè)參數(shù)是布爾值那么就把第一個(gè)參數(shù)的值給deep,然后把第二個(gè)參數(shù)作為目標(biāo)對(duì)象,如果第二個(gè)參數(shù)不存在就賦值為一個(gè)空對(duì)象,把源對(duì)象的下標(biāo)改為2,在這個(gè)例子里面  是走這里的因?yàn)榈谝粋€(gè)參數(shù)是ture然后把deep變成了true ,target被修正成了第二個(gè)參數(shù)也即是obj1,源對(duì)象的起始下標(biāo)為2就是從第三個(gè)開(kāi)始作為源對(duì)象也就是本例中的obj2

復(fù)制代碼 代碼如下:

// Handle case when target is a string or something (possible in deep copy)
    if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
        target = {};
    }

這里對(duì)target又進(jìn)一步進(jìn)行了處理對(duì)于非對(duì)象和函數(shù)的數(shù)據(jù)類型而言增加自定義屬性是無(wú)效的比如字符串自能調(diào)用自帶的方法和屬性

復(fù)制代碼 代碼如下:

// extend jQuery itself if only one argument is passed
    if ( length === i ) {
        target = this;
        --i;
    }

如果length屬性等于i的值那就表示沒(méi)有目標(biāo)對(duì)象存在,正常情況下length應(yīng)該是大于i的值的 ,那么這個(gè)時(shí)候就把this作為目標(biāo)對(duì)象把i值減一實(shí)現(xiàn)length值大于i值(比i大1)

這個(gè)就是jQuery給自己擴(kuò)展屬性的方法的實(shí)現(xiàn)原理,只要不傳入目標(biāo)對(duì)象就可以啦

兩種可能的情況:$.extend(obj)    或者  $.extend(false/true,obj);

復(fù)制代碼 代碼如下:

    for ( ; i < length; i++ ) {
        // Only deal with non-null/undefined values
        if ( (options = arguments[ i ]) != null ) {
            // Extend the base object
            for ( name in options ) {
                src = target[ name ];
                copy = options[ name ];
                // Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }
                // Recurse if we're merging plain objects or arrays
                if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                    if ( copyIsArray ) {
                        copyIsArray = false;
                        clone = src && jQuery.isArray(src) ? src : [];
                    } else {
                        clone = src && jQuery.isPlainObject(src) ? src : {};
                    }
                    // Never move original objects, clone them
                    target[ name ] = jQuery.extend( deep, clone, copy );
                // Don't bring in undefined values
                } else if ( copy !== undefined ) {
                    target[ name ] = copy;
                }
            }
        }
    }

這個(gè)部分就是此方法的核心了,從arguements對(duì)象的第i個(gè)下標(biāo)值開(kāi)始循環(huán)操作首先過(guò)濾掉源對(duì)象是null或者是undefined的情況可以看到其實(shí)

源對(duì)象不一定真的就是對(duì)像,也可以是其他類型的值比如字符串比如這樣寫(xiě):

復(fù)制代碼 代碼如下:

console.log($.extend({'name':'tom'},'aa'));   //Object {0: "a", 1: "a", name: "tom"}

是不是感覺(jué)很奇怪???究竟是怎么實(shí)現(xiàn)的呢?下面接著看

過(guò)濾完之后開(kāi)始進(jìn)行for循環(huán) src保存的是目標(biāo)對(duì)象的某個(gè)鍵的值,copy屬性保存的源對(duì)象的某個(gè)鍵的值,這兩個(gè)鍵都是一樣的

復(fù)制代碼 代碼如下:

// Prevent never-ending loop
                if ( target === copy ) {
                    continue;
                }

如果源對(duì)象的某個(gè)屬性值就是目標(biāo)對(duì)象可能會(huì)造成死循環(huán)導(dǎo)致程序崩潰所以這里做了一個(gè)限制讓其跳過(guò)此次循環(huán)例如:

復(fù)制代碼 代碼如下:

var o = {};
o.n1 = o;
$.extend( true, o, { n2: o } );
// 拋出異常:
// Uncaught RangeError: Maximum call stack size exceeded

但是這樣做也會(huì)冤枉一些正常的情況比如:

復(fù)制代碼 代碼如下:

 var obj1={a:'a'}
 var obj2={a:obj1};
 console.log($.extend(obj1,obj2)); //Object {a: "a"}

這種情況也是滿足源對(duì)象值等于目標(biāo)對(duì)象的但是結(jié)果發(fā)現(xiàn)obj1的a的屬性值并沒(méi)有被修改,就是因?yàn)閳?zhí)行了continue,下面把源碼的這段話注釋掉在執(zhí)行

復(fù)制代碼 代碼如下:

Object {a: Object}

這個(gè)時(shí)候就是正常被修改了個(gè)人感覺(jué)這個(gè)地方需要改進(jìn);

接著就是一個(gè)if判斷就是區(qū)分是不是進(jìn)行深度復(fù)制的先不看深度復(fù)制的先看一般的

復(fù)制代碼 代碼如下:

target[ name ] = copy;

很簡(jiǎn)單就是只要copy有值就直接復(fù)制給目標(biāo)對(duì)象,目標(biāo)對(duì)象有的就修改沒(méi)有就增加,這樣就實(shí)現(xiàn)了合并啦。

for循環(huán)之后在把新的目標(biāo)對(duì)象返回,所以目標(biāo)對(duì)象最后是被修改的,而且結(jié)果和返回的結(jié)果是一樣的。

復(fù)制代碼 代碼如下:

// Return the modified object
    return target;
};

下面再來(lái)說(shuō)說(shuō)深度復(fù)制了怎么去處理

首先保證deep是true,copy有值并且是對(duì)象或者數(shù)組(如果不是對(duì)象和數(shù)組深度復(fù)制也就無(wú)從談起)然后再分?jǐn)?shù)組和對(duì)象來(lái)處理,先來(lái)看數(shù)組的情況:

復(fù)制代碼 代碼如下:

if ( copyIsArray ) {
         copyIsArray = false;
         clone = src && jQuery.isArray(src) ? src : [];

} else {
        clone = src && jQuery.isPlainObject(src) ? src : {};
}

如果是數(shù)組copyIsArray的值為真然后走里面的 把值改成false ,針對(duì)當(dāng)前循環(huán)的源對(duì)象屬性,目標(biāo)對(duì)象可能有也可能沒(méi)有,有的話判斷一下是不是數(shù)組是的話就是原來(lái)的數(shù)組不變不是的話就讓它變成一個(gè)數(shù)組,因?yàn)榧热辉磳?duì)象的當(dāng)前屬性是數(shù)組最后目標(biāo)元素也必須是數(shù)組。不是數(shù)組就是對(duì)象把目標(biāo)對(duì)象當(dāng)前屬性改成對(duì)象。

復(fù)制代碼 代碼如下:

    // Never move original objects, clone them
     target[ name ] = jQuery.extend( deep, clone, copy );

然后把源對(duì)象的當(dāng)前屬性值(是數(shù)組或?qū)ο螅┖鸵呀?jīng)被改造過(guò)的目標(biāo)對(duì)象的當(dāng)前屬性進(jìn)行遞歸合并最后返回的新的數(shù)組或者對(duì)象賦值給目標(biāo)對(duì)象,最終實(shí)現(xiàn)了深度復(fù)制。

但是這里面還有一個(gè)比較奇怪的現(xiàn)象,比如這樣操作:

復(fù)制代碼 代碼如下:

      console.log($.extend({a:1},'aa')); //Object {0: "a", 1: "a", a: 1}

原來(lái)源對(duì)象不一定真的是對(duì)象e而且居然可以把字符串拆開(kāi)跟目標(biāo)對(duì)象合并,原來(lái)for...in循環(huán)是操作字符串的

復(fù)制代碼 代碼如下:

      var str='aa';
      for(var name in str){ 
         console.log(name);
         console.log(str[name])
      }

這樣也是可以的,會(huì)把字符串拆開(kāi)按數(shù)字下標(biāo)讀取,但是在源碼中

復(fù)制代碼 代碼如下:

if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) )

是有數(shù)組和對(duì)象限制的,那么深度復(fù)制的時(shí)候是不是就沒(méi)有效果了呢?

經(jīng)過(guò)我測(cè)試深度復(fù)制也是可以的,因?yàn)樵谠创a里面copy的值竟然變成了匿名函數(shù)函數(shù)

 alert(jQuery.isPlainObject(copy)); //true

至于為什么是函數(shù)筆者還沒(méi)搞清楚留待以后解決吧!

相關(guān)文章

  • 詳解Jquery Easyui的驗(yàn)證擴(kuò)展

    詳解Jquery Easyui的驗(yàn)證擴(kuò)展

    本文主要介紹了Jquery Easyui驗(yàn)證擴(kuò)展,Easyui驗(yàn)證,Easyui校驗(yàn),js正則表達(dá)式。具有一定的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-01-01
  • Android中的jQuery:AQuery簡(jiǎn)介

    Android中的jQuery:AQuery簡(jiǎn)介

    jQuery的流行已經(jīng)成為了事實(shí),它極大地減少了執(zhí)行異步任務(wù)和操作DOM所需要的代碼數(shù)量。新項(xiàng)目AQuery想要為Android開(kāi)發(fā)者提供同樣的功能
    2014-05-05
  • jquery實(shí)現(xiàn)數(shù)字輸入框

    jquery實(shí)現(xiàn)數(shù)字輸入框

    本文主要分享了jquery實(shí)現(xiàn)數(shù)字輸入框的示例代碼,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-02-02
  • JavaScript對(duì)象之間的轉(zhuǎn)換 jQuery對(duì)象和原聲DOM

    JavaScript對(duì)象之間的轉(zhuǎn)換 jQuery對(duì)象和原聲DOM

    jQuery對(duì)象和原聲DOM,JavaScript對(duì)象之間的轉(zhuǎn)換,學(xué)習(xí)jquery的朋友可以參考下。
    2011-03-03
  • jQuery日歷插件datepicker用法詳解

    jQuery日歷插件datepicker用法詳解

    這篇文章主要為大家詳細(xì)介紹了jQuery日歷插件datepicker用法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • jQuery模仿單選按鈕選中效果

    jQuery模仿單選按鈕選中效果

    單選按鈕以及復(fù)選按鈕的使用情況還是蠻多的,多選按鈕使用toggleClass()方法就可以實(shí)現(xiàn),下面小編給大家介紹單選按鈕的實(shí)現(xiàn),感興趣的朋友一起看下吧
    2016-06-06
  • jQuery中slidedown與slideup方法用法示例

    jQuery中slidedown與slideup方法用法示例

    這篇文章主要介紹了jQuery中slidedown與slideup方法用法,結(jié)合實(shí)例形式分析了jQuery基于slidedown與slideup方法實(shí)現(xiàn)頁(yè)面元素展開(kāi)與折疊的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2016-09-09
  • jQuery中DOM 屬性使用實(shí)例詳解下篇

    jQuery中DOM 屬性使用實(shí)例詳解下篇

    這篇文章主要為大家介紹了jQuery中DOM 屬性使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08
  • EasyUi 打開(kāi)對(duì)話框后控件賦值及賦值后不顯示的問(wèn)題解決辦法

    EasyUi 打開(kāi)對(duì)話框后控件賦值及賦值后不顯示的問(wèn)題解決辦法

    這篇文章主要介紹了easyUi 打開(kāi)對(duì)話框后控件賦值,以及賦值后不顯示的問(wèn)題解決辦法,解決方法非常簡(jiǎn)單,只需要將賦值語(yǔ)句修改下就好,下面小編給大家簡(jiǎn)單介紹下,需要的朋友參考下
    2017-01-01
  • jQuery/CSS3圖片特效插件整理推薦

    jQuery/CSS3圖片特效插件整理推薦

    這里給大家整理匯總了10款jQuery/CSS3圖片特效插件,效果都非常棒,推薦給大家,有需要的小伙伴參考下
    2014-12-12

最新評(píng)論