Как проверить равенство функций в Javascript - программирование

Как проверить равенство функций в Javascript

Как я могу получить положительный тест на равенство бар и foo?

 foo = function() {
    a = 1;
 }; 

 bar = function() {
    a = 1;
 }; 

 if (foo === bar) alert('baz');
 if (foo == bar) alert('qux');

Оба вышеуказанных условия ложны.

Обновлено - по просьбе причины, по которой мне нужно проверить равенство функции

Я создаю структуру Publish/Subscribe и должен передать callback inorder для отмены подписки на тему.

Смотрите скрипту: http://jsfiddle.net/jamiefearon/hecMS/47/

4b9b3361

Ответ 1

Вы можете проверить, совпадает ли содержимое двух функций, сравнивая результат вызова toString на них

 var foo = function() {
    a = 1;
 }; 

 var bar = function() {
    a = 1;
 }; 

alert(foo.toString() == bar.toString());​

Это будет, однако, неудачным, если есть только один символ, который отличается. С другой стороны, проверка того, что две функции выполняют одно и то же, практически невозможна.

Ответ 2

Проблема в том, что существуют разные понятия равенства на функциях.

  • Ссылка равенства. Функции хранятся где-то в памяти и начинаются с определенного адреса. Для двух имен функций (которые по существу являются адресами внутри) ссылочное равенство дает вам true если оба имени указывают на один и тот же адрес. Это вопрос, когда вы назначаете один bar = foo. В JavaScript используется ссылочное равенство.
  • Равенство по исходному коду, как предлагается в другом ответе. Это не сработает, если вы измените любой символ в теле функции. Кроме того, toSource в настоящее время (с 2014 года) доступен только в Firefox, поскольку он не является стандартным W3C.
  • Синтаксические равенства в исходном коде. Можно использовать абстрактные синтаксические деревья, чтобы противостоять изменениям в пространствах и комментариях. Можно использовать альфа-эквивалентность (т.е. Эквивалентность функций, где переменные последовательно переименованы), как определено в лямбда-исчислении, но также существует
  • Расширение равенства, когда функции равны, если они работают одинаково. Там теорема утверждает, что нет простого алгоритма для проверки экстенсионального равенства функций, поэтому это, конечно, не тот, который вы ищете. Хотя на некоторых более продвинутых языках, чем JS, есть
  • Целочисленное равенство (где вы либо доказываете, что функции равны вручную, либо ваша программа не компилируется) и
  • Наблюдательное равенство (этот слишком продвинут, чтобы объяснить).

Итак, позаботьтесь о том, что вы думаете о равенстве.

Ответ 3

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

Запуск пары функций через minifier будет интересен, потому что minifiers выполняет значительную часть статического анализа.

Ответ 4

Если вы посмотрите на источник Node.js для событий

https://github.com/nodejs/node/blob/master/lib/events.js

вы можете видеть, что основная команда использует === для сравнения функций для равенства

Я не уверен, как === реализован для функций, но я надеюсь, что это не toString(), поскольку две разные функции могут иметь один и тот же результат toString(), LOL

Ответ 5

Похоже, если вам нужна эта функциональность, возможно, вам будет лучше реструктурировать вашу программу. Что-то вроде этого может работать:

function baz(myInt) { return 3 + myInt; }
function asd(a) { return 3 + a; }

var foo = baz;
foo(1); //returns 4

var bar = baz;
bar(3); //returns 6

foo === bar; //true

bar = asd;
bar(3); //returns 6

foo === bar; //false

Ответ 6

В принципе, это невозможно вообще. Невозможно проверить функциональное равенство в javascript. Самое близкое, что вы можете получить, либо сравнить их код как строку для равенства.

Ответ 7

Простой подход: если вы внедряете свой API подписки для возврата уникального идентификатора при каждом его вызове, то это будет так же просто, как вызывать API отписки с этим идентификатором. Внутри простого сценария вы должны использовать простой массив для хранения всех подписчиков, но при таком подходе вам придется хранить. Идентификатор может быть простым счетчиком, который вы можете увеличить с каждым вызовом подписки.

{Функция обратного вызова идентификатора: абонент}

Итак, переадресуйте всех подписчиков, если вы хотите публиковать их всем подписчикам.

Расширенный подход: Вместо того, чтобы принимать простое имя функции в API подписки, примите объект класса, который должен иметь функцию onMessage (или любое другое имя, которое вы хотите дать этому методу). Затем вы можете просто передать тот же экземпляр объекта для отмены подписки API, чтобы получить незарегистрированный. Когда вам нужно уведомить абонента, вы можете вызвать функцию instance.onMessage для всех подписчиков. Сравнение двух ссылок на объекты очень просто.