JavaScript命名空间、函数参数类型重载的实现

迁移自: https://www.cnblogs.com/dashublog/p/3959388.html

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<!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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
(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);
}
});
})();