如何比較javascript中的2個函數? 我不是在談論內部參考。說如何比較javascript中的2個函數
var a = function(){return 1;};
var b = function(){return 1;};
是否有可能比較a
和b
?
如何比較javascript中的2個函數? 我不是在談論內部參考。說如何比較javascript中的2個函數
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()
請注意,這與匿名函數(其中,足夠公平,是OP要求的)。如果你有var a = function a(){....和var b = function b(){...(很多人都這樣做,因爲這樣你在你的堆棧中獲得更多有意義的消息),那麼沒有辦法 – gotofritz 2013-06-07 15:21:58
您可以比較可能包含函數的引用,看看他們是否指的是完全一樣的功能兩個變量,但你真的不能比較兩個獨立的功能,看看他們做同樣的事情。
例如,你可以這樣做:
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()
運算符,但是它將函數的字符串轉換相互比較,即使是微不足道的小事,對於它實際產生的結果也是無關緊要的,都是行不通的。我可以想象,我不會推薦這種可靠的比較機制。如果你認真考慮這樣做,我會問爲什麼?你真的想要完成什麼,並試圖找到解決問題的更強大的方法。
閉包意味着當你說「比較」時,你需要非常小心你的意思。例如:
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
超越功能的能力意味着在一般意義上,比較功能是不可能的。
然而,從實際意義上講,你可以用Esprima或Acorn等JavaScript解析庫獲得很長的路。這些讓你建立一個「抽象語法樹」(AST),它是你程序的JSON描述。例如,AST您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功能。您可以根據需要標準化變量名稱,檢查閉包,忽略日期等。
有一些工具和庫可以幫助簡化流程,但即使如此,它很可能是很多工作,可能並不實用,但它大都是可行的。
轉換函數的字符串,然後,在比較之前更換換行和空間:
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
P/S:如果您正在使用ES6,嘗試使用let
代替var
。
如果聲明像「function a(){return 1;}」這樣的函數,它不工作嗎? – 2016-08-25 12:08:41
@TarekSalahuddinMahmud你可以再試一次。我再次檢查。它正在工作。 – 2016-08-25 12:11:09
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 [在腳本塊中]。 – 2012-03-22 06:49:22
因爲一切都是在JS中的對象 - 你可能會嘗試找到像對象比較(http://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – shershen 2012-03-22 06:58:36