Как сравнить 2 функции в javascript? Я не говорю о внутренней ссылке. Скажите
var a = function(){return 1;};
var b = function(){return 1;};
Можно ли сравнить a
и b
?
Как сравнить 2 функции в javascript? Я не говорю о внутренней ссылке. Скажите
var a = function(){return 1;};
var b = function(){return 1;};
Можно ли сравнить a
и b
?
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( )
Закрытие означает, что вам нужно быть очень осторожным, что вы имеете в виду, когда говорите "сравнить". Например:
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 в форме данных. Вы можете нормализовать имена переменных, проверить закрытие, игнорировать даты и т.д. В зависимости от ваших потребностей.
Существует множество инструментов и библиотек, которые упрощают процесс, но, тем не менее, это, вероятно, много работы и, вероятно, не практично, но в основном это возможно.
Вы можете сравнить две переменные, которые могут содержать ссылки на функции, чтобы увидеть, относятся ли они к одной и той же функции, но вы не можете сравнить две отдельные функции, чтобы убедиться, что они делают то же самое.
Например, вы можете сделать это:
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()
для функций, но сравнивая преобразование строки в вашей литературе, которая, даже если она не соответствует второму биту, который несущественен для того, что он на самом деле производит, не будет работать. Я не могу думать ни о какой ситуации, где я бы рекомендовал это как надежный механизм сравнения. Если бы вы серьезно подумывали об этом, я бы спросил, почему? Что вы действительно пытаетесь выполнить и пытаетесь найти более надежный способ решения проблемы.
Преобразуйте функцию в строку, затем замените разрыв строки и пробел перед сравнением:
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
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.
Как говорили другие, это ненадежно, потому что одно пустое различие делает сравнение ложным.
Но что, если вы используете его в качестве защитной меры? ( "Кто-то изменил мою функцию, так как я ее создал?" ). Возможно, вы действительно захотите такого рода строгого сравнения.