zoukankan      html  css  js  c++  java
  • JavaScript命名空间、函数参数类型重载的实现

    突然心血来潮写的东西,可以考虑在func({arg1: xxx, arg2: xxx})不适用的情况下使用。

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
        <title>命名空间、参数类型重载</title>
        <script type="text/javascript" src="arg-func.js"></script>
        <script type="text/javascript">
            (function () {
                // 支持的参数类型:boolean, number, string, function, array, object,其中object类型的重载函数可被其它类型对应重载函数找不到的时候调用
                var MyFuncs = {
                    'myNamespace.exampleFunc(string str, number num)': function (str, num) {
                        alert('str: ' + str + ' num: ' + num);
                    },
                    'myNamespace.exampleFunc(number num)': function (num) {
                        alert('num: ' + num);
                    },
                    'myNamespace.exampleFunc(array)': function (arr) {
                        alert('arr: ' + arr);
                    },
                    'myNamespace.exampleFunc(object)': function (obj) {
                        alert('object: ' + obj);
                    },
                    'myNamespace.exampleFunc()': function () {
                        alert('无参数重载');
                    }
                };
    
                ArgFunc.parse(MyFuncs);
            })();
        </script>
    </head>
    <body>
        <input type="button" value="myNamespace.exampleFunc('abc',123)" onclick="myNamespace.exampleFunc('abc', 123)" /><br />
        <input type="button" value="myNamespace.exampleFunc(123)" onclick="myNamespace.exampleFunc(123)" /><br />
        <input type="button" value="myNamespace.exampleFunc([1,2,3])" onclick="myNamespace.exampleFunc([1, 2, 3])" /><br />
        <input type="button" value="myNamespace.exampleFunc()" onclick="myNamespace.exampleFunc()" /><br />
        <input type="button" value="myNamespace.exampleFunc(false)" onclick="myNamespace.exampleFunc(false)" /><br />
        <input type="button" value="myNamespace.exampleFunc('abc')" onclick="myNamespace.exampleFunc('abc')" /><br />
    </body>
    </html>
    

    arg-func.js:

    (function () {
        if (!String.prototype.trim) {
            String.prototype.trim = function () {
                return this.replace(/(^s+)|(s+$)/g, '');
            };
        }
    
        var TYPE = { EMPTY: 'empty', BOOLEAN: 'boolean', NUMBER: 'number', STRING: 'string', FUNCTION: 'function', ARRAY: 'array', OBJECT: 'object' };
        function getType(o) {
            if (o === undefined) { return TYPE.EMPTY; }
            if (o === null) { return TYPE.OBJECT; }
            switch (typeof (o)) {
                case TYPE.BOOLEAN: return TYPE.BOOLEAN;
                case TYPE.NUMBER: return TYPE.NUMBER;
                case TYPE.STRING: return TYPE.STRING;
                case TYPE.FUNCTION: return TYPE.FUNCTION;
            }
            switch (Object.prototype.toString.call(o)) {
                case '[object Array]': return TYPE.ARRAY;
                default: return o ? TYPE.OBJECT : TYPE.EMPTY;
            }
        }
    
        var ArgFunc = {
            findFunc: function (args, funcLink) {
                if (!args || args.length == 0) {
                    return funcLink ? funcLink._func : null;
                }
                if (!funcLink) {
                    return null;
                }
                var index = arguments[2] || 0;
                var argType = getType(args[index]);
                var func, nextFunc = funcLink[argType];
                if (index + 1 < args.length) {
                    func = ArgFunc.findFunc(args, nextFunc, index + 1);
                    if (!func) {
                        nextFunc = funcLink[TYPE.OBJECT];
                        func = ArgFunc.findFunc(args, nextFunc, index + 1);
                    }
                } else {
                    func = nextFunc ? nextFunc._func : null;
                    if (!func) {
                        nextFunc = funcLink[TYPE.OBJECT];
                        func = nextFunc ? nextFunc._func : null;
                    }
                }
                return func;
            },
            applyFunc: function (wrapperFunc, args) {
                var funcLink = wrapperFunc._funcs;
                var func = ArgFunc.findFunc(args, funcLink);
                if (!func) {
                    throw '没有找到参数类型匹配的重载方法';
                } else {
                    return func.apply(this, args);
                }
            },
            analyseNamespace: function (fullName, upperNamespace) {
                var namespace = upperNamespace || window;
                var parts = fullName.split('.');
                var name = parts.pop();
                for (var i = 0, part; part = parts[i]; i++) {
                    if (namespace[part] === undefined) {
                        namespace[part] = {};
                    }
                    namespace = namespace[part];
                }
                return { namespace: namespace, name: name };
            },
            parseSingle: function (format, func, namespace) {
                var lp = format.indexOf('('), rp = format.indexOf(')');
                var name = format.substring(0, lp);
                var argTypes = format.substring(lp + 1, rp).split(',');
                for (var i = 0, len = argTypes.length; i < len; i++) {
                    argTypes[i] = argTypes[i].trim().split(/ +/)[0];
                }
                if (argTypes.length == 1 && argTypes[0].length == 0) {
                    argTypes.pop();
                }
    
                var nsnn = ArgFunc.analyseNamespace(name, namespace);
                namespace = nsnn.namespace;
                name = nsnn.name;
    
                var wrapperFunc = namespace[name];
                if (wrapperFunc === undefined) {
                    wrapperFunc = namespace[name] = function () {
                        return ArgFunc.applyFunc(wrapperFunc, arguments);
                    };
                    wrapperFunc._funcs = {};
                }
    
                var funcLink = wrapperFunc._funcs;
                for (var i = 0, argType; argType = argTypes[i]; i++) {
                    if (funcLink[argType] === undefined) {
                        funcLink[argType] = { _func: null };
                    }
                    funcLink = funcLink[argType];
                }
                funcLink._func = func;
            },
            parseArray: function (funcs, namespace) {
                for (var i = 0, func; func = funcs[i]; i++) {
                    ArgFunc.parseSingle(func[0], func[1], namespace);
                }
            },
            parseObject: function (funcs, namespace) {
                for (var format in funcs) {
                    ArgFunc.parseSingle(format, funcs[format], namespace);
                }
            }
        };
    
    
    
    
        ArgFunc.parseObject({
            'ArgFunc.parse(object funcs, object namespace)': function (funcs, namespace) {
                ArgFunc.parseObject(funcs, namespace);
            },
            'ArgFunc.parse(object funcs)': function (funcs) {
                ArgFunc.parseObject(funcs, window);
            },
            'ArgFunc.parse(array funcs, object namespace)': function (funcs, namespace) {
                ArgFunc.parseArray(funcs, namespace);
            },
            'ArgFunc.parse(array funcs)': function (funcs) {
                ArgFunc.parseArray(funcs, window);
            },
            'ArgFunc.parse(string format, function func, object namespace)': function (format, func, namespace) {
                ArgFunc.parseSingle(format, func, namespace);
            },
            'ArgFunc.parse(string format, function func)': function (format, func) {
                ArgFunc.parseSingle(format, func);
            }
        });
    })();
  • 相关阅读:
    Working with the RadioButton and CheclBox controls
    Simple Data Binding in Silverlight 4.0
    Data Binding in Silverlight 4.0
    Building a Simple DataGrid in Silverlight 4.0
    EXCEL数据导入SQL Server数据库中
    正则表达式必知必会
    Eclipse插件一次copy多个文件的相对路径路径
    走出软件作坊
    写在前面的话
    [转载]有经验的Java开发者和架构师容易犯的10个错误
  • 原文地址:https://www.cnblogs.com/dashublog/p/3959388.html
Copyright © 2011-2022 走看看