Подтвердить что ты не робот

Как сравнить 2 функции в javascript

Как сравнить 2 функции в javascript? Я не говорю о внутренней ссылке. Скажите

var a = function(){return 1;};
var b = function(){return 1;};

Можно ли сравнить a и b?

4b9b3361

Ответ 1

var a = b = function( c ){ return c; };
//here, you can use a === b because they're pointing to the same memory and they're the same type

var a = function( c ){ return c; },
    b = function( c ){ return c; };
//here you can use that byte-saver Andy E used (which is implicitly converting the function to it body text as a String),

''+a == ''+b.

//this is the gist of what is happening behind the scences:

a.toString( ) == b.toString( )  

Ответ 2

Закрытие означает, что вам нужно быть очень осторожным, что вы имеете в виду, когда говорите "сравнить". Например:

function closure( v ) { return function(){return v} };
a = closure('a'); b = closure('b');
[a(), b()]; // ["a", "b"]

// Now, are a and b the same function?
// In one sense they're the same:
a.toString() === b.toString(); // true
// In another sense they're different:
a() === b(); // false

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

Однако в практическом смысле вы можете пройти очень долгий путь с помощью Javascript, анализирующих библиотеки, такие как Esprima или Acorn. Это позволит вам создать "Абстрактное синтаксическое дерево" (AST), которое представляет собой описание вашей программы JSON. Например, ваши функции return 1 выглядят так:

ast = acorn.parse('return 1', {allowReturnOutsideFunction:true});
console.log( JSON.stringify(ast), null, 2)
{
  "body": [
    {
      "argument": {
        "value": 1,              // <- the 1 in 'return 1'
        "raw": "1",
        "type": "Literal"
      },
      "type": "ReturnStatement" // <- the 'return' in 'return 1'
    }
  ],
  "type": "Program"
}
// Elided for clarity - you don't care about source positions

В AST есть вся информация, необходимая для проведения сравнений - это функция Javascript в форме данных. Вы можете нормализовать имена переменных, проверить закрытие, игнорировать даты и т.д. В зависимости от ваших потребностей.

Существует множество инструментов и библиотек, которые упрощают процесс, но, тем не менее, это, вероятно, много работы и, вероятно, не практично, но в основном это возможно.

Ответ 3

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

Например, вы можете сделать это:

function foo() {
    return 1;
}

var a = foo;
var b = foo;

a == b;   // true

Но вы не можете надежно сделать это:

function foo1() {
    return 1;
}

function foo2() {
    return 1;
}

var a = foo1;
var b = foo2;

a == b;   // false

Вы можете увидеть эту вторую здесь: http://jsfiddle.net/jfriend00/SdKsu/

Существуют некоторые обстоятельства, при которых вы можете использовать оператор .toString() для функций, но сравнивая преобразование строки в вашей литературе, которая, даже если она не соответствует второму биту, который несущественен для того, что он на самом деле производит, не будет работать. Я не могу думать ни о какой ситуации, где я бы рекомендовал это как надежный механизм сравнения. Если бы вы серьезно подумывали об этом, я бы спросил, почему? Что вы действительно пытаетесь выполнить и пытаетесь найти более надежный способ решения проблемы.

Ответ 4

Преобразуйте функцию в строку, затем замените разрыв строки и пробел перед сравнением:

let a = function () {
  return 1
};

let b = function () {
  return 1
};

a = a.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');
b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(a); // 'function () { return 1}'
console.log(b); // 'function () { return 1}'
console.log(a === b); // true

b = function () {
  return 2
};

b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(b); // 'function () { return 2}'
console.log(a === b); // false

b = () => 3;

b = b.toString().replace(/\n/g, '').replace(/\s{2}/g, ' ');

console.log(b); // '() => 3'
console.log(a === b); // false

Ответ 5

toString() для функции возвращает точное объявление. Вы можете изменить код jfriend00, чтобы проверить его.

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

Но сначала вам нужно устранить разницу в их именах.

function foo1() {
    return 1;
}

function foo2() {
    return 1;
}

//Get a string of the function declaration exactly as it was written.
var a = foo1.toString();
var b = foo2.toString();

//Cut out everything before the curly brace.
a = a.substring(a.indexOf("{"));
b = b.substring(b.indexOf("{"));

//a and b are now this string:
//"{
//    return 1;
//}"
alert(a == b); //true.

Как говорили другие, это ненадежно, потому что одно пустое различие делает сравнение ложным.

Но что, если вы используете его в качестве защитной меры? ( "Кто-то изменил мою функцию, так как я ее создал?" ). Возможно, вы действительно захотите такого рода строгого сравнения.