Java程式員的JavaScript學習筆記(9—— jQuery工具方法)

來源:互聯網
上載者:User

Java程式員的JavaScript學習筆記(9—— jQuery工具方法)

計劃按如下順序完成這篇筆記:

1. 理念。
2. 屬性複製和繼承。
3. this/call/apply。
4. 閉包/getter/setter。
5. prototype。
6. 物件導向類比。
7. jQuery基本機制。
8. jQuery選取器。
9. jQuery工具方法。
10. jQuery-在“類”層面擴充。
11. jQuery-在“對象”層面擴充。
12. jQuery-延伸選取器。
13. jQuery UI。
14. 擴充jQuery UI。

這是筆記的第9篇,從jQuery源碼的角度,聊聊jQuery的工具方法。


作者部落格:http://blog.csdn.net/stationxp

作者微博:http://weibo.com/liuhailong2008

轉載請取得作者同意


1、先看幾個工具方法如何使用:

var t = $.trim('   >>_<<   ');var ps = $.param({x:15,y:16});jQuery.type(function(){}) === "function"

jQuery的工具方法,相對jQuery本身,是相對獨立的。

2、這些方法是如何定義的呢?
我們猜測一下,試試看。
我們知道jQuery(即$)是全域變數,這些方法應該是jQuery變數的屬性。
我們可以通過如下文法添加:

jQuery.xx = function(a,b){ return a + b;}// tryvar r1 = jQuery.xx(2,3);console.log(r1);// output : 5var r2 = $.xx(3,3);console.log(r2);// output : 6
上面代碼,說明$和jQuery引用了相同變數,他們是一樣一樣的。
這些代碼達到了定義工具方法的目的,但jQuery是這樣做的嗎?

3、
查看jQuery原始碼,jQuery通過如下文法定義工具方法:

jQuery.extend({ noConflict: function( deep ) {  if ( window.$ === jQuery ) {window.$ = _$;  }  if ( deep && window.jQuery === jQuery ) {window.jQuery = _jQuery;  }  return jQuery; } //, ... });

extend方法定義如下:

//定義了一個方法,賦值給jQuery.fn.extend和jQuery.extend.//jQuery.fn.extend和jQuery.extend雖然定義相同,但調用者不同,從而方法中this指向不同,從而實現的功能不同。//沒有顯式聲明參數,而是通過arguments動態獲得,從而支援更豐富的功能。jQuery.extend = jQuery.fn.extend = function() {      var src, copyIsArray, copy, name, options, clone,            // 將第一個參數作為目標對象            target = arguments[0]      || {},            // i初始化為1,暫時還不知道做什麼用            i = 1,            // length表示參數的個數            length = arguments.length,            // deep 應該表示是否深層拷貝,預設為否。            deep = false;      // Handle a deep copy situation      if ( typeof      target === "boolean" ) {            //如果第一個參數是布爾類型,則第二個參數為目標對象            //形如:jQuery.extend(false,UiObject,...);            deep = target;            target = arguments[1] || {};            // i 是當前參數的數組下標,從0開始            i = 2;      }     //目標對象是能是函數或者對象,傳入其他參數,target預設為空白對象。      if      ( typeof target !== "object" && !jQuery.isFunction(target) ) {            target = {};      }      // 目前,如果第一個參數不是布爾,i值為1,length也為1,即extend(obj)的情況      // 如果是布爾,i值為2,length也為2,即extend(true,obj)的情況      // 總之,沒有傳入      src            if      ( length === i ) {            // jQuery      把傳入參數收了            // 參數下標重新指向傳入的這個參數,即此時指向了src            target = this;            --i;      }      // 現在i指向了target後面某個參數,應該是src      // 把後面傳入的每個參數都當src      for      ( ;i < length; i++ ) {            //      Only deal with non-null/undefined values            // 這樣過濾非空啊,如果是undefined會被過濾掉嗎?            // 不做 typeof src 是否 "object"、"function"的判斷嗎?            if ( (options = arguments[ i ])      != null ) {                  // 賦值給變數 options                  // Extend      the      base      object                  for ( name in options ) {                        src = target[ name ];                        copy = options[ name ];                                                // 思慮萬全:如果已經是自家人,就別嘚瑟了                        // Prevent      never-ending      loop                        if      ( target === copy ) {                              continue;                        }                                                // 對普通對象和數組,考慮遞迴深層拷貝                        // 問題來了,什麼叫普通對象? function 算不算?                        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      : {};                              }                              //遞迴調                              //如果寫成 jQuery.extend( deep, clone, copy )      是否一樣                              //      Never      move      original      objects, clone      them                              target[ name ] = jQuery.extend( deep, clone, copy );                        //      Don't bring in undefined      values                        //      對      undefined      和      != null      還要加深理解                        }      else if ( copy !== undefined ) {                              // 臨門一腳,如果是      jQuery.extend({xx,xfasf});的情況,擴充的是this,即調用者。                              // 對target直接修改,也沒建立clone啥的                              target[ name ] = copy;                        }                  }            }      }      // Return the modified object      return target;};

4、再看看jQuery.isPlainObject如何定義的

 isPlainObject: function( obj ) {    // Must be an Object.  // Because of IE, we also have to check the presence of the constructor property.  // Make sure that DOM nodes and window objects don't pass through, as well  // 翻譯:  // 必須是一個對象。  // 因為IE的緣故,我們還必須檢查是否有constructor屬性。  // 確認別放過Dom節點和window對象,他們不是普通對象。  if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {   // 以下不通過空、undefined、0、jQuery.type返回不是object的、dom對象、window對象   // 所以 typeof 為string、number、function、正則、date的都不成   return false;  }  try {   // Not own constructor property must be Object   if ( obj.constructor &&!core_hasOwn.call(obj, "constructor") &&!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {return false;   }  } catch ( e ) {   // IE8,9 Will throw exceptions on certain host objects #9897   return false;  }  // 枚舉的時候,自有屬性會先被枚舉出來,如果最後一個屬性是自有屬性,那麼所有屬性都是自有屬性。  // 簡而言之,不能有繼承來的,可以被枚舉到的屬性,你妹!為什麼有這樣的要求?  // Own properties are enumerated firstly, so to speed up,  // if last one is own, then all properties are own.  var key;  for ( key in obj ) {}  return key === undefined || core_hasOwn.call( obj, key ); }

5、
試試看

jQuery.extend({ sayHi:function(you){  console.log('hi',you); }});$.sayHi('Stanley'); // output : hi Stanley

還不錯!如果想覆蓋jQuery已有的方法呢?

jQuery.extend({ isPlainObject:function(obj){return 'baby, I am not sure.'; }});var r = $.isPlainObject({});console.log(r); // output : baby, I am not sure.

這...好吧,可以得逞。想想別的辦法吧,不能這樣。

再玩兒:

jQuery.extend({ extend:function(obj){  // do nothing  return 'who am i?'; }});var r = $.extend({x:function(){ alert();}});console.log(r); // output : who am i?jQuery.x();// error : function not be defined

又得逞,這樣,再沒人可以通過extend擴充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.