亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

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

2024-05-06 16:21:15
字體:
來源:轉載
供稿:網友
jQuery自定義了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能夠創建全局函數或者選擇器,而jQuery.fn.extend()方法能夠創建jQuery對象方法.
 

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

html代碼如下:

 

復制代碼代碼如下:

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

 

下面寫js里面的用法:

合并兩個普通對象

 

復制代碼代碼如下:

      //給兩個普通對象合并屬性
      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對象添加屬性或者方法

 

復制代碼代碼如下:

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

 

這個用法很重要,是jQuery內部添加實例屬性和方法以及原型屬性和方法的實現方法也是編寫jQuery插件的方法,下面是jQuery1.7.1中使用extend方法擴展自己的方法和屬性

 

復制代碼代碼如下:

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,
    .....

 

在這個例子中只傳入了一個對象參數,那么默認就把this當做待合并修改的對象

給jQuery對象實例添加屬性或者方法

 

復制代碼代碼如下:

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

 

只合并不修改待合并對象

 

復制代碼代碼如下:

      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}

 

默認情況下,待合并對象跟返回結果一樣是被修改了的,如果僅僅想得到一個合并后的對象又不想破壞任何一個原來的對象可以使用此方法

 

復制代碼代碼如下:

  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}

 

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

 

復制代碼代碼如下:

 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"}

 

詳細的使用方法可以看參考手冊http://www.w3cschool.cc/manual/jquery/

下面來分析下1.7.1源碼中是怎么實現的:

 

復制代碼代碼如下:

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

 

 首先是定義了一組變量,因為參數個數不確定所以就直接調用arguments對象訪問傳遞的參數

  變量 options:指向某個源對象。
‰ ‰ 變量 name:表示某個源對象的某個屬性名。
‰ ‰ 變量 src:表示目標對象的某個屬性的原始值。
‰ ‰ 變量 copy:表示某個源對象的某個屬性的值。
‰ ‰ 變量 copyIsArray:指示變量 copy 是否是數組。
‰ ‰ 變量 clone:表示深度復制時原始值的修正值。
‰ ‰ 變量 target:指向目標對象。
‰ ‰ 變量 i:表示源對象的起始下標。
‰ ‰ 變量 length:表示參數的個數,用于修正變量 target。
‰ ‰ 變量 deep:指示是否執行深度復制,默認為 false。

為了更好地了解代碼實現這里以上面舉的一個例子作為演示觀察源代碼執行情況

 

復制代碼代碼如下:

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

 

源碼分析

 

復制代碼代碼如下:

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

 

判斷是不是深度復制,如果第一個參數是布爾值那么就把第一個參數的值給deep,然后把第二個參數作為目標對象,如果第二個參數不存在就賦值為一個空對象,把源對象的下標改為2,在這個例子里面  是走這里的因為第一個參數是ture然后把deep變成了true ,target被修正成了第二個參數也即是obj1,源對象的起始下標為2就是從第三個開始作為源對象也就是本例中的obj2

 

復制代碼代碼如下:

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

 

這里對target又進一步進行了處理對于非對象和函數的數據類型而言增加自定義屬性是無效的比如字符串自能調用自帶的方法和屬性

 

復制代碼代碼如下:

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

 

如果length屬性等于i的值那就表示沒有目標對象存在,正常情況下length應該是大于i的值的 ,那么這個時候就把this作為目標對象把i值減一實現length值大于i值(比i大1)

這個就是jQuery給自己擴展屬性的方法的實現原理,只要不傳入目標對象就可以啦

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

 

復制代碼代碼如下:

    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;
                }
            }
        }
    }

 

這個部分就是此方法的核心了,從arguements對象的第i個下標值開始循環操作首先過濾掉源對象是null或者是undefined的情況可以看到其實

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

 

復制代碼代碼如下:

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

 

是不是感覺很奇怪???究竟是怎么實現的呢?下面接著看

過濾完之后開始進行for循環 src保存的是目標對象的某個鍵的值,copy屬性保存的源對象的某個鍵的值,這兩個鍵都是一樣的

 

復制代碼代碼如下:

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

 

如果源對象的某個屬性值就是目標對象可能會造成死循環導致程序崩潰所以這里做了一個限制讓其跳過此次循環例如:

 

復制代碼代碼如下:

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

 

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

 

復制代碼代碼如下:

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

 

這種情況也是滿足源對象值等于目標對象的但是結果發現obj1的a的屬性值并沒有被修改,就是因為執行了continue,下面把源碼的這段話注釋掉在執行

 

復制代碼代碼如下:

Object {a: Object}

 

這個時候就是正常被修改了個人感覺這個地方需要改進;

接著就是一個if判斷就是區分是不是進行深度復制的先不看深度復制的先看一般的

 

復制代碼代碼如下:

target[ name ] = copy;

 

很簡單就是只要copy有值就直接復制給目標對象,目標對象有的就修改沒有就增加,這樣就實現了合并啦。

for循環之后在把新的目標對象返回,所以目標對象最后是被修改的,而且結果和返回的結果是一樣的。

 

復制代碼代碼如下:

// Return the modified object
    return target;
};

 

下面再來說說深度復制了怎么去處理

首先保證deep是true,copy有值并且是對象或者數組(如果不是對象和數組深度復制也就無從談起)然后再分數組和對象來處理,先來看數組的情況:

 

復制代碼代碼如下:

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

 

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

 

如果是數組copyIsArray的值為真然后走里面的 把值改成false ,針對當前循環的源對象屬性,目標對象可能有也可能沒有,有的話判斷一下是不是數組是的話就是原來的數組不變不是的話就讓它變成一個數組,因為既然源對象的當前屬性是數組最后目標元素也必須是數組。不是數組就是對象把目標對象當前屬性改成對象。

 

復制代碼代碼如下:

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

 

然后把源對象的當前屬性值(是數組或對象)和已經被改造過的目標對象的當前屬性進行遞歸合并最后返回的新的數組或者對象賦值給目標對象,最終實現了深度復制。

但是這里面還有一個比較奇怪的現象,比如這樣操作:

 

復制代碼代碼如下:

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

 

原來源對象不一定真的是對象e而且居然可以把字符串拆開跟目標對象合并,原來for...in循環是操作字符串的

 

復制代碼代碼如下:

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

 

這樣也是可以的,會把字符串拆開按數字下標讀取,但是在源碼中

 

復制代碼代碼如下:

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

 

是有數組和對象限制的,那么深度復制的時候是不是就沒有效果了呢?

經過我測試深度復制也是可以的,因為在源碼里面copy的值竟然變成了匿名函數函數

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

至于為什么是函數筆者還沒搞清楚留待以后解決吧!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
性欧美长视频免费观看不卡| 国产欧美日韩精品丝袜高跟鞋| 欧美性生交大片免网| 91久久久久久久| 性欧美长视频免费观看不卡| 欧美性生交xxxxxdddd| 成人亚洲激情网| 日本sm极度另类视频| 国产69精品99久久久久久宅男| 亚洲精品wwwww| 久久这里只有精品99| 欧美精品999| 日韩女优人人人人射在线视频| 日韩av网站导航| 国产亚洲精品久久久久久777| 国产精品久久久久久久7电影| 成人黄色免费网站在线观看| 亚洲女性裸体视频| 一区二区三区在线播放欧美| 久久夜色精品国产亚洲aⅴ| 91香蕉嫩草神马影院在线观看| xxxxx成人.com| 日韩在线www| 97avcom| 国产精品91久久久| 亚洲一区二区福利| 伊人久久大香线蕉av一区二区| 国产亚洲一区精品| 欧美大尺度激情区在线播放| 日本欧美国产在线| 日韩欧美一区二区三区| 岛国视频午夜一区免费在线观看| 成人自拍性视频| 久久99精品久久久久久噜噜| 8050国产精品久久久久久| 夜夜躁日日躁狠狠久久88av| 国产日韩在线亚洲字幕中文| 亚洲国模精品一区| 亚洲欧洲成视频免费观看| 国产精品美女在线| 97在线视频免费| 免费97视频在线精品国自产拍| 国产精品久久久久久久久久| 国产精品白嫩初高中害羞小美女| 成人亚洲综合色就1024| 中文日韩在线观看| 亚洲区在线播放| 欧美午夜影院在线视频| 日韩视频―中文字幕| 日韩男女性生活视频| 亚洲欧美在线第一页| 亚洲成人性视频| 精品无人区太爽高潮在线播放| 久久五月天色综合| 久久五月情影视| 欧美日韩激情美女| 国产精品免费小视频| 91麻豆国产语对白在线观看| 成人妇女淫片aaaa视频| 91沈先生在线观看| 91极品女神在线| 海角国产乱辈乱精品视频| 成人性生交大片免费观看嘿嘿视频| 亚洲自拍偷拍第一页| 好吊成人免视频| 日本精品性网站在线观看| 精品亚洲一区二区三区四区五区| 久久九九精品99国产精品| 亚洲图片在线综合| 性金发美女69hd大尺寸| 亚洲小视频在线观看| 亚洲精品视频免费| 大荫蒂欧美视频另类xxxx| 欧美日本精品在线| 欧美日韩国产激情| xvideos亚洲人网站| 51精品国产黑色丝袜高跟鞋| 欧美大尺度在线观看| 欧美成人网在线| 成人免费视频网| 欧美日韩亚洲一区二| 久久久久久久一| 久久精品成人一区二区三区| 91av视频在线播放| 午夜精品久久久久久久久久久久久| 91久久综合亚洲鲁鲁五月天| 久久久女女女女999久久| 久久综合免费视频影院| 成人黄色av免费在线观看| 欧美一级电影免费在线观看| www.亚洲天堂| 日韩在线欧美在线| 亚洲精品狠狠操| 美女扒开尿口让男人操亚洲视频网站| 久久久国产精品亚洲一区| 国产亚洲精品久久久| 亚洲xxxx在线| 欧美美女18p| 91沈先生作品| 精品无码久久久久久国产| 中文字幕亚洲一区二区三区五十路| 色阁综合伊人av| 热99久久精品| 国产精品亚洲自拍| 欧美国产乱视频| 欧美激情一区二区久久久| 亚洲男人的天堂在线播放| 91精品视频在线播放| 8x海外华人永久免费日韩内陆视频| 国产日韩av高清| 亚洲免费视频一区二区| 精品偷拍一区二区三区在线看| 日韩美女视频中文字幕| 亚洲国产成人精品电影| 中文字幕九色91在线| 91禁国产网站| 欧美性猛交xxxx乱大交| 91网站免费观看| 欧美视频在线视频| 日韩美女视频免费在线观看| 亚洲福利在线视频| 欧美日韩国产色| 欧美在线观看网站| 成人一区二区电影| 18性欧美xxxⅹ性满足| 久久青草精品视频免费观看| 深夜精品寂寞黄网站在线观看| 亚洲国产精品美女| 国产欧美精品一区二区三区介绍| 日韩免费电影在线观看| 日韩视频免费看| 欧美最猛黑人xxxx黑人猛叫黄| 国产v综合v亚洲欧美久久| 欧美激情影音先锋| 欧美电影第一页| 2021国产精品视频| 中文字幕欧美视频在线| 一区二区成人精品| 91sa在线看| 在线丨暗呦小u女国产精品| 国产极品jizzhd欧美| 亚洲xxxx在线| 亚洲va久久久噜噜噜| 欧美性色19p| 国产欧美日韩91| 精品久久久久久中文字幕大豆网| 日本道色综合久久影院| 欧美激情综合亚洲一二区| 亚洲精品理论电影| 热re99久久精品国产66热| 国产美女主播一区| 久久中文精品视频| 亚洲欧美资源在线| 中文国产成人精品久久一| 亚洲精品国产综合区久久久久久久| 国产欧美日韩综合精品| 色综合导航网站| 国产精品福利无圣光在线一区| 国产亚洲视频中文字幕视频| 国产成人精品电影久久久| 久久香蕉国产线看观看av| 2019日本中文字幕| 91在线网站视频| 久久中文字幕在线|