Вот подход, который допускает перегрузку реальных методов с использованием типов параметров, показанных ниже:
Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);
Редактировать (2018) : С тех пор, как это было написано в 2011 году, скорость прямых вызовов методов значительно возросла, а скорость перегруженных методов - нет.
Я бы не рекомендовал такой подход, но стоит подумать над тем, как решить эти проблемы.
Вот эталон различных подходов - https://jsperf.com/function-overloading. Это показывает, что перегрузка функций (с учетом типов) может быть примерно в 13 раз медленнее в Google Chrome V8 по состоянию на 16,0 (бета) .
Наряду с передачей объекта (т. Е. {x: 0, y: 0}
), можно также использовать подход C, когда это уместно, называя методы соответственно. Например, Vector.AddVector (vector), Vector.AddIntegers (x, y, z, ...) и Vector.AddArray (integerArray). Вы можете посмотреть библиотеки C, такие как OpenGL, для вдохновения в именовании.
Редактировать : я добавил тест для прохождения объекта и тестирования объекта, используя как 'param' in arg
, так и arg.hasOwnProperty('param')
, и перегрузка функции намного быстрее, чем передача объекта и проверка свойств (по крайней мере, в этом тесте).
С точки зрения проектирования перегрузка функции допустима или логична только в том случае, если перегруженные параметры соответствуют одному и тому же действию. Таким образом, само собой разумеется, что должен быть базовый метод, который касается только конкретных деталей, в противном случае это может указывать на неправильный выбор дизайна. Таким образом, можно также разрешить использование перегрузки функций путем преобразования данных в соответствующий объект. Конечно, нужно учитывать масштаб проблемы, поскольку нет необходимости создавать сложные дизайны, если вы хотите просто напечатать имя, но для разработки каркасов и библиотек такая мысль оправдана.
Мой пример взят из реализации Rectangle - отсюда и упоминание Dimension and Point. Возможно, Rectangle может добавить метод GetRectangle()
к прототипу Dimension
и Point
, и тогда проблема перегрузки функции будет решена. А как насчет примитивов? Итак, у нас есть длина аргумента, которая теперь является допустимым тестом, поскольку у объектов есть метод GetRectangle()
.
function Dimension() {}
function Point() {}
var Util = {};
Util.Redirect = function (args, func) {
'use strict';
var REDIRECT_ARGUMENT_COUNT = 2;
if(arguments.length - REDIRECT_ARGUMENT_COUNT !== args.length) {
return null;
}
for(var i = REDIRECT_ARGUMENT_COUNT; i < arguments.length; ++i) {
var argsIndex = i-REDIRECT_ARGUMENT_COUNT;
var currentArgument = args[argsIndex];
var currentType = arguments[i];
if(typeof(currentType) === 'object') {
currentType = currentType.constructor;
}
if(typeof(currentType) === 'number') {
currentType = 'number';
}
if(typeof(currentType) === 'string' && currentType === '') {
currentType = 'string';
}
if(typeof(currentType) === 'function') {
if(!(currentArgument instanceof currentType)) {
return null;
}
} else {
if(typeof(currentArgument) !== currentType) {
return null;
}
}
}
return [func.apply(this, args)];
}
function FuncPoint(point) {}
function FuncDimension(dimension) {}
function FuncDimensionPoint(dimension, point) {}
function FuncXYWidthHeight(x, y, width, height) { }
function Func() {
Util.Redirect(arguments, FuncPoint, Point);
Util.Redirect(arguments, FuncDimension, Dimension);
Util.Redirect(arguments, FuncDimensionPoint, Dimension, Point);
Util.Redirect(arguments, FuncXYWidthHeight, 0, 0, 0, 0);
}
Func(new Point());
Func(new Dimension());
Func(new Dimension(), new Point());
Func(0, 0, 0, 0);