我理解基于arguments对象实现JavaScript重载,或者通过显式检查参数的类型和长度来理解。请解释这篇文章:http://ejohn.org/blog/javascript-method-overloading/。
答案 0 :(得分:2)
下面的函数中有两个概念,我认为可能是您混淆的原因。
addMethod
使用var old = object[name];
保留对先前添加的函数的引用作为闭包堆栈。addMethod
知道使用Function.length
(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length)定义函数的参数数量,并将其与它创建的闭包堆栈进行比较。如果它不匹配,它会上升到下一个();这就是John Resig所指的那种方法所带来的开销。以下代码创建的日志记录可以帮助您了解正在发生的事情。
// addMethod - By John Resig (MIT Licensed)
function addMethod(object, name, fn) {
var old = object[name];
object[name] = function() {
if (fn.length == arguments.length) {
console.log('Arguments and parameters count are the same, found the function');
return fn.apply(this, arguments);
}
if (typeof old == 'function') {
console.log('Arguments and parameters count are not the same, try the next function in the closure stack');
return old.apply(this, arguments);
}
};
}
function Users() {
// This will be at the bottom of the stack, every call will have to go through the functions below
addMethod(this, "find", function() {
console.log('Called with 0 arguments');
});
// This will be at the middle of the task
addMethod(this, "find", function(name) {
console.log('Called with one argument');
});
// This is the one with the least overhead
addMethod(this, "find", function(first, last) {
console.log('Called with two arguments');
});
}
var users = new Users();
users.find();
users.find('John');
users.find('John', 'Resig');
请记住在尝试理解它们时逐步执行功能。右键单击下面的图像,然后选择“在新选项卡中打开图像”
这里的addMethods
会减少开销和恕我直言,更好的语法和更少的重复。
// addMethods - By Juan Methods, inspired by John Resig (MIT Licensed)
function addMethods(object, name /* fn, fn, fn ... */ ) {
// Key is the parameter count for each passed in function, value is the function itself */
var functionMap = {};
for (var i = 2; i < arguments.length; i++) {
functionMap[arguments[i].length] = arguments[i];
}
object[name] = function() {
functionMap[arguments.length].apply(this, arguments);
};
}
function Users() {
// Now every function has constant overhead of a single map lookup, which
// is less expensive than multiple method calls up the closure stack
addMethods(this, "find",
function() {
console.log('Called with 0 arguments');
},
function(name) {
console.log('Called with one argument');
},
function(first, last) {
console.log('Called with two arguments');
}
);
}
var users = new Users();
users.find();
users.find('Jack');
users.find('John', 'Resig');