2012-03-22 17 views
31

如何比較javascript中的2個函數? 我不是在談論內部參考。說如何比較javascript中的2個函數

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

是否有可能比較ab

+0

JavaScript甚至不會解析語法錯誤...但是,您是什麼意思的「比較」?各種瀏覽器對函數對象的「toString」支持不同,因此可能適用於您的情況。 (但不是在這一個,因爲它不會解析,所以沒有分配給'a'或'b')。我也認爲有些庫可以「反映」JavaScript [在腳本塊中]。 – 2012-03-22 06:49:22

+0

因爲一切都是在JS中的對象 - 你可能會嘗試找到像對象比較(http://stackoverflow.com/questions/1068834/object-comparison-in-javascript) – shershen 2012-03-22 06:58:36

回答

37
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() 
+2

請注意,這與匿名函數(其中,足夠公平,是OP要求的)。如果你有var a = function a(){....和var b = function b(){...(很多人都這樣做,因爲這樣你在你的堆棧中獲得更多有意義的消息),那麼沒有辦法 – gotofritz 2013-06-07 15:21:58

8

您可以比較可能包含函數的引用,看看他們是否指的是完全一樣的功能兩個變量,但你真的不能比較兩個獨立的功能,看看他們做同樣的事情。

例如,你可以這樣做:

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()運算符,但是它將函數的字符串轉換相互比較,即使是微不足道的小事,對於它實際產生的結果也是無關緊要的,都是行不通的。我可以想象,我不會推薦這種可靠的比較機制。如果你認真考慮這樣做,我會問爲什麼?你真的想要完成什麼,並試圖找到解決問題的更強大的方法。

12

閉包意味着當你說「比較」時,你需要非常小心你的意思。例如:

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功能。您可以根據需要標準化變量名稱,檢查閉包,忽略日期等。

有一些工具和庫可以幫助簡化流程,但即使如此,它很可能是很多工作,可能並不實用,但它大都是可行的。

0

轉換函數的字符串,然後,在比較之前更換換行和空間:

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

+0

如果聲明像「function a(){return 1;}」這樣的函數,它不工作嗎? – 2016-08-25 12:08:41

+0

@TarekSalahuddinMahmud你可以再試一次。我再次檢查。它正在工作。 – 2016-08-25 12:11:09

0

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. 

正如其他人所說,這是不可靠的,因爲單個空白的差異會導致比較錯誤。

但是,如果您將其作爲保護措施使用,該怎麼辦? (「有人在我創建它之後改變了我的功能?」)您可能實際上希望進行這種嚴格的比較。