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

首頁 > 編程 > JavaScript > 正文

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

2019-11-20 12:22:24
字體:
來源:轉載
供稿:網友

這兩個方法用的是相同的代碼,一個用于給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
国产精品久久久久久久久影视| 欧美成人免费小视频| 国产精品欧美日韩久久| 国产成人精品一区二区在线| 中文字幕亚洲欧美日韩高清| 欧美在线欧美在线| 日韩av影视在线| 欧美激情va永久在线播放| 中文字幕免费国产精品| 国产区亚洲区欧美区| 久久这里只有精品99| 国产精品久久91| 日本午夜精品理论片a级appf发布| 精品久久久免费| 九九久久久久久久久激情| 亚洲国产欧美一区二区丝袜黑人| 91精品久久久久久久久| 69国产精品成人在线播放| 国产在线视频一区| 国精产品一区一区三区有限在线| 色悠悠久久88| 国产99视频精品免视看7| www.欧美三级电影.com| 免费av一区二区| 亚洲女在线观看| 亚洲国产成人精品一区二区| 成人乱人伦精品视频在线观看| 在线观看免费高清视频97| 欧美疯狂xxxx大交乱88av| 日韩精品在线电影| 日韩在线视频线视频免费网站| 欧美激情视频一区二区三区不卡| 国产精品视频一区二区高潮| 久久99视频精品| 亚洲精品www久久久| 成人天堂噜噜噜| 国产成人欧美在线观看| 亚洲一区二区三区乱码aⅴ| 韩剧1988在线观看免费完整版| 国产成人一区二区三区| 欧美性猛交xxxxx免费看| 欧美在线视频免费观看| 日日摸夜夜添一区| 午夜剧场成人观在线视频免费观看| 亚洲欧美国产视频| 久久亚洲精品小早川怜子66| 日韩国产欧美精品一区二区三区| 国产精品69久久久久| 久久精品成人一区二区三区| 日韩亚洲欧美中文在线| 亚洲视频在线看| 欧美国产一区二区三区| 精品人伦一区二区三区蜜桃网站| 国产视频精品xxxx| 亚洲国产精品久久| 日韩精品视频在线观看免费| 69久久夜色精品国产7777| 最近2019年手机中文字幕| 久久久久日韩精品久久久男男| 国产日韩精品视频| 久久亚洲欧美日韩精品专区| 精品久久久久久中文字幕大豆网| 国产最新精品视频| 欧洲成人免费aa| 久久精品视频免费播放| 黄网站色欧美视频| 久久精品99久久久久久久久| 亚洲第一男人av| 成人黄色大片在线免费观看| 欧美激情乱人伦| 欧美激情视频一区二区| 中文字幕不卡在线视频极品| 色偷偷偷亚洲综合网另类| 久久久精品美女| 富二代精品短视频| 欧美亚洲另类视频| 91黄色8090| 亚洲国产免费av| 国产精品高清在线| 亚洲日本中文字幕免费在线不卡| 亚洲女人被黑人巨大进入| 日韩欧美国产中文字幕| 日韩精品福利网站| 精品国产欧美一区二区五十路| 高潮白浆女日韩av免费看| 亚洲伊人久久大香线蕉av| 久久精品国产2020观看福利| 日韩在线视频一区| 久久久久久欧美| 97视频在线观看视频免费视频| 亚洲国产精品久久久| 亚州精品天堂中文字幕| 午夜精品一区二区三区在线播放| 国产有码在线一区二区视频| 国产69精品久久久| 日韩电影大片中文字幕| 亚洲xxx自由成熟| 国产精品夜色7777狼人| 欧美猛交ⅹxxx乱大交视频| 亲子乱一区二区三区电影| 一本久久综合亚洲鲁鲁| 久久精品99无色码中文字幕| 国产欧美日韩精品专区| 成人一区二区电影| 久久91亚洲精品中文字幕奶水| 国产精品成人一区| 91性高湖久久久久久久久_久久99| 久久99精品久久久久久噜噜| 久久成人综合视频| 欧美激情视频网址| 国产精品99久久久久久白浆小说| 日韩禁在线播放| 一本大道香蕉久在线播放29| 日韩激情av在线播放| 日韩成人在线免费观看| 伊人久久大香线蕉av一区二区| 亚洲毛片在线看| 国产精品久久在线观看| 在线亚洲午夜片av大片| 色综合伊人色综合网站| 亚洲精品网站在线播放gif| 中文字幕亚洲欧美日韩2019| 国产激情久久久久| 亚洲精品国产精品自产a区红杏吧| 亚洲人成伊人成综合网久久久| 91精品免费看| 孩xxxx性bbbb欧美| 亚洲国产欧美一区二区三区同亚洲| 8x海外华人永久免费日韩内陆视频| 尤物yw午夜国产精品视频明星| 久久久久成人网| 日韩在线免费视频| 久久视频在线直播| 一区二区在线视频播放| 国产精品第10页| 久久影视电视剧免费网站清宫辞电视| 日韩在线中文字幕| 日韩精品久久久久久福利| 日韩精品亚洲精品| 7m第一福利500精品视频| 91在线观看免费观看| 成人黄色激情网| 亚洲精品白浆高清久久久久久| 2018中文字幕一区二区三区| 日韩电影在线观看中文字幕| 国产一区二区在线免费视频| 欧洲成人免费视频| 国产精品国产亚洲伊人久久| 国产美女精品视频| 伊人久久久久久久久久久| 国产精品人成电影| 欧美电影《睫毛膏》| 日韩久久精品成人| 98精品国产高清在线xxxx天堂| 亚洲欧美制服丝袜| 一个人看的www久久| 懂色av一区二区三区| 亚洲精品国精品久久99热| 亚洲国产日韩欧美在线99| 午夜精品久久久久久久99热浪潮| 亚洲黄色有码视频| 日韩成人中文电影| 久久久精品视频在线观看| 国产精品视频白浆免费视频|