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

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

 更新時間:2015年06月03日 12:06:40   投稿:hebedich  
jQuery自定義了jQuery.extend()和jQuery.fn.extend()方法.其中jQuery.extend()方法能夠創(chuàng)建全局函數(shù)或者選擇器,而jQuery.fn.extend()方法能夠創(chuàng)建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內部添加實例屬性和方法以及原型屬性和方法的實現(xiàn)方法也是編寫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,
    .....

在這個例子中只傳入了一個對象參數(shù),那么默認就把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源碼中是怎么實現(xiàn)的:

復制代碼 代碼如下:

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

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

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

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

復制代碼 代碼如下:

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

判斷是不是深度復制,如果第一個參數(shù)是布爾值那么就把第一個參數(shù)的值給deep,然后把第二個參數(shù)作為目標對象,如果第二個參數(shù)不存在就賦值為一個空對象,把源對象的下標改為2,在這個例子里面  是走這里的因為第一個參數(shù)是ture然后把deep變成了true ,target被修正成了第二個參數(shù)也即是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又進一步進行了處理對于非對象和函數(shù)的數(shù)據(jù)類型而言增加自定義屬性是無效的比如字符串自能調用自帶的方法和屬性

復制代碼 代碼如下:

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

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

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

兩種可能的情況:$.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個下標值開始循環(huán)操作首先過濾掉源對象是null或者是undefined的情況可以看到其實

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

復制代碼 代碼如下:

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

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

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

Object {a: Object}

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

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

復制代碼 代碼如下:

target[ name ] = copy;

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

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

復制代碼 代碼如下:

// Return the modified object
    return target;
};

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

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

復制代碼 代碼如下:

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

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

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

復制代碼 代碼如下:

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

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

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

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

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

復制代碼 代碼如下:

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

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

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

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

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

相關文章

  • 詳解Jquery Easyui的驗證擴展

    詳解Jquery Easyui的驗證擴展

    本文主要介紹了Jquery Easyui驗證擴展,Easyui驗證,Easyui校驗,js正則表達式。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • Android中的jQuery:AQuery簡介

    Android中的jQuery:AQuery簡介

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

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

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

    JavaScript對象之間的轉換 jQuery對象和原聲DOM

    jQuery對象和原聲DOM,JavaScript對象之間的轉換,學習jquery的朋友可以參考下。
    2011-03-03
  • jQuery日歷插件datepicker用法詳解

    jQuery日歷插件datepicker用法詳解

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

    jQuery模仿單選按鈕選中效果

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

    jQuery中slidedown與slideup方法用法示例

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

    jQuery中DOM 屬性使用實例詳解下篇

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

    EasyUi 打開對話框后控件賦值及賦值后不顯示的問題解決辦法

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

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

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

最新評論