Как зарегистрировать функцию JavaScript с определенной подписью?

Скажем, у вас есть две функции со следующими сигнатурами:

  • addClass( class )
  • addClass( class, duration )

Они живут в сторонней библиотеке (нет призов для угадывания, которые!!).

Если вы вызываете addClass() с двумя параметрами, но регистрируете только 1 подпись, не будет ошибки, и будет вызываться подпись 1. Второй параметр игнорируется.

Итак, есть способ обнаружить, что подпись 2 с двумя параметрами была зарегистрирована?

Ответ 1

Вы можете использовать свойство length объекта функции для проверки подписи. Пример:

function x(a) {}
function y(a,b) {}

alert(x.length); // shows "1"
alert(y.length); // shows "2"

Ответ 2

В JavaScript нет встроенной перегрузки методов. Вы можете создать свой собственный: http://ejohn.org/blog/javascript-method-overloading/

(Обновление 11/5/15: ссылка кажется мертвой, здесь версия Google Cache)

Итак, если вы делаете

function addClass( class ) { console.log('1 arg'); };
function addClass( class, duration ) { console.log('2 args'); };

второй перезаписывает первый. Поэтому, даже если вы назовете "addClass (1)", вывод будет по-прежнему "2 аргумента". То же, что и при выполнении

someObject.addClass = function(a) {...}
someObject.addClass = function(a, b) {...}

Первая "версия" будет потеряна.

Ответ 3

Этого не очень сложно достичь, но метод Resig не очень много, поскольку он проверяет только длину аргументов, которая касается только тангенциально связанных с реальными сигнатурными сигнатурами.

Метод Йоханнеса на самом деле метод, переопределяющий не множественные сигнатуры вызова, и в любом случае не будет работать в режиме JS Strict, где запрещается объявлять несколько функций с тем же именем.

Для правильной реализации вам необходимо реализовать его с помощью переадресации вызовов, заверяя каждую сигнатуру вызова в проверку типа/существования:

function myFunction(arg1, arg2, arg3){
  switch(true){
    case arg1 instanceof someObject:
        myFunction_signature1.apply(this, arguments);
        break;
    case typeof arg1 === "string":
        myFunction_signature2.apply(this, arguments);
        break;
    }
}

Он становится немного более сложным, когда некоторые параметры также являются необязательными.

Ответ 4

Если вы используете node, вы можете использовать func.toString() и проанализировать результат, чтобы получить подпись, которая была использована.