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); } }); })();