Как сравнить 2 функции в javascript? Я не говорю о внутренней ссылке. СкажемКак сравнить 2 функции в javascript
var a = function(){return 1;};
var b = function(){return 1;};
Можно ли сравнить a
и b
?
Как сравнить 2 функции в javascript? Я не говорю о внутренней ссылке. СкажемКак сравнить 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's body's text as a String),
''+a == ''+b.
//this is the gist of what is happening behind the scences:
a.toString() == b.toString()
Обратите внимание, что это работает с анонимными функциями (которые , справедливо, то, что спросил ОП). Если у вас есть var a = function a() {.... и var b = function b() {... (что многие люди делают, потому что тогда вы получаете более значимые сообщения в своем стеке), тогда нет способа – gotofritz
Вы можете сравнить две переменные, которые могут содержать ссылки на функции, чтобы увидеть, если они относятся к той же самой функции, но вы не можете сравнить две отдельные функции, чтобы увидеть, если они делают то же самое.
Например, вы можете сделать это:
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()
для функций, но это сравнение линейного преобразования строки вашей функции друг к другу, которое, i f даже от маленького бита, который несущественен для того, что он на самом деле производит, не будет работать. Я не могу думать ни о какой ситуации, где я бы рекомендовал это как надежный механизм сравнения. Если бы вы серьезно подумывали об этом, я бы спросил, почему? Что вы действительно пытаетесь выполнить и пытаетесь найти более надежный способ решения проблемы.
Закрытие означает, что вам нужно быть очень осторожным, что вы имеете в виду, когда говорите «сравнить». Например:
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
АСТ содержит всю информацию, необходимую для сравнения - это функция Javascript в виде данных. Вы можете нормализовать имена переменных, проверить закрытие, игнорировать даты и т. Д. В зависимости от ваших потребностей.
Существует множество инструментов и библиотек, которые помогают упростить процесс, но даже при том, что это, вероятно, будет большой работой и, вероятно, не практичным, но в основном это возможно.
Преобразовать функции в строку, а затем заменить разрыв строки и пространство перед сравнением:
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
р/с: Если вы используете ES6, попробуйте использовать let
вместо var
,
это не работает, если объявить функцию типа «function a() {return 1;}»? –
@TarekSalahuddinMahmud Вы можете попробовать еще раз. Я просто проверяю еще раз. Работает. –
Функция 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.
Как говорили другие, это ненадежно, потому что одно пробел различия делает сравнение ложным.
Но что, если вы используете его в качестве защитной меры? («Кто-то изменил мою функцию с тех пор, как я ее создал?»). Тогда вы можете захотеть такого строгого сравнения.
То, что JavaScript даже не разобрал, делает синтаксическую ошибку ... но, что вы подразумеваете под «сравнением»? Различные браузеры поддерживают «toString» по функциональным объектам по-разному, поэтому могут работать в вашем случае. (Но не в этом, потому что он не будет анализировать, поэтому ничего не назначено 'a' или' b'). Я также думаю, что есть некоторые библиотеки, чтобы «задуматься» о JavaScript [в блоках скриптов]. –
, поскольку все объекты в JS - вы, вероятно, могли бы попытаться найти сравнение с аналогичным объектом (http://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – shershen