(轉)三分鐘玩轉jQuery.noConflict()

jQuery是目前使用最普遍的前端框架之一,有大量的第三方庫和插件基於它開發。爲了不全局命名空間污染,jQuery提供了jQuery.noConflict()方法解決變量衝突。這個方法,毫無疑問,很是有效。遺憾的是,jQuery的官方文檔對該方法的描述不夠清晰,許多開發者並不清楚當他們調用jQuery.noConflict()時,究竟發生了什麼,從而致使在使用時出現了許多問題。儘管如此,jQuery.noConflict()背後實現原理依然值得Web開發者學習掌握,成爲解決相似全局命名空間污染問題的利器。javascript

jQuery.noConflict()的做用?

  jQuery.noConflict()的存在只有一個目的:它容許你在同一個頁面加載多個jQuery實例,尤爲是不一樣版本的jQuery。你可能會以爲奇怪,爲何要在一個頁面加載/使用多個不一樣版本的jQuery對象呢?通常而言,有兩種狀況。第一種狀況,你的業務代碼採用了最新版的jQuery庫,而你選用的第三方插件依賴的更早版本的jQuery庫;第二種狀況,你正維護着一個系統,它已有的業務代碼因爲各類緣由,引用了較老版本的jQuery庫,你新開發的模塊採用的是其餘版本的jQuery庫。不論哪一種狀況,你都不得不面對,jQuery對象/方法衝突的問題。幸運的是,jQuery.noConflict()幫你解決了這個煩惱。css

jQuery被加載時發生了什麼?

  當jQuery被頁面引用/加載時,它被封裝在一個自執行函數(匿名函數)裏,它提供的全部一切變量、函數、對象都在匿名函數內部的可執行環境內,外部環境沒法調用,以防止全局命名空間污染。html

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

jQuery在匿名函數內部定義了兩個全局對象:jQuery$,把本身暴露給外部環境。開發者習慣使用的各類公共方法都是經過這兩個對象進行訪問的,如jQuery.ajax(),jQuery.css()等。在最初,它們指向匿名函數內部的同一個對象jQuery(私有變量),經過它訪問匿名函數內部的私有變量和函數。這使得匿名函數在自執行後其內部的私有變量和函數仍然進駐在內存裏,不會被javascript的垃圾回收機制清除。前端

window.jQuery = window.$ = jQuery;

  當jQuery被頁面加載後,當前頁面有可能已經存在了jQuery$這兩個全局變量(好比,加載了其它的第三方庫,其內部也定義了它倆),這就會致使已經存在的對象被覆蓋(全局命名空間污染)。爲了解決這個問題,jQuery在內部先將已經存在的全局變量緩存起來,保存在私有變量_jQuery_$中,供後續調用。因此,若是頁面在加載jQuery庫時,還不存在jQuery$對象,那麼_jQuery_$都是undefined;不然,它們都會保存對已有jQuery$的引用(也許來自以前引用的第三方庫或是不一樣版本的jQuery庫)。以後,jQuery會像上文說描述的那樣,覆蓋這兩個全局變量並將本身暴露給外部環境。至此,頁面上的全局變量jQuery$已經指向剛剛引入的jQuery庫。java

// Map over jQuery in case of overwrite _jQuery = window.jQuery, // Map over the $ in case of overwrite _$ = window.$, // Otherwise expose jQuery to the global object as usual window.jQuery = window.$ = jQuery;

jQuery.noConflict()的神奇效果?

  假設你維護的系統已經引用了1.7.0版本的jQuery庫,而你在新添加的功能裏引用了1.10.2版本的jQuery庫。那麼,還有辦法從新使用jQuery 1.7.0 或是同時使用兩個版本的jQuery庫嗎?答案是確定,那就是jQuery.noConflict()。實際上,利用jQuery.noConflict(),你能夠馬上把全局變量jQuery$從新指向以前引用的對象。很神奇吧?這就是爲何jQuery在對外暴露本身前內部緩存了以前引用的對象。
  jQuery.noConflict()接受一個可選的布爾值參數,一般默認值是false。這個參數會帶來什麼影響呢?其實,很簡單。若是調用jQuery.noConflict()或是jQuery.noConflict(false),只有全局變量$會被重置恢復成以前的引用值;若是調用jQuery.noConflict(true),那麼全局變量jQuery$都會被重置恢復成以前的引用值。這一點很是重要,建議牢記。當你調用jQuery.noConflict(false/true)以後,它會返回當前jQuery的實例,利用這個特性咱們能夠實現jQuery的重命名。jquery

// "Renaming" jQuery var jayquery = jQuery.noConflict( true ); // Now we can call things like jayquery.ajax(), jayquery.css(), and so on

咱們再來看一個代碼片斷,測試一下是否真正理解了神奇的noConflict()ajax

<!-- jQuery and $ are undefined --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script> <!-- jQuery and $ now point to jQuery 1.10.2 --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"> <!-- jQuery and $ now point to jQuery 1.7.0 --> <script>jQuery.noConflict();</script> <!-- jQuery still points to jQuery 1.7.0; $ now points to jQuery 1.10.2 --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"> <!-- jQuery and $ now point to jQuery 1.6.4 --> <script>var jquery164 = jQuery.noConflict( true );</script> <!-- jQuery now points to jQuery 1.7.0; $ now points to jQuery 1.10.2; jquery164 points to jQuery 1.6.4 -->

避免第三方庫的衝突

  以上的代碼片斷展現瞭如何解決多版本jQuery的衝突。接下來,咱們嘗試解決jQuery庫和第三方庫的衝突,下面出現的代碼片斷在jQuery的官方文檔中都有,有興趣的程序猿能夠仔細閱讀官方文檔體會其中的區別。api

直接使用No-Conflict模式

  使用No-Conflict模式,其實就是對jQuery進行重命名,再調用。緩存

<!-- 採用no-conflict模式,jquery.js在prototype.js以後被引入. --> <script src="prototype.js"></script> <script src="jquery.js"></script> <script> var $j = jQuery.noConflict(); // $j 引用了jQuery對象自己. $j(document).ready(function() { $j( "div" ).hide(); }); // $ 被從新指向prototype.js裏定義的對象 // document.getElementById(). mainDiv below is a DOM element, not a jQuery object. window.onload = function() { var mainDiv = $( "main" ); } </script>

使用自執行函數封裝

  使用這種方式,你能夠在匿名函數內部繼續使用標準的$對象,這也是衆多jQuery插件採用的方法。須要注意的是,使用這種方法,函數內部沒法再使用prototype.js定義的$對象了。前端框架

<!-- jquery.js在prototype.js以後被引入. --> <script src="prototype.js"></script> <script src="jquery.js"></script> <script> jQuery.noConflict(); (function( $ ) { // Your jQuery code here, using the $ })( jQuery ); </script>

使用標準jQuery(document).ready()函數

  若是jQuery庫在其它庫以前引入,那麼jQuery內部定義的jQuery$會被第三方庫覆蓋,這時候再使用noConflict()已經沒有什麼意義了。解決的方法很簡單,直接使用jQuery的標準調用方式。




文章大讚,怕丟失,直接轉過來了。原文地址:https://www.cnblogs.com/laoyu/p/5189750.html#undefined<!-- jquery.js在prototype.js以前被引入. --> <script src="jquery.js"></script> <script src="prototype.js"></script> <script> // Use full jQuery function name to reference jQuery. jQuery( document ).ready(function() { jQuery( "div" ).hide(); }); // 或者 jQuery(function($){ // Your jQuery code here, using the $ }); // Use the $ variable as defined in prototype.js window.onload = function() { var mainDiv = $( "main" ); }; </script>
相關文章
相關標籤/搜索