seajs的简化版sea-me.js,自己改的

完整代码

(function(global) {

    if(global.seajs) {

        return;

    }

    var seajs = global.seajs = {};

    var data = seajs.data = {};

    data.paths = {};

    data.vars = {};

    var DIRNAME_RE = /.*\//;

    function dirname(path) {

        return path.match(DIRNAME_RE)[0];

    }

    function isType(type) {

        return function(obj) {

            return {}.toString.call(obj) == "[object " + type + "]";

        }

    }

    var isObject = isType("Object");

    var isString = isType("String");

    var isArray = Array.isArray || isType("Array");

    var isFunction = isType("Function");

    var scripts = document.scripts;

    var loaderScript = scripts[scripts.length - 1];

    var seajsDir = dirname(loaderScript.src); //sea.js路径

    var supportOnload = "onload" in loaderScript;

    var cwd = dirname(location.href); //当前工作目录

    var DOT_RE = /\/\.\//g;

    var MULTI_SLASH_RE = /([^:/])\/+\//g;

    var DOUBLE_DOT_RE = /\/[^/]+\/\.\.\//;

    function realpath(path) {

        // /a/b/./c/./d ==> /a/b/c/d

        path = path.replace(DOT_RE, "/");

        // a///b/////c ==> a/b/c

        path = path.replace(MULTI_SLASH_RE, "$1/");

        // a/b/c/../../d  ==>  a/b/../d  ==>  a/d

        while(path.match(DOUBLE_DOT_RE)) {

            path = path.replace(DOUBLE_DOT_RE, "/");

        }

        return path;

    }

    var PATHS_RE = /^([^/:]+)(\/.+)$/;

    var VARS_RE = /{([^{]+)}/g;

    function parsePaths(uri) {

        var m, paths = data.paths;

        if(paths && (m = uri.match(PATHS_RE)) && isString(paths[m[1]])) {

            uri = paths[m[1]] + m[2];

        }

        return uri;

    }

    function parseVars(uri) {

        var vars = data.vars;

        if(vars && uri.indexOf("{") > -1) {

            uri = uri.replace(VARS_RE, function(m, key) {

                return isString(vars[key]) ? vars[key] : m;

            });

        }

        return uri;

    }

    // normalize("path/to/a") ==> "path/to/a.js"

    function normalize(path) {

        var last = path.length - 1;

        return path.substring(last - 2) === ".js" ? path : path + ".js";

    }

    var HOST_RE = /^\/\/.|^[https?|file]:\/\/./;

    var ROOT_DIR_RE = /^.*?\/\/.*?\//;

    function addBase(uri, refUri) {

        var ret, first = uri.charCodeAt(0);

        // Host

        if(HOST_RE.test(uri)) {

            ret = uri.indexOf("//") === 0 ? location.protocol + uri : uri;

        }

        // Absolute

        else if(first === 47 /* "/" */ ) {

            var m = cwd.match(ROOT_DIR_RE);

            ret = m[0] + uri.substring(1);

        }

        // Relative

        else if(first === 46 /* "." */ ) {

            ret = (refUri ? dirname(refUri) : cwd) + uri;

        }

        // default

        else {

            ret = seajsDir + uri;

        }

        return realpath(ret);

    }

    var head = document.getElementsByTagName("head")[0] || document.documentElement;

    var currentlyAddingScript = null;

    function request(url) {

        var node = document.createElement("script");

        addOnload(node, url);

        node.async = true;

        node.src = url;

        currentlyAddingScript = node;

        head.appendChild(node);

        currentlyAddingScript = null;

    }

    function addOnload(node, url) {

        if(supportOnload) {

            node.onload = onload;

        } else {

            node.onreadystatechange = function() {

                if(/loaded|complete/.test(node.readyState)) {

                    onload();

                }

            }

        }

        function onload() {

            node.onload = node.onreadystatechange = null;

            var mod = cachedMods[node.src];

            if(supportOnload) {

                mod.dependencies = anonymousMeta.deps;

                mod.callback = anonymousMeta.callback;

            }

            mod.load();

            head.removeChild(node);

            node = null;

            anonymousMeta = null;

            mod.callback && mod.callback();

        }

    }

    function getCurrentScript() {

        if(currentlyAddingScript) {

            return currentlyAddingScript;

        }

        var i, script, scripts = head.getElementsByTagName("script");

        for(i = scripts.length - 1; i >= 0; i--) {

            script = scripts[i];

            if(script.readyState === "interactive") {

                return script;

            }

        }

    }

    function inArray(arr, obj) {

        var i = arr.length;

        while(i--) {

            if(arr[i] === obj) {

                return true;

            }

        }

        return false;

    }

    var cachExps = seajs.exports = {};

    var cachedMods = seajs.cachedMods = {};

    function Module() {

        this.dependencies = [];

        this.deps = [];

        this.entry = [];

    }

    Module.resolve = function(uri, refUri) {

        uri = parsePaths(uri);

        uri = parseVars(uri);

        uri = normalize(uri);

        uri = addBase(uri, refUri);

        return uri;

    }

    // Resolve module.dependencies

    Module.prototype.resolve = function() {

        var mod = this;

        var i, deps = mod.dependencies;

        for(i = 0, len = deps.length; i < len; i++) {

            mod.deps[i] = Module.resolve(deps[i], mod.uri);

        }

    }

    Module.prototype.load = function() {

        var i, m, mod = this;

        mod.resolve();

        for(i = 0; i < mod.deps.length; i++) {

            if(!cachedMods[mod.deps[i]]) {

                m = cachedMods[mod.deps[i]] = new Module();

                m.uri = mod.deps[i];

                m.fetch();

            }

        }

    }

    // Fetch a module

    Module.prototype.fetch = function() {

        var mod = this;

        request(mod.uri);

    }

    Module.prototype.call = function(call) {

        var mod = this;

        if(0 === mod.deps.length) {

            call();

        } else {

            mod.n = 0;

            var i, entry;

            for(i = 0; i < mod.deps.length; i++) {

                if(!cachExps[mod.deps[i]]) {

                    entry = cachedMods[mod.deps[i]].entry;

                    mod.n++;

                    if(!inArray(entry, mod)) {

                        entry.push(mod);

                    }

                }

            }

            if(0 === mod.n) {

                call();

            }

        }

    }

    Module.prototype.cutExp = function() {

        var mod = this;

        var i, exports = [];

        for(i = 0; i < mod.deps.length; i++) {

            exports.push(cachExps[mod.deps[i]]);

        }

        return exports;

    }

    Module.use = function(deps, callback) {

        var mod = new Module();

        deps = deps ? deps : [];

        mod.dependencies = isArray(deps) ? deps : [deps];

        mod.callback = function() {

            function call() {

                var exports = mod.cutExp();

                if(isFunction(callback)) {

                    callback.apply(global, exports);

                }

                mod = null;

            }

            mod.call(call);

        }

        mod.load();

        mod.callback();

    }

    var anonymousMeta = null;

    Module.define = function(deps, factory) {

        var argsLen = arguments.length;

        if(argsLen === 1) {

            factory = deps;

            deps = [];

        }

        deps = isArray(deps) ? deps : [deps];

        var callback = function() {

            var mod = this;

            function call() {

                var exports = mod.cutExp();

                var m, i, exp = (isFunction(factory) ? factory.apply({}, exports) : factory) || true;

                cachExps[mod.uri] = exp;

                for(i = 0; i < mod.entry.length; i++) {

                    m = mod.entry[i];

                    m.n--;

                    m.callback();

                }

                delete cachedMods[mod.uri];

                mod = null;

            }

            mod.call(call);

        }

        if(supportOnload) {

            // Save information for the script onload event

            anonymousMeta = {

                deps: deps,

                callback: callback

            };

        } else {

            var node = getCurrentScript();

            var mod = cachedMods[node.src];

            mod.dependencies = deps;

            mod.callback = callback;

        }

    }

    // Public API

    seajs.use = function(deps, callback) {

        Module.use(deps, callback);

        return seajs;

    }

    global.define = Module.define;

    seajs.config = function(configData) {

        var curr, prev, key, k;

        for(key in configData) {

            curr = configData[key];

            prev = data[key];

            // Merge object config such as paths, vars

            if(prev && isObject(prev)) {

                for(k in curr) {

                    prev[k] = curr[k];

                }

            }

        }

        return seajs;

    }

})(this);

使用方法很简单,类似seajs和requirejs,略微不同

define:

define(['a','b',...],function(a,b,...){

    a.a();

    b.b();

    return obj;

});

//或者

define('a',function(a){

    a.a();

    return obj;

});

//第一个参数为依赖,第二个是工厂函数,返回带有方法的对象,用来自己开发js库。

seajs.use:

seajs.use(['a','b',...],function(a,b,...){

    a.a();

    b.b();

});

//或者

seajs.use('a',function(a){

    a.a();

});

你可能感兴趣的:(seajs的简化版sea-me.js,自己改的)