久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

jquery1.43源碼分析之工具方法

 quasiceo 2012-11-23
這個(gè)部分是jquery一些常用的工具方法. 包括為jquery對(duì)象擴(kuò)展了一些數(shù)組里的方法.一些測(cè)試方法,函數(shù)代理和瀏覽器的特性檢測(cè).

數(shù)組和對(duì)象操作.這部分的很多方法都已經(jīng)成為javascript1.6的標(biāo)準(zhǔn).

這部分包括一些原型函數(shù),靜態(tài)函數(shù),內(nèi)部函數(shù).
原型函數(shù)主要通過(guò)api暴露給外界. 靜態(tài)方法主要包含了原型方法的具體邏輯實(shí)現(xiàn). 內(nèi)部函數(shù)主要供內(nèi)部調(diào)用.
prototype上的方法一般設(shè)計(jì)得比較簡(jiǎn)單, 主要充當(dāng)一個(gè)控制層的作用. 而具體的實(shí)現(xiàn)邏輯, 大多數(shù)都放在了底層的靜態(tài)方法中. 這樣將來(lái)版本升級(jí)的時(shí)候, 一般只要修改靜態(tài)方法就可以了,跟api緊密耦合的prototype方法不會(huì)受到太多牽連.


這部分其中有一些方法已經(jīng)在jquery1.43源碼分析之核心部分寫(xiě)過(guò)了, 看看另外一些方法的實(shí)現(xiàn).

jQuery.isArray
Java代碼  收藏代碼
  1. isArray: function( obj ) {  
  2.         return toString.call(obj) === "[object Array]";  
  3.     }  

判斷對(duì)象是不是Array類型.這個(gè)簡(jiǎn)單的需求經(jīng)歷了漫長(zhǎng)的演變過(guò)程.
一般我們判斷對(duì)象類型, 會(huì)想到下面幾種方式.
1 typeof    typeof  只能判斷大概區(qū)分是不是對(duì)象類型, 不論是Array還是Date還是null,還是通過(guò)自定義構(gòu)造函數(shù)生成的對(duì)象.返回的都是object
2 instanceof和constructor  都非常容易在原型繼承中出現(xiàn)問(wèn)題,
比如
Java代碼  收藏代碼
  1. var A = function(){  
  2.           
  3. }  
  4. A.prototype = new Array;      
  5.   
  6. var a = new A;  
  7.   
  8. alert (a instanceof Array)   //true  

而且在不同的iframe中, 判斷也不準(zhǔn)確, 因?yàn)椴煌膇frame不共享原型鏈. instanceof和constructor自然也會(huì)失效.
3 后來(lái)就有了流行一時(shí)的鴨式變型. 如果一只鴨子, 它會(huì)呱呱叫, 也會(huì)像鴨子一樣走路. 那么就認(rèn)為它就是鴨子.
Java代碼  收藏代碼
  1. isArray: function(object) {     
  2. return object != null && typeof object == "object" &&    
  3.  'splice' in object && 'join' in object;     
  4. }    


不過(guò)也許有那么一只聰明的雞學(xué)會(huì)了呱呱叫, 也學(xué)會(huì)了像鴨子一樣走路.
比如 var a = {}; a.splice = 1; a.join = 2;

前面的方法顯然都不完美, 直到有個(gè)人發(fā)現(xiàn)了Object.prototype.toString.call(obj) === "[object Array]", 世界才變美好.其實(shí)就是利用toString方法來(lái)得到一個(gè)包含這個(gè)對(duì)象內(nèi)部屬性的字符串,這個(gè)字符串就包含了此對(duì)象構(gòu)造器的信息.



jQuery.prototype.each

顧名思義, each方法是對(duì)數(shù)組或者對(duì)象中的每個(gè)元素都做一些類似的操作. 我們?cè)诳丛创a之前先自己實(shí)現(xiàn)一個(gè)Array.prototype.each.
Java代碼  收藏代碼
  1. Array.prototype.each = function(fn){  
  2.     for (var i = 0, l = this.length; i < l; i++){  
  3.         fn(this[i]);  //當(dāng)前元素作為回調(diào)函數(shù)的參數(shù).  
  4.     }  
  5. };  
  6.   
  7. [123].each(function(i){  
  8.     alert (i);      //i 就是上面的 this[i]  
  9. })  

很簡(jiǎn)陋, 然后想想它有哪些不足.
1, 在回調(diào)函數(shù)里我不知道當(dāng)前循環(huán)到了第幾個(gè)元素.
2, 回調(diào)函數(shù)里的this指向了window, 這個(gè)沒(méi)任何意義.

所以現(xiàn)在來(lái)稍微改一下.
Java代碼  收藏代碼
  1. Array.prototype.each = function(fn){  
  2.     for (var i = 0, l = this.length; i < l; i++){  
  3.         fn.call(this[i], i, this[i]);  
  4.     }  
  5. };  
  6.   
  7. [123].each(function(i, n){  
  8.     alert ([this, i, n]);  
  9. })  


現(xiàn)在在回調(diào)函數(shù)里可以取到3個(gè)值, this指向當(dāng)前元素. i表示循環(huán)到了第幾個(gè). n也表示當(dāng)前元素. 當(dāng)然你也可以把this指向別的東西. jquery就指向了原始元素.
不過(guò)如果我想在循環(huán)之中退出怎么辦, 比如我找到了2, 就想退出循環(huán).那么再修改一下.

Java代碼  收藏代碼
  1. Array.prototype.each = function(fn){  
  2.     for (var i = 0, l = this.length; i < l; i++){  
  3.         if ( fn.call(this[i], i, this[i]) === false ) break;  //當(dāng)回調(diào)函數(shù)返回false的時(shí)候, 中止循環(huán).  
  4.     }  
  5. };  
  6.   
  7. [123].each(function(i, n){  
  8.     if (n >= 2) {  
  9.         return false;  
  10.     }  
  11.     alert (n)  
  12. })  

現(xiàn)在已經(jīng)基本達(dá)到目的了, 再來(lái)看看jquery里each的實(shí)現(xiàn).
Java代碼  收藏代碼
  1.  each: function( callback, args ) {  
  2.     return jQuery.each( this, callback, args );  
  3. },  

直接交給靜態(tài)方法jQuery.each來(lái)操作. 看看jQuery.each
Java代碼  收藏代碼
  1. jQuery.each  
  2. each: function( object, callback, args ) {  
  3. /* 
  4. object為目標(biāo)jquery對(duì)象, callback為回調(diào)函數(shù), args表示callback方法里的參數(shù), 如果不傳, 就為默認(rèn)的i(下標(biāo)), n(當(dāng)前元素). 
  5. */  
  6.    var name, i = 0,   //對(duì)象屬性名、 數(shù)組下標(biāo)  
  7.     length = object.length,  
  8.     isObj = length === undefined || jQuery.isFunction(object);  
  9. /* 
  10. isObj判斷object是單個(gè)對(duì)象還是數(shù)組, 如果是單個(gè)對(duì)象, 就遍歷它的屬性, 如是數(shù)組, 就循環(huán)每個(gè)元素. 
  11. */  
  12.   
  13. if ( args ) {   //如果給callback傳遞了參數(shù)  
  14.             if ( isObj ) {  //如果是單個(gè)對(duì)象  
  15.                 for ( name in object ) {   //遍歷屬性  
  16.                     if ( callback.apply( object[ name ], args ) === false ) {      
  17. /* 
  18. 執(zhí)行回調(diào)函數(shù), 如果回調(diào)函數(shù)返回false, 退出循環(huán). 回調(diào)函數(shù)里的參數(shù)為自己傳遞的args. 
  19. */  
  20.              break;  
  21.                     }  
  22.                 }  
  23.             } else {        //如果是數(shù)組  
  24.                 for ( ; i < length; ) {   //循環(huán)數(shù)組  
  25.                     if ( callback.apply( object[ i++ ], args ) === false ) {     //執(zhí)行回調(diào)函數(shù), 如果回調(diào)函數(shù)返回false, 退出循環(huán).  
  26.                         break;  
  27.                     }  
  28.                 }  
  29.             }  
  30.   
  31.         }  else {  //基本同上, 除了用i和value代替參數(shù)args  
  32.         if ( isObj ) {  
  33.                 for ( name in object ) {  
  34.                     if ( callback.call( object[ name ], name, object[ name ] ) === false ) {  
  35.                         break;  
  36.                     }  
  37.                 }  
  38.             } else {  
  39.                 for ( var value = object[0];  
  40.                     i < length && callback.call( value, i, value ) !== false; value = object[++i] ) {}  
  41.             }  
  42.         }  
  43.   
  44.         return object;  
  45.     },  

其實(shí)each方法還有一個(gè)小小的缺陷. 當(dāng)要遍歷一個(gè)對(duì)象的時(shí)候.
比如 { name: "John", lang: "JS" }這個(gè)對(duì)象. 這樣寫(xiě)是沒(méi)問(wèn)題的.
Java代碼  收藏代碼
  1. $.each( { name: "John", lang: "JS" }, function(i, n){  
  2.    alert( "Name: " + i + ", Value: " + n );  
  3. })  

但其實(shí)很多時(shí)候我們可能希望這樣寫(xiě)
Java代碼  收藏代碼
  1.   $({ name: "John", lang: "JS" }).each(function(i, n){  
  2.     alert( "Name: " + i + ", Value: " + n );  
  3. })  

但這樣寫(xiě)不行. 因?yàn)楝F(xiàn)在的目標(biāo)對(duì)象object實(shí)際上是一個(gè)經(jīng)過(guò)包裝了的jquery對(duì)象. 即使里面是單個(gè)元素, 它的length也為1. isObj為false. jquery不會(huì)遍歷它的屬性.

這個(gè)方法里的代碼其實(shí)也可以更精簡(jiǎn)一點(diǎn),2個(gè)大的條件分支完全可以合并成一個(gè).



jQuery.prototype.map

將一組元素轉(zhuǎn)換成其他數(shù)組(不論是否是元素?cái)?shù)組)

其實(shí)很容易聯(lián)想到, map方法就是讓集合里的每個(gè)元素都執(zhí)行一次同一個(gè)函數(shù), 把返回值填充到一個(gè)數(shù)組并返回這個(gè)新的數(shù)組.

看個(gè)例子
Java代碼  收藏代碼
  1. var ary = $.map( [0,1,2], function(n){  
  2.   return n + 4;  
  3. });   
  4.   
  5. alert (ary);  

ary已經(jīng)被轉(zhuǎn)化成為[4,5,6].

再看源碼
Java代碼  收藏代碼
  1. map: function( callback ) {  
  2.     return this.pushStack( jQuery.map(this, function( elem, i ) {  
  3.         return callback.call( elem, i, elem );  
  4.     }));  
  5. },  

看起來(lái)有一點(diǎn)點(diǎn)復(fù)雜, 其實(shí)callback.call( elem, i, elem )得到的是每個(gè)元素通過(guò)轉(zhuǎn)化之后的值.在jQuery.map里,這些值都會(huì)被填充進(jìn)一個(gè)新的數(shù)組.最后把原來(lái)的引用存入pushStack,方便回溯.


看看jquery.map
Java代碼  收藏代碼
  1. map: function( elems, callback, arg ) {  
  2.         var ret = [], value;   
  3.    //ret是待填充的數(shù)組.  
  4.    //value引用回調(diào)函數(shù)的返回值  
  5.         for ( var i = 0, length = elems.length; i < length; i++ ) {   
  6.             value = callback( elems[ i ], i, arg );    
  7. //執(zhí)行回調(diào)函數(shù). elems[ i ]表示當(dāng)前元素值, i表示當(dāng)前循環(huán)到了  
  8. //第幾個(gè)元素. arg參數(shù)是1.26版本里沒(méi)有的.只供內(nèi)部使用  
  9.             if ( value != null ) {   //當(dāng)返回值不為空時(shí).   
  10.                 ret[ ret.length ] = value;  //push進(jìn)新數(shù)組.  
  11.             }  
  12.         }  
  13.   
  14.         return ret.concat.apply( [], ret );    
  15.           
  16.     },  

注意value != null, 這里只有2個(gè)等號(hào), 意味著可以也過(guò)濾掉返回值為undefined的元素, 比如在map一堆dom節(jié)點(diǎn)的子節(jié)點(diǎn)時(shí), 如果某個(gè)元素沒(méi)有子節(jié)點(diǎn), 那個(gè)元素就會(huì)被過(guò)濾掉.
可以看測(cè)試代碼
Java代碼  收藏代碼
  1. <body>  
  2.         <div><span></span></div>  
  3.         <div><span></span></div>  
  4.         <div><span></span></div>  
  5.         <div><span></span></div>  
  6.         <div></div>  
  7. </body>  
  8.     <script>  
  9.           
  10.     var ary = $.map( document.getElementsByTagName('div'), function(n){  
  11.       return n.childNodes[0];  
  12.       
  13.     });   
  14.       
  15.     alert (ary.length)  
  16.     </script>  

jQuery.prototype.grep
使用一個(gè)過(guò)濾函數(shù)閉包來(lái)按照某種條件來(lái)過(guò)濾數(shù)組
Java代碼  收藏代碼
  1. grep: function( elems, callback, inv ) {   
  2.  //至少需要前2個(gè)參數(shù), 待過(guò)濾的數(shù)組和過(guò)濾函數(shù). 第3個(gè)參數(shù)沒(méi)有什么必要.默認(rèn)為false. 如果填true 就在過(guò)濾函數(shù)返回false的時(shí)候選擇那個(gè)元素.  
  3.         var ret = [];  //空數(shù)組, 待會(huì)裝載過(guò)濾后的元素.  
  4.   
  5.         for ( var i = 0, length = elems.length; i < length; i++ ) {   
  6.      //循環(huán)待過(guò)濾數(shù)組.  
  7.             if ( !inv !== !callback( elems[ i ], i ) ) {    
  8. //inv默認(rèn)為undefined, callback也有可能返回undefined. 等號(hào)2端前面都加個(gè)!是為了讓inv和//callback統(tǒng)一轉(zhuǎn)化為boolean類型進(jìn)行===的判斷.其實(shí)可以簡(jiǎn)單看成  
  9.     //inv !== callback( elems[ i ], i ) )  
  10.                 ret.push( elems[ i ] );  //符合條件的塞進(jìn)數(shù)組  
  11.             }  
  12.         }  
  13.         return ret;  
  14.     },  

當(dāng)過(guò)濾函數(shù)的返回結(jié)果不為undefined, "", 0, false, null這5種情況之一時(shí), 通過(guò)!轉(zhuǎn)化恰好不等于默認(rèn)的inv(默認(rèn)為false). 條件成立,這個(gè)就是需要的元素. 不過(guò)一般情況下我們讓過(guò)濾函數(shù)返回true就可以了. 注意并沒(méi)有用callback.call的形式來(lái)調(diào)用callback. 所以callback里的this是指向window的.



jQuery.prototype.ready

用來(lái)替代window.onload. 每個(gè)主流庫(kù)中都有這個(gè)方法的相應(yīng)實(shí)現(xiàn).

如果使用window.onload, 你必須得等到頁(yè)面的所有圖片,視頻等都加載完,才會(huì)觸發(fā)window.onload里面的方法.

下面是頁(yè)面加載的具體順序.
onContentReady,這時(shí)DOM樹(shù)完成
script defer 這時(shí)開(kāi)始執(zhí)行設(shè)定了defer屬性的script.
             某些庫(kù)比如ext用到了這個(gè)屬性
ondocumentready complete這時(shí)可以使用HTC組件與XHR 
html.doScroll 這時(shí)可以讓HTML元素使用doScroll方法
window.onload 這時(shí)圖片flash等資源都加載完畢
來(lái)自http://www.cnblogs.com/rubylouvre/archive/2009/12/30/1635645.html


jQuery分別用到了onContentReady, html.doScroll, window.onload來(lái)確認(rèn)dom最早加載完成的時(shí)間.
jQuery的實(shí)現(xiàn)可以大致分為這幾個(gè)步驟.

1首先把需要在頁(yè)面加載完成后執(zhí)行的函數(shù)都存到一個(gè)list中, 加載完成后再依次觸發(fā).并設(shè)置一個(gè)控制器, 保證一個(gè)頁(yè)面只有一個(gè)監(jiān)聽(tīng)函數(shù)在執(zhí)行.

2判斷document.readyState是不是為complete.表示dom是否加載完畢

3 如果2步驟失敗, 根據(jù)瀏覽器的不同,給document增加DOMContentLoaded或者onreadystatechange事件,當(dāng)該事件被觸發(fā)的時(shí)候執(zhí)行readyList里的方法.

4在IE瀏覽器中, 設(shè)置一個(gè)定時(shí)器,不停的查看是否已經(jīng)可以執(zhí)行這個(gè)操作.document.documentElement.doScroll("left");如果執(zhí)行這個(gè)操作時(shí)不再拋出異常,說(shuō)明dom已經(jīng)加載完畢了.這個(gè)辦法可能比步驟3更快.

看看代碼



Java代碼  收藏代碼
  1. ready: function( fn ) {  
  2.         jQuery.bindReady();  //添加監(jiān)聽(tīng)函數(shù)  
  3.   
  4.         if ( jQuery.isReady ) { //如果dom加載完成了  
  5.             fn.call( document, jQuery );  //立刻執(zhí)行函數(shù)  
  6.   
  7.         } else if ( readyList ) {  
  8.             readyList.push( fn );  //否則把函數(shù)添加進(jìn)readyList  
  9.         }  
  10.         return this;  
  11.     },  

這里的邏輯并不復(fù)雜, 當(dāng)調(diào)用$().ready(fn) 時(shí), 先通過(guò)jQuery.isReady看dom有沒(méi)有加載完成(jQuery.isReady默認(rèn)是false, 當(dāng)加載完成時(shí)會(huì)被設(shè)置為true).如果dom已經(jīng)加載完成了,就立刻執(zhí)行fn. 否則, 把fn添加進(jìn)待執(zhí)行的數(shù)組.等dom加載完成時(shí)再執(zhí)行.


看看bindReady的實(shí)現(xiàn)
Java代碼  收藏代碼
  1. bindReady: function() {  
  2.     if ( readyBound ) {  //默認(rèn)為false  
  3.         return;  
  4.     }  
  5.   readyBound = true;  
  6.   
  7. if ( document.readyState === "complete" ) {    
  8. //如果$().ready()的時(shí)候,document已經(jīng)加載完成了.  
  9.         return jQuery.ready();  //執(zhí)行readyList里的方法  
  10.     }  
  11.     if ( document.addEventListener ) {    
  12.   //如果支持w3c標(biāo)準(zhǔn)事件模型, 如firefox opera, safari  
  13. document.addEventListener("DOMContentLoaded",DOMContentLoaded, false );   
  14. //當(dāng)dom加載完成時(shí), 觸發(fā)DOMContentLoaded方法. DOMContentLoaded方  
  15. //法可查看源碼742行.  
  16.   
  17.     window.addEventListener( "load", jQuery.ready, false );    
  18.   //保險(xiǎn)起見(jiàn), 給window.onload上面也綁定jQuery.ready, 這是其它方法都  //失效,逼不得以的情況.  
  19.   
  20.     } else if ( document.attachEvent ) {   //如果是IE事件模型  
  21. document.attachEvent("onreadystatechange", DOMContentLoaded);  //實(shí)際上是判斷當(dāng)document.readyState === "complete"時(shí), 執(zhí)行  
  22. // readyList里的函數(shù), 見(jiàn)源碼754行.   
  23.   
  24.               
  25.         window.attachEvent( "onload", jQuery.ready );    
  26.   //同上面的window.addEventListener  
  27.         /* 
  28. 下面的代碼只針對(duì)IE瀏覽器和頁(yè)面不在iframe之中的情況, 當(dāng)頁(yè)面處在iframe中, 好像有時(shí)候用doScroll()會(huì)出問(wèn)題 (不過(guò)我測(cè)試了幾次, 似乎沒(méi)有發(fā)現(xiàn)這個(gè)問(wèn)題 - -!). 
  29.         */  
  30.         var toplevel = false;  
  31.   try {  
  32.             toplevel = window.frameElement == null;    
  33.   //判斷是IE并且頁(yè)面不在iframe當(dāng)中  
  34.             } catch(e) {}  
  35.         if ( document.documentElement.doScroll && toplevel ) {  
  36.                 doScrollCheck();   
  37. //不停的執(zhí)行document.documentElement.doScroll("left"); 直到不報(bào)異常  
  38. }  
  39.         }  
  40.     }  

再看看bindReady方法中涉及到的幾個(gè)方法.
Java代碼  收藏代碼
  1. jQuery.ready  
  2.     ready: function() {  
  3.         if ( !jQuery.isReady ) {              
  4.   if ( !document.body ) {    
  5.   //至少要保證document.body存在. 似乎又是為IE做的hack  
  6.                 return setTimeout( jQuery.ready, 13 );   
  7.     //每隔13ms調(diào)用, resig似乎對(duì)13這個(gè)數(shù)字情有獨(dú)鐘, 是因?yàn)楸容^接近c(diǎn)pu  
  8.     //平均一幀的時(shí)間?  
  9.             }  
  10.             jQuery.isReady = true;  //設(shè)置isReady  
  11.             if ( readyList ) {  
  12.                 var fn, i = 0;  
  13.                 while ( (fn = readyList[ i++ ]) ) {  
  14.                     fn.call( document, jQuery );     
  15.                  //依次執(zhí)行readyList里的方法.  
  16.                 }  
  17.                 readyList = null;  
  18.                 //清空readyList,盡早釋放內(nèi)存. 因?yàn)楫?dāng)isReady為true時(shí),  
  19.           //$().ready().對(duì)于參數(shù)里方法,采取的是來(lái)一個(gè)執(zhí)行一個(gè).已經(jīng)無(wú)須  
  20.             // readyList了.  
  21.   
  22.  }  
  23.   
  24.             if ( jQuery.fn.triggerHandler ) {    
  25.                 //觸發(fā)document上綁定的事件  
  26.                 jQuery( document ).triggerHandler( "ready" );  
  27.             }  
  28.         }  
  29.     }  

doScrollCheck
Java代碼  收藏代碼
  1. function doScrollCheck() {  
  2.     if ( jQuery.isReady ) {  
  3.         return;  
  4.     }  
  5.   
  6.     try {  
  7.         document.documentElement.doScroll("left");  
  8.     } catch( error ) {  
  9.         setTimeout( doScrollCheck, 1 );     
  10.         return;  
  11.     }  
  12.     //不停的執(zhí)行document.documentElement.doScroll("left")  
  13.     //直到?jīng)]有異常拋出  
  14.     jQuery.ready();  
  15. }  

jQuery.proxy

proxy: function( fn, proxy, thisObject ) 返回一個(gè)新函數(shù),,這個(gè)函數(shù)的this指向你指定的對(duì)象.

jquery1.4總算提供了this代理的方法了, 以前總是要自己實(shí)現(xiàn)一個(gè)Function.prototype.bind方法.
可能很多同學(xué)對(duì)this的調(diào)用和指向還是有點(diǎn)模糊. 那在此之前,先講一下this的幾種指向情況.

1 普通函數(shù)調(diào)用, this指向window.
比如
var fn = function(){
alert (this === window)
};
fn();
結(jié)果為true

2 對(duì)象屬性調(diào)用, this指向擁有這個(gè)屬性的對(duì)象.
比如 var obj = {
fn: function(){
alert (this === obj);
}
obj.fn();
}
結(jié)果為true
或者
document.getElementById("id1").onclick = function(){
alert (this.id);
}
點(diǎn)擊后彈出id1, 此時(shí)this指向onclick的擁有者id1.

3 通過(guò)構(gòu)造函數(shù)調(diào)用this時(shí),this指向通過(guò)構(gòu)造函數(shù)生成的對(duì)象.
比如 function A(){
this.b = 1;
}
var a = new A();
當(dāng)a去調(diào)用A的構(gòu)造函數(shù)時(shí), this是指的a.

4 call或者apply, 這里的this是由自己指定.
比如
Java代碼  收藏代碼
  1. (function(){  
  2.     alert(this.name);  
  3. }).call({name: "__游樂(lè)場(chǎng)"})  

這里需要一個(gè)括號(hào)把function(){alert(this.name)}包圍起來(lái)是為了讓引擎把括號(hào)里面的語(yǔ)句當(dāng)成一個(gè)表達(dá)式而不是函數(shù)聲明, 函數(shù)聲明是不能調(diào)用方法的. 編譯期進(jìn)行語(yǔ)法檢測(cè)的時(shí)候就會(huì)報(bào)錯(cuò).

其實(shí)我們?cè)陂_(kāi)發(fā)很容易就不知不覺(jué)弄丟了this.舉個(gè)例子.我要點(diǎn)擊一個(gè)div的時(shí)候,彈出這個(gè)div的id.
Java代碼  收藏代碼
  1. document.getElementById('div1').onclick = function(){  
  2.     ~function(){  
  3.         alert (this.id);  
  4.     }()  
  5. }  

這個(gè)方法里的this就已經(jīng)是window了. 一般我們可以改成這樣
Java代碼  收藏代碼
  1. document.getElementById('div1').onclick = function(){  
  2.     var self = this;  
  3.     ~function(){  
  4.         alert (self.id);  
  5.     }()  
  6. }  

也許你不喜歡self這個(gè)臨時(shí)變量.那換一種方法.我們擴(kuò)展一下Function的原型,實(shí)現(xiàn)一個(gè)最簡(jiǎn)單的bind方法.
Java代碼  收藏代碼
  1. Function.prototype.bind = function(obj){  
  2.     var self = this;   
  3.     return function(){ //返回一個(gè)閉包, 調(diào)用的時(shí)候把obj當(dāng)成this.  
  4.         self.call(obj);    
  5.     }  
  6. }  
Java代碼  收藏代碼
  1. document.getElementById('div1').onclick = function(){  
  2.     ~function(){  
  3.         alert (this.id);  
  4.     }.bind(this)()  
  5. }  


現(xiàn)在已經(jīng)OK了,沒(méi)有了討厭的臨時(shí)變量. 這里的proxy方法肯定也是利用call或者apply方法來(lái)指定this. 看看api上的例子
Java代碼  收藏代碼
  1. var obj = {  
  2.     name: "John",  
  3.     test: function() {  
  4.       alert( this.name );  
  5.       $("#test").unbind("click", obj.test);  
  6.     }  };  
  7.     $("#test").click( jQuery.proxy( obj, "test" ) );      
  8.     // 以下代碼跟上面那句是等價(jià)的:    
  9.     // $("#test").click( jQuery.proxy( obj.test, obj ) );  
  10.     // 可以與單獨(dú)執(zhí)行下面這句做個(gè)比較。  
  11.     // $("#test").click( obj.test );    

proxy根據(jù)參數(shù)傳遞的不同有2種調(diào)用方式,
1, 參數(shù)分別為obj對(duì)象, 被代理函數(shù)(必須是obj對(duì)象的屬性). 結(jié)果是返回obj.test函數(shù), this指向obj.
2, 參數(shù)分別為被代理函數(shù)(obj.test), this指向obj.

第二種方式看來(lái)順眼得多.再看看源碼的具體實(shí)現(xiàn)

Java代碼  收藏代碼
  1. proxy: function( fn, proxy, thisObject ) {   
  2.     //參數(shù)分別為被代理函數(shù), this代理, thisObject是內(nèi)部用的變量, 用來(lái)修正被代理函數(shù)  
  3.         if ( arguments.length === 2 ) {  
  4.             if ( typeof proxy === "string" ) {    
  5.     //如果第二個(gè)參數(shù)為字符型, 參看上面的第一種調(diào)用方式.  
  6.                 thisObject = fn;                    
  7.     //修正thisObject指向obj對(duì)象. 這里代碼雖然寫(xiě)的fn, 看起來(lái)像一個(gè)函數(shù)  
  8.     //實(shí)際上是第一種調(diào)用方式傳遞進(jìn)來(lái)的某個(gè)對(duì)象.   
  9.                 fn = thisObject[ proxy ];           
  10.     //被代理函數(shù)修正為obj對(duì)象的某個(gè)屬性函數(shù).  
  11.                 proxy = undefined;                  
  12. //清空proxy, 跟下面的if ( !proxy && fn ) 統(tǒng)一處理只有一個(gè)參數(shù)fn的情況.  
  13.   
  14.         } else if ( proxy && !jQuery.isFunction( proxy ) ) {       
  15.  //上面第二種調(diào)用方式  
  16.                 thisObject = proxy;                 
  17. //修正thisObject指向obj對(duì)象.  
  18.                 proxy = undefined;                  
  19. //清空proxy, 跟下面的 if ( !proxy && fn ) 統(tǒng)一處理只有一個(gè)參數(shù)fn的情況.  
  20.             }  
  21.         }  
  22.   
  23.         if ( !proxy && fn ) {                  
  24.      // 如果只有一個(gè)參數(shù), proxy為undefined. 有2個(gè)參數(shù)的絕大部分情況下, proxy也已經(jīng)被設(shè)置為undefined. 這里的條件判斷都為true  
  25.             proxy = function() {               
  26.                 return fn.apply( thisObject || this, arguments );     
  27. //進(jìn)行代理, 如果只有一個(gè)參數(shù), thisObject顯然是undefined, 這里的代理對(duì)象還是原來(lái)的this. 注意proxy返回一個(gè)函數(shù), 這里的第二個(gè)參數(shù)arguments是以后調(diào)用proxy函數(shù)時(shí)候的arguments  
  28.             };  
  29.         }  
  30.   
  31.         if ( fn ) {  
  32.             proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;  //設(shè)置一個(gè)全局標(biāo)識(shí)符, 在event系統(tǒng)中用到.  
  33.         }  
  34.   
  35.         return proxy;  
  36.     }  


瀏覽器特性檢測(cè)

從jquery1.3版本開(kāi)始, 寫(xiě)不同瀏覽器的兼容代碼之前, 不贊成再去判斷瀏覽器的類型, 而是直接判斷支不支持某個(gè)特性, 比如盒模型. 透明度這些. 就像一個(gè)老外向你問(wèn)路的時(shí)候, 他肯定是先說(shuō)can you speak English. 而不是are you Amercan.

關(guān)于特性檢測(cè)的具體實(shí)現(xiàn), 可以參考下面文章.
http://peter./articles/feature-detection-state-of-the-art-browser-scripting
http://yura./cft/
http://www./faq/faq_notes/not_browser_detect.html

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購(gòu)買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多