SOURCE

console 命令行工具 X clear

                    
>
console
/* 
 * date:    2017.04.24
 * version: v1.0.3.0
 * author:  blqw
 */
(function (window, name) {
    if (name in window) {
        throw new Error(["already '", name, "' in 'window'"].join(""));
    }

    function trim(str) {
        switch (typeof str) {
            case "undefined": return "";
            case "boolean": return str ? "true" : "";
            case "string": return str.replace(/^\s+|\s+$/g, "");
            case "number": return str.toString();
            case "object": return trim(str || "");
            case "function": return trim(str());
        }
    }

    //在字符串中查找指定的字符,如果不存在返回字符串长度
    function findIndex(str, chars) {
        var r = str.length;
        for (var i = 0; i < chars.length; i++) {
            var j = str.indexOf(chars[i]);
            if (j >= 0 && r > j)
                r = j;
        }
        return r;
    }

    //处理url中的 \..
    function backtrack(path) {
        while (path !== (path = path.replace(/((\/|^)[^\/]+\/\.\.)|^\/\.\.|^\.\./g, ""))) {
        }
        return path;
    }

    function parseSearch(search) {
        if (/^[^#][^?#]*[?#]/.test(search)) {
            throw new Error('Argument format is invalid. from string : "' + search + '"');
        }
        search = trim(search);
        if (search.charAt(0) === "?") {
            search = search.substr(1);
        }
        var params = {};
        if (search.charAt(0) === "&") {
            params[""] = "";
            search = search.substr(1);
        }
        if (search === "") return params;
        var args = search.match(/[?]?[^=&]+=[^=&]+/g);
        if (args == null) return params;
        for (var j = 0; j < args.length; j++) {
            try {
                var kv = args[j].split("=");
                setPropValue(params, decodeURIComponent(kv[0]), decodeURIComponent(kv[1]));
            } catch (e) {
                console.debug(e);
            }
        }
        return params;
        //---- function ----

        //设置属性的值
        function setPropValue(object, name, value) {
            var reg = /\[([0-9]*)\]|\[([^\[\]\.]+)\]|\.([^\[\]\.]+)|^([^\[\]\.]+)|\./g;
            var p = {
                get: function () { return object; },
                set: function (value) { object[""] = (object[""] === undefined ? value : [object[""], value]); },
                build: function () { return object; },
                append: function (name) { return new prop(p, name); }
            };
            var m = null;
            while (m = reg.exec(name)) {
                if (m[1] != null) {
                    p = p.append(parseInt(m[1]) || 0);
                } else {
                    var n = m[2] || m[3] || m[4];
                    if (n == null) {
                        object[name] = value;
                        return object;
                    }
                    p = p.append(n);
                }
            }
            p.set(value);
            return p.build();
        }

        function prop(ref, name) {
            this.ref = ref;
            this.name = name;
            this.build = this.ref.build;
            this.get = function () {
                var object = this.ref.get();
                if (object == null) {
                    return null;
                }
                return object[this.name];
            }
            this.set = function (value) {
                var object = this.ref.get();
                if (object == null) {
                    if (typeof this.name === "number") {
                        this.ref.set(object = []);
                    } else {
                        this.ref.set(object = {});
                    }
                }
                if (object[name] !== undefined) {
                    object[name] = [object[name], value];
                } else {
                    object[name] = value;
                }
            }
            this.append = function (name) {
                return this.next = new prop(this, name);
            }
        }
    }

    function urlencoded(params) {
        if (params == null || Object.keys(params).length === 0) {
            return "";
        }
        var arr = [];
        (function (value, name) {

            switch (typeof value) {
                case "undefined":
                    break;
                case "boolean":
                    arr.push(name + "=" + value);
                    break;
                case "string":
                    if (name == null || name === "") {
                        arr.push(encodeURIComponent(value));
                    } else {
                        arr.push(name + "=" + encodeURIComponent(value));
                    }
                    break;
                case "number":
                    arr.push(name + "=" + value);
                    break;
                case "object":
                    if (value instanceof Array) {
                        for (var index = 0; index < value.length; index++) {
                            arguments.callee(value[index] || "", name.length > 0 ? name + "%5B" + (index || "") + "%5D" : "");
                        }
                        return;
                    }
                    if (value !== null) {
                        var keys = Object.keys(value);
                        if (keys.length > 0) {
                            for (var index = 0; index < keys.length; index++) {
                                var key = encodeURIComponent(keys[index]);
                                if (key == null) {
                                    key = "";
                                }
                                if (name.length != 0) {
                                    key = name + "%5B" + key + "%5D";
                                }
                                var val = value[keys[index]];
                                if (val == null) {
                                    val = "";
                                }
                                arguments.callee(val, key);
                            }
                        } else if (value instanceof Date) {
                            var date = value.getFullYear()
                                + "-" + ("0" + (date.getMonth() + 1)).slice(-2)
                                + "-" + ("0" + value.getDate()).slice(-2)
                                + " " + ("0" + value.getHours()).slice(-2)
                                + "%3A" + ("0" + value.getMinutes()).slice(-2)
                                + "%3A" + ("0" + value.getSeconds()).slice(-2);
                        } else {
                            arguments.callee(value.toString(), name);
                        }
                    }
                    break;
                case "function":
                    arguments.callee(value(), name);
                    break;
            }
        })(params, "");
        return arr.join("&");
    }

    var token = new Object();

    function Url(url) {
        if (arguments[1] !== token) {
            return new Url(url, token);
        }
        url = trim(url || window.location.href);

        var _scheme = null; // http://
        var _domain = null; // baidu.com
        var _path = null; // /a/b/c
        var _query = null; // ?id=1
        var _anchor = null; // #abc

        if (url.length > 0) {

            var scheme = /^([^:/]+:\/\/|\/\/)/.exec(url) || "";
            if (scheme && scheme.length > 0) {
                _scheme = scheme[0];
                url = url.substr(_scheme.length);
                _domain = url.substr(0, findIndex(url, ["/", "\\", "?", "#"])).replace(/[\/\\]$/g, "");
                if (_domain.indexOf(".") == -1) {
                    throw new Error('The "url" argument is invalid. because "domian" doesn\'t exist. from string : "' + arguments[0] + '"');
                }
                url = url.substr(_domain.length);
            }
            _path = url.substr(0, findIndex(url, ["?", "#"])).replace(/[?#]$/g, "");
            url = url.substr(_path.length);
            _path = _path.replace(/(\\|\/)+/g, "/");
            _query = url.substr(0, findIndex(url, ["#"]));
            url = url.substr(_query.length);
            _anchor = url;
        }

        this.params = parseSearch(_query);
        var me = this;

        if (typeof Object.defineProperties === "function") {
            var error = function (name, value) {
                throw new Error('The "' + name + '" format is invalid. from string : "' + value + '"');
            }
            Object.defineProperties(this, {
                scheme: {
                    get: function () { return _scheme; },
                    set: function (value) {
                        value = trim(value);
                        if (/^([a-z]+:)?\/\/$/.test(value) === false) {
                            error("scheme", value);
                        }
                        _scheme = value;
                    }
                },
                domain: {
                    get: function () { return _domain; },
                    set: function (value) {
                        value = trim(value);
                        if (/^([a-z0-9]([a-z0-9\-]+[a-z0-9])?\.)+[a-z0-9]+\/?$/.test(value) === false) {
                            error("domain", value);
                        }
                        if (value.slice(-1) === "/") {
                            value = value.slice(0, -1);
                        }
                        _domain = value;
                    }
                },
                path: {
                    get: function () {
                        var path = _path;
                        if (_scheme == null || _scheme === "" || _domain == null || _domain !== "") {
                            return path;
                        }
                        path = backtrack(path);
                        if (path.charAt(0) !== "/") {
                            path = "/" + path;
                        }
                        return path;
                    },
                    set: function (value) {
                        value = trim(value).replace(/([^\/]|^)[\/]{2,}/g, function (m) { return m.charAt(0) === ":" ? "://" : m.charAt(0) + "/"; });
                        if (/^\/?(([^\/?#]+)(\/|$))+$/.test(value) === false) {
                            error("path", value);
                        }
                        _path = value;
                    }
                },
                query: {
                    get: function () {
                        var str = urlencoded(me.params);
                        return (str === "") ? "" : "?" + str;
                    },
                    set: function (value) {
                        me.params = parseSearch(value);
                    }
                },
                anchor: {
                    get: function () { return (_anchor === "" || _anchor.charAt(0) === "#") ? _anchor : "#" + _anchor; },
                    set: function (value) { _anchor = trim(value); }
                }
            });
        } else {
            this.scheme = _scheme;
            this.domain = _domain;
            this.path = _path;
            this.query = _query;
            this.anchor = _anchor;
        }


        this.toString = function () {
            var path = this.path;
            if (_scheme == null || _scheme === "" || _domain == null || _domain !== "") {
                path = backtrack(path);
                if (path.charAt(0) !== "/") {
                    path = "/" + path;
                }
            }
            return [this.scheme, this.domain, path, this.query, this.anchor === "#" ? "" : this.anchor].join("");
        };
    }

    function combine(url1, url2) {
        if (url1 == null || url1.length === 0) {
            return url2 && new Url(url2).toString();
        }
        if (url2 == null || url2.length === 0) {
            return new Url(url1).toString();
        }
        if (/^\.\.[^/]/.test(url2)) {
            url2 = "./" + url2;
        }
        var u1 = new Url(url1);
        var u2 = new Url(url2);

        if (u2.scheme != null) {
            if (u2.scheme === "//" && u1.scheme != null) {
                u2.scheme = u1.scheme;
            }
            return u2.toString();
        }

        if (u2.path != null && u2.path.length > 0) {
            if (u2.path.charAt(0) === "/") {
                u1.path = u2.path;
            }
            else if (u2.path.substr(0, 2) === "./") {
                u1.path = [u1.path, u2.path.substr(u1.path.slice(-1) === "/" ? 2 : 1)].join("");
            }
            else if (u1.path.slice(-1) === "/") {
                u1.path = [u1.path, u2.path].join("");
            } else if (u2.path.charAt(0) !== ".") {
                u1.path = [u1.path.substr(0, u1.path.lastIndexOf("/")), "/", u2.path].join("");
            }
        }

        if (u2.query == null || u2.query.length === 0) {
            if (u2.anchor != null && u2.anchor.length > 0) {
                u1.anchor = u2.anchor;
            } else {
                u1.query = "";
            }
            return u1.toString();
        }

        if (u2.query.substr(0, 2) === "?&") {
            if (u2.query.length > 2) {
                if (u1.query == null || u1.query.length === 0) {
                    u1.query = ["?", u2.query.substr(2)];
                } else {
                    u1.query = [u1.query, u2.query.substr(u1.query.slice(-1) === "&" ? 2 : 1)].join("");
                }
            }
        } else {
            u1.query = u2.query;
        }

        if (u2.anchor != null && u2.anchor.length > 0) {
            u1.anchor = u2.anchor;
        }

        return u1.toString();
    }

    Url.encoded = urlencoded;
    Url.combine = function (url1, url2) {
        if (arguments.length < 2) {
            return arguments[0];
        }
        var _base = url1;
        for (var i = 1; i < arguments.length; i++) {
            _base = combine(_base, arguments[i]).toString();
        }
        return _base;
    };
    Url.parseSearch = parseSearch;
    window[name] = Url;
    if (typeof window.define === "function") {
        window.define(name, [], function () { return Url; });
    }
})(window, "Url");


var test = new Url("http://baidu.com/api/get?id=1");
console.log(test)
<pre>
<script>
var urls = [
    "http://baidu.com/a/b", "c/d",
    "http://baidu.com/a/b", "//c.com/d",
    "http://baidu.com/a/b", "c/d",
    "http://baidu.com/a/b/", "c/d",
    "http://baidu.com/a/b", "/c/d",
    "http://baidu.com/a/b", "../c/d",
    "http://baidu.com/a/b", "./c/d",
    "http://baidu.com/a/b", "../../../c/d",
    "http://baidu.com/a/b", "c//////d",
    //"http://baidu.com/a/b", "/////c//////d",
    "http://baidu.com/a/b?id=1#abc", "c/d?name=blqw",
    "http://baidu.com/a/b?id=1#abc", "c/d?&name=blqw#def",
    "http://baidu.com/a/b?id=1#abc", "..?id=2#"
];
function padRight(str,length) {
    var space = "                                                            ";
    return (str + space).substr(0, length);
}
for (var i = 0; i < urls.length; i += 2) {
    var url = Url.combine(urls[i], urls[i + 1]);
    document.writeln([padRight(urls[i],30), padRight(urls[i + 1],20), url].join("  |  "));

}



</script>
    </pre>