談談 jQuery 中的防衝突(noConflict)機制

    許多的 JS 框架類庫都選擇使用 $ 符號做爲函數或變量名,jQuery 是其中最爲典型的一個。在 jQuery 中,$ 符號只是 window.jQuery 對象的一個引用,所以即便 $ 被刪除,window.jQuery 依然是保證整個類庫完整性的堅強後盾。jQuery 的 API 設計充分考慮了多框架之間的引用衝突,咱們可使用 jQuery.noConflict 方法來輕鬆實現控制權的移交。

    jQuery.noConflict 方法包含一個可選的布爾參數[1],用以決定移交 $ 引用的同時是否移交 jQuery 對象自己: jquery

jQuery.noConflict([removeAll])
    缺省狀況下,執行 noConflict 會將變量 $ 的控制權移交給第一個產生 $ 的庫;當 removeAll 設置爲 true 時,執行 noConflict 則會將 $ 和 jQuery 對象自己的控制權所有移交給第一個產生他們的庫。

    例如在 KISSY 和 jQuery 混用,而且慣用 $ = KISSY 來簡化 API 操做的時候,就可以經過這個方法解決命名衝突的問題。

    那麼這個機制是如何實現的呢?閱讀 jQuery 源碼開頭[2],首先作的一件事情是這樣的:
// Map over jQuery in case of overwrite
 _jQuery = window.jQuery,

 // Map over the $ in case of overwrite
_$ = window.$,
    容易理解的是,jQuery 經過兩個私有變量映射了 window 環境下的 jQuery 和 $ 兩個對象,以防止變量被強行覆蓋。一旦 noConflict 方法被調用,則經過 _jQuery, _$, jQuery, $ 四者之間的差別,來決定控制權的移交方式,具體的代碼以下:

noConflict: function( deep ) {
                if ( window.$ === jQuery ) {
                        window.$ = _$;
                }

                if ( deep && window.jQuery === jQuery ) {
                        window.jQuery = _jQuery;
                }

                return jQuery;
        }
    再來看上面所說的參數設定問題,若是 deep 沒有設置,_$ 覆蓋 window.$,此時 jQuery 別名 $ 失效,但 jQuery 自己完整無缺。若是有其餘類庫或代碼從新定義了 $ 變量,它的控制權就徹底交接出去了。反之若是 deep 設置爲 true 的話,_jQuery 覆蓋 window.jQuery,此時 $ 和 jQuery 都將失效。


    這種操做的好處是,無論是框架混用仍是 jQuery 多版本共存這種高度衝突的執行環境,因爲 noConflict 方法提供的移交機制,以及自己返回未被覆蓋的 jQuery 對象,徹底可以經過變量映射的方式解決衝突。


    但沒法避免的事實是可能致使的插件失效等問題,固然經過簡單修改上下文參數便可恢復 $ 別名:
var query = jQuery.noConflict(true);
(function ($) {

     // 插件或其餘形式的代碼,也能夠將參數設爲 jQuery

})(query);
[1]  http://api.jquery.com/jQuery.noConflict/#jQuery-noConflict-removeAll
[2]  https://github.com/jquery/jquery/blob/master/src/core.js
相關文章
相關標籤/搜索