第二章 : 種子模塊

種子模塊也叫核心模塊,是框架中最早執行的部分。即使像jQuery那樣的單文件函數庫,它的內部也分不少模塊,必然有一些模塊執行時在最前面當即執行,有一些模塊只有用到才執行。有的模塊無關緊要,存在感比較弱,只有在特定的瀏覽器下才運行。javascript

種子模塊就是其中的先鋒,它裏邊的方法不必定要求個個功能齊全,設計優良,但必定要極具擴展性,經常使用,穩定css

擴展性是指經過他們能給將其它模塊包含進來;經常使用是指絕大多數的模塊都能用到它們,防止作重複工做。穩定是指在版本迭代時不輕易被新方法替代。html

參照許多框架和庫的實現,咱們認爲種子模塊包含以下功能對象擴展數組化類型斷定簡單的綁定與卸載無衝突處理模塊的加載domReady.本章學習的內容以mass Framework種子模塊爲範本。java

https://github.com/RubyLouvre/mass-Frameworknode

1.命名空間git

種子模塊做爲一個框架最開始的部分,負責輔建全局的基礎設施外。jQuery就有一個很好的開頭,使用IIFE(當即調用函數表達式).github

LIFE是現代javascript框架裏最主要的基礎設施,它就像細胞同樣包裹自身,防止變量污染。就像一個立足點,這個就是命名空間,如prototype.js,mootools,它們讓你感覺不到框架的存在,它的意義深入到javascript、DOM、BOM等整個執行環境的每一個角落,對原生的對象原型就行擴展。因爲道格拉斯(JSON做者)的極力反對,新的框架都在命名空間上構建了。chrome

咱們看怎麼在javascript上模擬命名空間。javascript一切基於對象,但只有符合類型的對象才符合要求,好比function 、RegExp、Object,不過最經常使用的是object和function。咱們往一個對象上添加一個屬性,而這個屬性又是一個對象,這個對象咱們又能夠爲它添加一個對象,經過這種方法,咱們就能夠有條不紊的構建咱們的框架。用戶想調用某個方法,就以xxx.yyy.zzz()的形式調用windows

    if( typeof(Ten) === "undefined" ){
        Ten = {};
        Ten.Function = {  /**/ }
        Ten.Array = {  /**/ }
        Ten.Class = {  /**/ }
        Ten.JSONP = new Ten.Class(/**/ )
        Ten.XHR = new Ten.Class(/**/ )
    }

縱觀各大類庫的實現,一開始基本都是定義一個全局變量做爲命名空間,而後對它進行擴展,如Base2的Base,Ext的Ext,jQuery的jQuery,YUI的YUI,dojo的dojo,MochiKit的mochKit。從全局變量的污染程度來看,分爲兩類:api

prototype.js和mootools與Base2歸爲一類,Prototype的哲學是對javascript的原生對象進行擴展。早些年,prototype差點稱爲事實的標準。所以沒有考慮到與其它庫共存的問題。基本Prototype,也發展出諸如script.aculo.us,rico,Plotr,protoChart,Script2等很是優秀的類庫以一大類收費插件。並且,有些淵源的插件幾乎都與Prototype有關,好比lightBox。mootools是prototype.js的升級版,更加OO,全面複製其API。Base2則是想修復IE的bug,讓IE擁有標準瀏覽器的API,所以也把全部原生的對象污染一遍

第二類是jQuery,YUI,EXT這些框架YUI和Ext就是對象嵌套對象的方式構建的。jQuery則另闢蹊徑,它是以選擇器爲導向的,所以它的命名空間是一個函數,方便用戶將css表達器的字符串傳進來。而後經過選擇器進行查找,最後返回一個jQuery對象實例。

jQuery最開始也像Prototype使用$做爲它的命名空間,所以,它實現了不少庫的共存機制,在$和jQuery中任意切換,jQuery的多庫共存原理很簡單,所以後來也成爲許多小庫的標配。首先,把命名空間保存到一個臨時變量中(注意,這時候這個對象並非本身框架的東西,多是prototype.js或者其餘的),而後再使用個noConflict放回去。

    //jQuery1.2
    var _jQuery = window.jQury , _$ = window.$; //把可能存在同名變量先保存起來
    jQury.extend({
        noConflict : function(deep) {
            window.$ = _$; //這時再放回去
            if (deep)  //補充 if ( deep && window.jQuery === jQuery )
                window.jQury = _jQuery;
            return jQury;
        }
    })

參考:http://zhidao.baidu.com/question/1239712776390687219.html

但jQuery的noConflict只是對單文件的類庫框架有用,像Ext就不能複製了。所以把命名空間更名後,將Ext置爲null,而後經過動態加載的方法引入新的javascript文件中,該文件會以Ext調用,會致使報錯

2.對象擴展

咱們須要一種機制,將新功能添加到咱們的命名空間上來。這方法在javascript一般稱做extend或mixin。javascript對象在屬性描述符(Property Descriptor)沒有誕生以前,是能夠隨意添加、更改、刪除其成員的,所以,擴展一個對象很是便捷。一個簡單的擴展方法實現是這樣的。

    function extend (destination,source){
        for (var property in source)
            destination[property] = source[property];
        return destination;
    }

不過,舊版本IE在這裏有個問題,它認爲像Object的原型方法就是不該該被遍歷出來,所以for in循環是沒法遍歷valueOf、toString的屬性名。這致使,模擬Object.keys方法是現實時也遇到了這個問題。

    Object.keys = Object.keys || function(obj){
        var a = [];
        for(a[a.length] in obj);
        return a;
    }

在不一樣的框架,這個方法還有不一樣的實現,如Ext分別爲apply與applyIf兩個方法,前者會覆蓋目標對象的同名屬性,然後者不會。dojo容許多個對象合併在一塊兒。jQuery還支持深拷貝。下面是mass Farmework的mix方法。支持多對象合併與選擇是否覆寫。

    function mix(target,source){ //若是最後參數是布爾,斷定是否覆蓋同名屬性
        var args = [].slice.call(arguments), i = 1, key,
            ride = typeof args[args.length - 1] == "boolean" ? args.pop() : true;
        if (args.length === 1){ //處理$.mix(hash)的情形
            target = !this.window ? this : {};
            i = 0;
        }    
        while ((source = args[i++])) {
            for (key in source){ //容許對象糅雜,用戶保證都是對象
                if (ride || !(key in target)) {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }

3.數組化

瀏覽器下存在不少類數組對象,如function內的arguments,經過document.forms、form.elements,document.links、select.options、document.getElementsByName,document.getElementsByTagName、childNodes、children等方式獲取的節點的結合(HTMLCollection 、NodeList)或按照某些特殊的寫法自定義對象。

類數組對象是一個很好的存儲結構。不過功能太弱了,爲了能使用純數組的那些便捷的方法,咱們會在處理它們前都會作一下轉換。

一般來講,使用[].slice.call就能轉換了 ,不過功能不夠用,但在舊版本的HTMLCollection、NodeList不是Object的子類,採用如上的方法會致使IE執行異常。咱們看一下

jQuery:makeArray

    var makeArray = function(array) {
        var ret = [] ;
        if(array != null){
            var i = array.length;
            if(i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval)
                ret[0] = array;
            else
                while (i)
                    ret(--i) = array[i];
        }
        return ret;
    }

mass的實現,一開始就進行區分,直接[].slice.call,IE的話本身動手實現一個slice方法

    $.slice = window.dispatchEvent ? function(nodes,start,end){
        return [].slice.call(nodes,start,end);
    } : function (nodes,start,end){
        var ret = [],
              n = nodes.length;
        if (end === void 0 || typeof end === "number" && isFinite(end)){
            start  = parseInt (start,0) || 0;
            end = end == void 0 ? n:parseInt (end,10);
            if(start < 0){
                start += n;
            }
            if (end > n) {
                end =n
            };
            if (end < 0) {
                end += n
            };
            for (var i = start; i < end; ++i){
                ret[i-start] = nodes[i];
            }
        }
        return ret;
    }

4.類型的斷定

javascript存在兩套類型系統,一套是基本的數據類型,另外一套是對象類型系統。基本數據類型包括6中 。分別是undefined、string、null、boolean、function、object。基本數據類型是經過typeof來檢測的。對象類型系統是以基礎類型系統爲基礎的,經過instanceof來檢測的。然而,javascript自帶的這兩套識別機制很是不靠譜,因而就催生了isXXX系列。就拿typeof來講,它只能粗略識別出string、number、boolearn、function、undefined、object這6種數據類型,沒法識別null,RegExpArgument等細分的對象類型。

    typeof null // => "object"
    typeof document.childNodes //=> safari: "function"
    typeof document.creatElement('embed') //=> ff3-10 "function"
    typeof document.creatElement('object') //=> ff3-10 "function"
    typeof document.creatElement('object') //=> ff3-10 "function"
    typeof /\d/i //在實現了ecma262v4的瀏覽器返回"function"
    typeof window.alert //ie678 "object"
    var iframe = document.creatElement("iframe")
    document.body.appendChild(iframe)
    xArray = window.frames[window.frames.length - 1].Array;
    var arr = new xArray(1,2,3) //=>[1,2,3]
    arr instanceof Array ;// false
    isNaN("aaa") //=> true

另外,之前人們老是以document.all來判斷是否爲ie,這實際上是很危險的,由於,用document.all來取得頁面中全部的元素是不錯的注意,這個方法FF,chrome打算使用好久了,不過人們都這樣判斷,就是在chrome下有這樣的鬧劇。

    typeof document.all //undefined
    document.all //HTMLAllCollection [728] (728爲元素總數)

在斷定undefined、null、string、number、boolean、function這六個還算簡單,前面兩個能夠分別與void(0)、null比較,後面4個的typeof也能夠知足90%的情形。這樣說是由於string、number、boolean能夠包裝成僞對象。

    typeof new Boolean(1); //=>"object"
    typeof new Number(1); //=>"object"
    typeof new String("aa"); //=> "object"

這些還不是最難的,難點在於RegExp與Array.斷定RegExp的狀況不多。Array則不同。有關isArray的實現不下二十種。都是由於鴨式辨型被打破了。直到prototype.js把Object.prototype.toString發掘出來。此方法是直接輸出內部的[[Class]],絕對精準。有了它,95%的陷阱被跳過了。

    function isArray(arr){
        return arr instanceof Array;
    }

    function isArray(arr){
        return !!arr && arr.constructor === Array;
    }

    function isArray(arr) { //prototype.js 1.6
        return arr != null && typeof arr === "object" && 'splice' in arr && 'join' in arr;
    }

    function isArray(arr){// Douglas Crockford(JSON做者,反對原型污染)
        return typeof arr.sort == "function"
    }

    function isArray(array){ //kriszyp
        var result = false;
        try{
            new array.constructor (Math.pow(2,32))
        } catch (e){
            result = /Array/.test(e.message)
        }
        return result;
    };

    function isArray(o){//kangax
        try{
            Array.prototype.toString.call(o);
            return true;
        } catch (e) {
        }
        return false;
    }

    function isArray(o){ //kangax
        if(o && typeof o == 'object' && typeof o.length == 'number' && isFinite(o.length))
        {
            var _origLength = o.length;
            o[o.length] = '__test__';
            var _newLength = o.length;
            o.length = _origLength;
            return _newLength == _origLength + 1;
        }
        return false
    }

至於null 、 undefined 、NaN直接這樣寫

    function isNaN(obj) {
        return obj !== obj
    }

    function isNull(obj) {
        return obj === null;
    }

    function isUndefined(obj){
        return obj === void 0;
    }

最後要斷定的是對象是window,因爲ECMA是不規範的Host對象,window對象屬於host.因此也就沒有被約定。就算Object.prototype.toString也對它沒辦法

    [object Object] IE6 
    [object Object] IE7 
    [object Object] IE8
    [object Window] IE9
    [object Window] ff3.6
    [object Window] opera10
    [object DOMWindow] safari 4.04
    [object global] chrome5.0

不過根據window.window和window.setInterval去斷定更加不靠譜,用一個技巧就能夠完美識別ie6 ie7 ie8的window對象,其它還用toString,這個神奇的hack就是,window與document互相比較,若是順序不同,結果也是不同的

剩下的就是一些經典方法:

在prototype.js中,擁有isElement,isArray,isHash,isFunctoion,isString,isNumber,isDate,isUndefined

mootools有一個typeOf斷定基本類型,instanceOf斷定自定義「類」

RightJS 有isFunction , isHash , isString , isNumber , isArray ,isElement, isNode.

Ext有比較全面的判斷,isEmpty,isArray,isDate,isObject,isSimpleObject,isPrimitive,isFunction,isNumber,isMumeric,isString,isBoolean,isElement,isTextNode,isDefined,isIterable,應有盡有。最後,還有typeOf判斷基本類型。

Underscore.js有isElement,isEmpty,isArray,isArgument,isObject,isFunction,isString,isNumber,isFinite,isNaN,isBoolean,isDate,isRegExp,isNull,isUndefined.

jQuery就不與其它框架同樣了,在jQuery1.4中只有isFunction,isArray,isPlainObject,isEmptyObject。isFunction,isArray用戶確定用的較多,isPlainObject是用來判斷是不是純淨的js對象。既不是DOM,BOM對象,也不是自定義的「類」的實例對象,製造它的目的最初是爲了深拷貝,避開像window那樣本身引用本身的對象。isEmptyObject是用於數據緩存的系統,當此對象爲空時,就能夠刪除它。

    //jQuery2.0純淨數組的斷定思路
    jQuery.isPlainObject = function(obj){
        //首先排除基礎類型不爲Object的類型,而後是DOM節點與window對象
        if(jQuery.type(obj) !== "object" || object.nodeType || jQuery.isWindow(obj)){
            return false;
        }

        //而後回溯它的最近的原型對象是否有isPrototypeOf.
        //舊版本的IE一些原生的對象沒有暴露constructor、prototype。所以在這裏過濾掉
        try{
            if (obj.constructor && !hasOwn.call(obj.constructor.prototype,"isPrototypeOf")){
                return false;
            }
        } case(e) {
            return false;
        }
        return true;
    }

 

avalon.mobile中有一個更精簡的版本,只支持最新的瀏覽器,能夠大膽的使用ecma262v5新API

    avalon.isPlainObject = function(obj){
        return obj && typeof obj === "object" && Object.getPrototypeOf(obj) === Object.prototype
    }

isArrayLike也是一個經常使用的方法,可是斷定一個類數組太難了,惟一的識別方法就是判斷有一個大於0或等於0的length屬性,此外,還有一些共識,如window與函數和元素節點,如(form元素),不算類數組,雖然它們都知足前面的條件。所以,至今jQuery都沒有把它暴露出來。

    //jQuery2.0
    function isArrayLike(obj){
        var length = obj.length , type = jQuery.type(obj);
        if (jQuery.isWindow(obj)){
            return false;
        }
        if (obj.nodeType === 1 && length){
            return true
        }
        return type === "array" || type !== "function" && (length === 0 || typeof length === "number" && length > 0 && (length -1) in obj);
    }

    // avalonjs
    function isArrayLike (obj) {
        if (obj && typeof obj === "object"){
            var n = obj.length
            if (+n === n && !( n % 1) && n >= 0){//檢測length是否爲非負整數
               try{
                   if ({}.prototypeIsEnumerable.call(obj,'length') === false){
                    return Array.isArray(obj) || /^\s?function/.test(obj.item || obj.callee)
                 }
                return true;
              } catch (e) { //IE的NodeList直接報錯
                return true;
              }
            }
        }
    return false
    }

 

在Prototype.js1.3版本中的研究成果(Object.prototype.toString.call)就應用於jQuery,在jQuery1.2中,判斷一個變量是否爲函數很是複雜。

    isFunction : function(fn){
        return !!fn && typeof fn != "string" && !fn.nodeName && fn.constructor != Array && /^[\s[]?function/.test(fn + ""); 
    }

jQuery1.43中引入isWindow來處理makeArray中對window的斷定,引入isNaN用於確保樣式賦值的安全同時引入type代替typeof關鍵字,用於獲取基本數據的基本類型。

    class2type = {};
    jQuery.each("Boolean Number String Function Array Date RegExpObject".split("  "),function( i , name ){
        class2type[ "[object " + name + "]" ] = name.toLowerCase();
    });

    jQuery.type = function(obj){
        return obj == null ? String(obj) : class2type[toString.call(obj)] || "object";
    }

jQuery1.7中添加isNumeric代替isNaN。這是個不一樣於其它框架的isNumber,它能夠是個字符串,只要外觀上像數字就能夠了。但jQuery1.7還作了一個違背以前提到穩定性的事情。冒然去掉jQuery.isNaN,所以,基於舊版jQuery的有大批插件失效。

    //jQuery.1.43-1.64
    jQuery.isNaN = function ( obj ) {
        return obj == null || !rdigit.test( obj ) || isNaN( obj );
    }

    //jQuery1.7就是isNaN的去反版
    jQuery.isNumeric =  function ( obj ) {
        return obj != null && rdigit.test( obj ) && !isNaN( obj );
    }

    //jQuery.1.71 - 1.72
    jQuery.isNumeric =  function ( obj ) {
        return !isNaN( parseFloat(obj) ) && isFinite( obj );
    }

    //jQuery2.1
    jQuery.isMumeric  = function( obj ) {
        return obj - parseFloat(obj) >= 0;
    }

massFarmeWork的思路與jQuery一致,儘可能減小isXXX系列的代碼,把is Window,isNaN,nodeName等方法作了整合。代碼較長,既能夠獲取類型,也能夠傳入第二參數進行類型比較

    var class2type = {
        "[objectHTMLDocument]" : "Document",
        "[objectHTMLCollection]" : "NodeList",
        "[objectStaticNodeList]" :  "NodeList",
        "[objectIXMLDOMNodeList]" : "NodeList",
        "[objectDOMWindow]" : "window",
        "[object global]" : "window",
        "Null" : "Null",
        "undefined" : "undefined"
    },
    toString = class2type.toString;
    "Boolean,Number,String,Function,Array,Date,RegExp,Window,Document,Arguments,NodeList".replace($.rword,function( name ) {
        class2type[ "[object" + name + "]" ] = name;
    });

    //class2type這個映射幾乎把經常使用的斷定對象一網打盡
    mass.type = function( obj , str ){
        var result = class2type[ (obj == null || obj !== obj) ? obj : toString.call(obj) ] || obj.nodeName || "#";
        if(result.charAt(0) === "#") { //兼容舊版瀏覽器的個別狀況,如window.opera
            //利用IE678 window === document爲true,document === window爲false
            if( obj == obj.document && obj.document != obj ) {
                result = "window"; //返回構造器名稱
            } else if ( obj.nodeType === 9 ) {
                result = "Document";
            } else if ( obj.callee) {
                result = "Arguments";
            } else if ( isFinite(obj.length) && obj.item ) {
                result = "NodeList" //處理節點集合
            } else {
                result = toString.call(obj).slice(8,-1);
            }
        }
        if(str){
            result str === result;
        }
        return result;
    }

而後type方法就十分輕鬆了,用toSring.call(obj)得出值的左鍵,直接從映射中取得。IE678,咱們才費一些周折處理window,document,argument,nodeList等對象。

百度的七巧板基於實用主義,斷定也十分嚴謹。與EXT同樣,能想到的寫上,而且斷定十分嚴謹。

目前版本2.0.2.5 http://tangram.baidu.com/api#baidu.type()

    baidu.isDate = function( unknow ) {
    return baidu.type(unknow) == "date" && unknow.toString() != 'Invalid Date' && !isNaN(unknow);
    };
    baidu.isNumber = function( unknow ) {
    return baidu.type(unknow) == "number" && isFinite( unknow );
    };

 5.主流框架的引入機制-domReady

domReady實際上是一種名爲"DOMContentLoaded"事件的別稱,不過因爲框架的須要,它與真正的DOMContentLoaded有一點區別,在不少新手和舊的書中,不少人將其寫在window.onload回調中,防止dom樹尚未建完就開始對節點操做。而對於框架來講,越早越介入dom就越好,如要進行特徵偵測之類的。domready還能夠知足用戶提早綁定事件需求,由於有時頁面圖片過多等,window.onload事件遲遲不能觸發,這時用戶操做都沒有效果,所以,主流的框架都引入了domReady機制,而且費了很大週摺才兼容全部瀏覽器。具體的策略以下

  • 對於支持DOMContentLoaded事件使用DOMcontentLoaded事件
  • 舊版本IE使用Diego perini發現的著名Hack
    //by Diego Perini 2007.10.5
     function IEContentLoaded (w, fn) {
     var d = w.document, done = false,
     // 只執行一次用戶的回調函數init()
     init = function () {
        if (!done) {
            done = true;
            fn();
        }
     };
    (function () {
        try {
            // DOM樹未建立完以前調用doScroll會拋出錯誤
            d.documentElement.doScroll('left');
        } catch (e) {
            //延遲再試一次~
            setTimeout(arguments.callee, 50);
            return;
        }
        // 沒有錯誤就表示DOM樹建立完畢,而後立馬執行用戶回調
        init();
                 })();
    //監聽document的加載狀態
    d.onreadystatechange = function() {
        // 若是用戶是在domReady以後綁定的函數,就立馬執行
        if (d.readyState == 'complete') {
            d.onreadystatechange = null;
            init();
        }
             };
    }

關於加載思路:http://www.cnblogs.com/horve/p/4092064.html

司徒正美《javascript的事件加載》:http://www.cnblogs.com/rubylouvre/archive/2009/08/26/1554204.html  


此外,IE還能夠經過script defer hack進行斷定

     document.write("<script id=__ie_onload defer src=//0 mce_src=http://0></scr"+"ipt>"); 
        script = document.getElementById("__ie_onload"); 
        script.onreadystatechange = function() { //IE即便是死鏈也能觸發事件 
                    if (this.readyState == "complete") 
        init(); // 指定了defer的script在dom樹建完才觸發
    }; 

不過還有個問題,若是咱們的種子模塊是動態加載的,在它插入dom樹時,DOM樹是否已經建完呢?這該怎麼觸發ready回調?jQuery的方案是,連onload也監聽了 ,但若是連onload也沒遇上,就斷定document.readyState等於complete。(完美)惋惜ff3.6以前沒有這屬性,看mass的方案

    var readyList = [];
    mess.ready = function( fn ) {
        if ( readyList ) {
            fn.push( fn );
        } else {
            fn();
        }
    }
    var readyFn ,ready = W3C ? "DOMContentLoaded" : "readyStatechange";
    function fireReady() {
        for (var i = 0 , fn; fn = readyList[i++]) {
            fn();
        }
        readyList = null;
        fireReady = $.noop; //惰性函數,防止IE9調用_checkDeps
    }
    function doScrollCheck() {
        try { //IE下經過doScrollCheck檢測DOM樹是否建設完
            html.doScroll("left");
            fireReady();
        } catch (e){
            setTimeout(doScrollCheck);
        }
    }

    //FF3.6前,沒有readyState屬性
    //http://www.cnblogs.com/rubylouvre/archive/2012/12/18/2822912.html
    if (!document.readyState){
        var readyState = document.readyState  =  document.body ? "complete" : "loading";
        if (document.readyState === "complete") {
            fireReady(); //若是在domReay以外加載
        } else {
            $.bind(document,ready,readyFn = function(){
                if(W3C || document.readyState === "complete") {
                    fireReady();
                    if(readyState){ //IE下不能該項document.readyState
                        document.readyState = "complete";
                    }
                }
            });
            if (html.doScroll){
                try {//若是跨域就報錯,證實有兩個窗口
                    if (self.eval === parent.eval) {
                        doScrollCheck();
                    }
                } catch (e) {
                    doScrollCheck();
                }
            }
        }

    }

6.無衝突處理

無衝突處理也叫多庫共存,$是這個重要的函數名,以致於你們都愛拿它來作本身的命名空間,當jQuery開始發展時,Prototype是主流,jQuery發明了noConflict函數

    var window = this,
    undefined,
    _jQuery = window.jQuery,
    _$ = window.$,
    //將window存入閉包中的同名變量,方便內部函數調用windows不用太麻煩查找它。
    //_jQuery與_$用於之後重寫
    jQuery = window.jQuery = window.$ = function(selector, context){
        //用於返回一個jQuery對象
        return new jQuery.fn.init(selector,context);
    }

    jQuery.extend({
        noConflict : function(deep) {
            //引入jQuery類庫後,閉包外邊的window.$與window.jQuery都儲存着一個函數
            //它是用來生成jQuery對象或在domReady後執行裏面的函數
            //回顧最上面的代碼,在尚未把function賦值給它們時,_jQuery和_$已經被賦值了,所以,它們兩的值必然是undefined
            //所以,這種放棄控制權的技術很簡單,就是用undefined把window.$裏邊jQuery函數清除掉。
            //這時,prototype或mootools的$就被拿走了
            window.$ = _$; //至關於window.$ = undefined,若是你有一個叫jQuery的庫,也能大方的過渡出去。
            //這時,須要給noConflict添加一個布爾值,true
        
        if (deep)
            //但咱們必須使用一個東西接納jQuery與jQuey的入口函數
            //閉包裏邊的東西除非被window等宿主引用,不然是不可見的
            //所以,咱們把閉包裏的jQuery return出去,外面用一個變量接納就能夠
            window.jQuery = _jQuery; //至關window.jQuery = undefined
        return jQuery;
        }
    })

使用時,先引入別人的庫,而後引入jQuery,使用調用$.noConflict()進行更名,這樣就不影響別人的$運行了。

mass的操做方式是在script標籤上定義一個nick屬性,那麼釋放出來的命名空間就是你的那個屬性值。裏面實現了相似jQuery的機制。

<script nike="aaa" src="mass.js"></script>
<script>
    aaa.log("xxxxxx")
</script>

本章完結

上一章:第一章 : javaScript框架分類及主要功能     下一章:第三章 :模塊加載系統

相關文章
相關標籤/搜索