成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

詳解jQuery構造器的實現

開發 前端
jQuery的$符號非常神奇,它可以接受一個字符,也可以接受一個文檔對象或window對象,亦可以傳個函數進行變為domReady加載器。顯然,能做到這一步,其實現是相當的復雜,這個實現就是它的init方法,jQuery的真實構造器。它功能也隨著版本的升級而升級,越來越長。

2009-01-13發布的1.3版

  1. init: function( selector, context ) {    
  2.  // Make sure that a selection was provided    
  3.     selector = selector || document;    
  4.  
  5.  
  6.     // 處理節點參數,直接添加屬性到新實例上    
  7.     if ( selector.nodeType ) {    
  8.         this[0] = selector;    
  9.         this.length = 1;    
  10.         this.context = selector;    
  11.         return this;    
  12.     }    
  13.     // 處理字符串參數    
  14.     if ( typeof selector === "string" ) {    
  15.         // 判定是否為HTML片斷還是ID    
  16.         var match = quickExpr.exec( selector );    
  17.             if ( match && (match[1] || !context) ) {    
  18.              // 如果是HTML片斷,轉換一個由節點構造的數組    
  19.             if ( match[1] )    
  20.                selector = jQuery.clean( [ match[1] ], context );       
  21.             // 如果是ID,則查找此元素,如果找到放進空數組中    
  22.             else {    
  23.                 var elem = document.getElementById( match[3] );     
  24.                 // Make sure an element was located    
  25.                 if ( elem ){    
  26.                     // 處理 IE and Opera 混淆ID與NAME的bug    
  27.                     if ( elem.id != match[3] )    
  28.                         return jQuery().find( selector );    
  29.                     var ret = jQuery( elem );    
  30.                     ret.context = document;    
  31.                     ret.selector = selector;    
  32.                     return ret;    
  33.                 }    
  34.                 selector = [];    
  35.             }    
  36.         } else   
  37.         //使用Sizzle處理其他CSS表達式,生成實例并返回    
  38.             return jQuery( context ).find( selector );    
  39.         // 處理函數參數,直接domReady    
  40.     } else if ( jQuery.isFunction( selector ) )    
  41.         return jQuery( document ).ready( selector );    
  42.      //處理jQuery對象參數,簡單地將其兩個屬性賦給新實例    
  43.     if ( selector.selector && selector.context ) {    
  44.         this.selector = selector.selector;    
  45.         this.context = selector.context;    
  46.     }    
  47.     //將上面得到節點數組,用setArray方法把它們變成實例的元素    
  48.     return this.setArray(jQuery.makeArray(selector));    
  49. },  

2009-02-19發布的1.32版

  1. init: function( selector, context ) {    
  2.     // Make sure that a selection was provided    
  3.     selector = selector || document;    
  4.     // 處理節點參數,直接添加屬性到新實例上    
  5.     if ( selector.nodeType ) {    
  6.         this[0] = selector;    
  7.         this.length = 1;    
  8.         this.context = selector;    
  9.         return this;    
  10.     }    
  11.      //處理字符串參數    
  12.     if ( typeof selector === "string" ) {    
  13.         //判定是否為HTML片斷還是ID    
  14.         var match = quickExpr.exec( selector );    
  15.         if ( match && (match[1] || !context) ) {    
  16.            // 如果是HTML片斷,轉換一個由節點構造的數組    
  17.             if ( match[1] )    
  18.                 selector = jQuery.clean( [ match[1] ], context );    
  19.             else {    
  20.                 var elem = document.getElementById( match[3] );    
  21.  
  22.                 // 如果是ID,則查找此元素,如果找到放進空數組中    
  23.                 if ( elem && elem.id != match[3] )    
  24.                   return jQuery().find( selector );    
  25.                    //這里對1.3版做了些優化,更簡潔    
  26.                 var ret = jQuery( elem || [] );    
  27.                 ret.context = document;    
  28.                 ret.selector = selector;    
  29.                 return ret;    
  30.             }    
  31.         } else   
  32.             //使用Sizzle處理其他CSS表達式,生成實例并返回    
  33.             return jQuery( context ).find( selector );    
  34.            // 處理函數參數,進行domReady操作    
  35.     } else if ( jQuery.isFunction( selector ) )    
  36.         return jQuery( document ).ready( selector );    
  37.         //處理jQuery對象參數,簡單地將其兩個屬性賦給新實例    
  38.     if ( selector.selector && selector.context ) {    
  39.         this.selector = selector.selector;    
  40.         this.context = selector.context;    
  41.     }    
  42. //這里對1.3版做了些擴展,允許傳珍上元素集合(HTMLCollection)與節點集合(NodeList),    
  43. //元素數組可能是我們用字符串轉換過來的,也可以是用戶直接傳進來的    
  44.     return this.setArray(jQuery.isArray( selector ) ? selector : jQuery.makeArray(selector));    
  45. },   

2010-01-13發布的1.4版

  1. init: function( selector, context ) {    
  2.     var match, elem, ret, doc;    
  3.     //處理空白字符串,null,undefined參數(新增),返回一個非常純凈的實例    
  4.     if ( !selector ) {    
  5.         return this;    
  6.     }    
  7.     // 處理節點參數,直接添加屬性到新實例上    
  8.     if ( selector.nodeType ) {    
  9.         this.context = this[0] = selector;//寫法上優化    
  10.         this.length = 1;    
  11.         return this;    
  12.     }    
  13.     //處理字符串參數    
  14.     if ( typeof selector === "string" ) {    
  15.         //  判定是否為HTML片斷還是ID    
  16.         match = quickExpr.exec( selector );    
  17.         if ( match && (match[1] || !context) ) {    
  18.             //如果是HTML片斷    
  19.             if ( match[1] ) {    
  20.                 //取得文檔對象    
  21.                 doc = (context ? context.ownerDocument || context : document);    
  22.                 // 如果是單個標簽,直接使用 document.createElement創建此節點并放入數組中    
  23.                 ret = rsingleTag.exec( selector );    
  24.                 if ( ret ) {    
  25.                     //如果后面跟著一個純凈的JS對象,則為此節點添加相應的屬性或樣式    
  26.                     if ( jQuery.isPlainObject( context ) ) {    
  27.                         selector = [ document.createElement( ret[1] ) ];    
  28.                         jQuery.fn.attr.call( selector, context, true );    
  29.                     } else {    
  30.                         selector = [ doc.createElement( ret[1] ) ];    
  31.                     }    
  32.                 } else {    
  33.                     //改由buildFragment來生成節點集合(NodeList)    
  34.                     ret = buildFragment( [ match[1] ], [ doc ] );    
  35.                     selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;    
  36.                 }    
  37.             } else {    
  38.                 // 如果是ID,則查找此元素,如果找到放進空數組中    
  39.                 elem = document.getElementById( match[2] );    
  40.                 if ( elem ) {   
  41.                     // 處理 IE and Opera 混淆ID與NAME的bug    
  42.                     if ( elem.id !== match[2] ) {    
  43.                         return rootjQuery.find( selector );    
  44.                     }    
  45.                     //這里也做了一些優化,原來是很傻地再生成一個jQuery實例    
  46.                     this.length = 1;    
  47.                     this[0] = elem;    
  48.                 }    
  49.                 this.context = document;    
  50.                 this.selector = selector;    
  51.                return this;    
  52.             }      
  53.  
  54.             // 如果字符是很簡單的標簽選擇器,那基本沒有必要走Sizzle路線,直接getElementsByTagName,很好的優化    
  55.         } else if ( !context && /^\w+$/.test( selector ) ) {    
  56.             this.selector = selector;    
  57.             this.context = document;    
  58.             selector = document.getElementsByTagName( selector );    
  59.             // 如果第二個參數不存在或者是jQuery對象,那么用它或rootjQuery調用find查找目標節點(走Sizzle路線)    
  60.         } else if ( !context || context.jquery ) {    
  61.             return (context || rootjQuery).find( selector );    
  62.             // HANDLE: $(expr, context)    
  63.             // (which is just equivalent to: $(context).find(expr)    
  64.         } else {    
  65.             //如果第二個參數已指定為某元素節點,轉為jQuery對象,走Sizzle路線    
  66.             return jQuery( context ).find( selector );    
  67.         }    
  68.            // 處理函數參數,直接domReady    
  69.     } else if ( jQuery.isFunction( selector ) ) {    
  70.         return rootjQuery.ready( selector );    
  71.     }    
  72.     //處理jQuery對象參數,簡單地將其兩個屬性賦給新實例    
  73.     if (selector.selector !== undefined) {    
  74.         this.selector = selector.selector;    
  75.         this.context = selector.context;    
  76.     }    
  77.  
  78. //這里又做了些許修改,緣于makeArray可以接受第二個參數(可以是數組或類數組,這時相當合并操作)    
  79.     return jQuery.isArray( selector ) ?    
  80.         this.setArray( selector ) ://內部用push方法,迅速將一個普通對象變成類數組對象    
  81.         jQuery.makeArray( selector, this );    
  82. },  

接著是廣受歡迎的2010-02-13發布的1.42版

  1. init: function( selector, context ) {    
  2.     var match, elem, ret, doc;   
  3.     // 處理空白字符串,null,undefined參數    
  4.     if ( !selector ) {    
  5.         return this;    
  6.     }    
  7.     // 處理節點參數    
  8.     if ( selector.nodeType ) {    
  9.         this.context = this[0] = selector;    
  10.         this.length = 1;    
  11.         return this;    
  12.     }       
  13.     // 處理body參數(新增)    
  14.     if ( selector === "body" && !context ) {    
  15.         this.context = document;    
  16.         this[0] = document.body;    
  17.         this.selector = "body";    
  18.         this.length = 1;    
  19.         return this;    
  20.     }    
  21.     // 處理字符串參數,分七種情形:    
  22.     //①單個標簽,帶對象屬性包           --->   jQuery.merge    
  23.     //②單個標簽,不帶對象屬性包         --->   attr + jQuery.merge    
  24.     //③復雜的HTML片斷                 --->   buildFragment + jQuery.merge    
  25.     //④ID選擇器,與找到的元素的ID不同   --->   getElementById + Sizzle + pushStack    
  26.     //⑤ID選擇器,與找到的元素的ID相同   --->   getElementById + 簡單屬性添加    
  27.     //⑥標簽選擇器                     --->   getElementsByTagName + jQuery.merge    
  28.     //⑦其他CSS表達式                  --->   Sizzle + pushStack    
  29.     if ( typeof selector === "string" ) {    
  30.         match = quickExpr.exec( selector );    
  31.         if ( match && (match[1] || !context) ) {    
  32.             if ( match[1] ) {    
  33.                 doc = (context ? context.ownerDocument || context : document);    
  34.                 ret = rsingleTag.exec( selector );    
  35.                 if ( ret ) {    
  36.                   if ( jQuery.isPlainObject( context ) ) {    
  37.                         selector = [ document.createElement( ret[1] ) ];    
  38.                         jQuery.fn.attr.call( selector, context, true );    
  39.                     } else {    
  40.                         selector = [ doc.createElement( ret[1] ) ];    
  41.                     }    
  42.                 } else {    
  43.                     ret = buildFragment( [ match[1] ], [ doc ] );    
  44.                     selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;    
  45.                 }    
  46.                 return jQuery.merge( this, selector );    
  47.             } else {    
  48.                 elem = document.getElementById( match[2] );    
  49.                 if ( elem ) {    
  50.                     if ( elem.id !== match[2] ) {    
  51.                         return rootjQuery.find( selector );    
  52.                     }    
  53.                     this.length = 1;    
  54.                     this[0] = elem;    
  55.                 }    
  56.                 this.context = document;    
  57.                 this.selector = selector;    
  58.                 return this;    
  59.             }    
  60.         } else if ( !context && /^\w+$/.test( selector ) ) {    
  61.             this.selector = selector;    
  62.             this.context = document;    
  63.             selector = document.getElementsByTagName( selector );    
  64.             return jQuery.merge( this, selector );    
  65.         } else if ( !context || context.jquery ) {    
  66.             return (context || rootjQuery).find( selector );    
  67.         } else {    
  68.            return jQuery( context ).find( selector );    
  69.         }    
  70.         // 處理函數參數,直接domReady    
  71.     } else if ( jQuery.isFunction( selector ) ) {    
  72.         return rootjQuery.ready( selector );    
  73.     }    
  74.     //處理jQuery對象參數    
  75.     if (selector.selector !== undefined) {    
  76.         this.selector = selector.selector;    
  77.         this.context = selector.context;    
  78.     }    
  79.     //無論是數組還是類數組(如NodeList),統統使用jQuery.makeArray來為實例添加新的元素    
  80.     return jQuery.makeArray( selector, this );    
  81. },   

另附上makeArray方法與merge方法,merge方法好神奇啊

  1. makeArray: function( array, results ) {    
  2.     var ret = results || [];     
  3.     if ( array != null ) {    
  4.         // The window, strings (and functions) also have 'length'    
  5.         // The extra typeof function check is to prevent crashes    
  6.         // in Safari 2 (See: #3039)    
  7.         if ( array.length == null || typeof array === "string" || jQuery.isFunction(array) || (typeof array !== "function" && array.setInterval) ) {    
  8.             push.call( ret, array );    
  9.         } else {    
  10.             jQuery.merge( ret, array );    
  11.         }    
  12.     }    
  13.     return ret;    
  14. },    
  15. merge: function( first, second ) {    
  16.     var i = first.length, j = 0;     
  17.     if ( typeof second.length === "number" ) {    
  18.         for ( var l = second.length; j < l; j++ ) {    
  19.             first[ i++ ] = second[ j ];    
  20.         }    
  21.     } else {    
  22.         while ( second[j] !== undefined ) {    
  23.             first[ i++ ] = second[ j++ ];    
  24.         }    
  25.     }    
  26.     first.length = i;    
  27.     return first;    
  28. },  

2011-01-23發布的1.5版,其init方法與1.42的變化不大:只有兩處做了改動:

  1. //1.42    
  2. -  ret = buildFragment( [ match[1] ], [ doc ] );    
  3. -  selector = (ret.cacheable ? ret.fragment.cloneNode(true) : ret.fragment).childNodes;    
  4. //1.5    
  5. + ret = jQuery.buildFragment( [ match[1] ], [ doc ] );    
  6. + selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;    
  7. //1.42    
  8. return jQuery( context ).find( selector );    
  9. //1.5    
  10. return this.constructor( context ).find( selector );//目的就是為了不再生成新實例   

2011-05-02發布的jquery1.6,變化不大,只是對HTML片斷進行了更嚴密的判定:

  1. // Are we dealing with HTML string or an ID?    
  2.    if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {    
  3.   // Assume that strings that start and end with <> are HTML and skip the regex check    
  4.     match = [ null, selector, null ];    
  5.    } else {    
  6.     match = quickExpr.exec( selector );    
  7.    }   

總體來說,jQuery的構造器已經做得非常之***,基本上達到“改無可改”的地步了。但是要保證其高效運作,我們還需要一點選擇器的知識與了解buildFragment方法的運作,因為這兩個實在太常用了,但也是最耗性能的。

原文鏈接:http://www.cnblogs.com/rubylouvre/archive/2011/05/15/2046593.html

【編輯推薦】

  1. jQuery調用WCF開發實例經驗分享
  2. 5月***超有趣的免費jQuery插件推薦
  3. 從零開始學習jQuery之管理jQuery包裝集
  4. jQuery性能指標和調優
  5. 手把手教你jQuery jqPlot畫圖插件
責任編輯:陳貽新 來源: 司徒正美
相關推薦

2009-07-21 12:35:00

Scala從構造器

2022-04-15 08:30:00

Lombok@Builde構建器

2009-07-17 17:41:41

SwingWorker

2012-05-16 13:45:24

Java構造器

2010-12-03 09:55:31

PHP構造方法

2011-08-22 16:19:58

jQuery

2009-07-24 11:01:12

jQuery框架

2011-08-17 10:58:59

Objective-C構造函數

2009-08-14 09:27:27

C#構造函數的特性

2012-05-14 10:18:54

jQuery

2010-06-08 17:42:50

UML構造塊

2019-10-22 08:45:07

Java構造器編程語言

2009-09-15 17:58:00

2010-04-01 17:43:56

Oracle實現跨服務

2009-03-04 13:10:41

SQL語句INSERTDELETE

2011-08-24 16:41:38

lua調試器

2011-08-31 16:39:06

Lua調試器

2011-10-10 09:35:54

云計算服務器

2016-11-01 09:24:38

Python裝飾器

2009-11-20 18:56:17

路由器功能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品成人一区二区三区 | 欧美区日韩区 | 国产精品99久久久久久久vr | 日韩中文字幕免费在线 | 羞羞的视频免费在线观看 | 成人免费视频 | 欧美日韩91 | 国产精品美女久久久久久不卡 | 一本大道久久a久久精二百 欧洲一区二区三区 | 亚洲精品久久久久久久久久久久久 | 午夜视频网站 | 国产在线激情视频 | 91久久久久久久久 | 日韩91 | 久草热8精品视频在线观看 午夜伦4480yy私人影院 | 爱草视频 | 一区二区三区在线免费观看视频 | 超碰一区二区 | 国产乱码精品一区二区三区中文 | 99re视频这里只有精品 | 在线欧美日韩 | 在线第一页 | 国产一区二区在线看 | 91精品国产一区二区三区动漫 | 97操操| 久久精品a级毛片 | 免费在线观看av片 | 毛片在线免费 | 成人免费精品视频 | 久久中文字幕一区 | 国产精品久久久久aaaa | 国产高清视频一区 | 久久久久久成人网 | 国产精品久久久久久吹潮 | 日本成人免费网站 | 免费中文字幕日韩欧美 | 呦呦在线视频 | 精品国产一区二区在线 | 黄色大片观看 | 日韩在线精品视频 | 欧美性极品xxxx做受 |