2012-09-11 54 views
3

是否有可能在Javascript中檢測到重複函數(在某些情況下可能會意外寫入)?在谷歌C​​hrome,在Javascript中識別重複函數

printLah(); //this prints "Haha" for some reason, without even printing an error message in the Javascript console! 
function printLah(){ 
    alert("Hahah!"); 
} 


function printLah(){ 
    alert("Haha"); 
} 

Here it is on JSfiddle.

+1

閱讀[吊裝](http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Histing)。 – josh3736

+0

@ josh3736那篇文章是錯誤的。結果是正確的,但作者對發生的事情的理解是錯誤的。他在那篇文章中闡述的內容與範圍界定無關。看到這個:http://stackoverflow.com/questions/3887408/javascript-function-declaration-and-evaluation-order/3887590#3887590 – slebetman

+0

@slebetman - 你爲什麼認爲[文章](http://www.adequatelygood .com/2010/2/JavaScript-Scoping-and-Hoisting)與範圍界定無關?前三個示例演示範圍行爲(同時也是關於提升)... – nnnnnn

回答

8

簡短的回答是,不,這不是

這是javascript的工作原理。函數名稱只是一個賦予函數的變量。例如:

function foo() { 
    alert('foo!'); 
} 

foo = 1; 

foo(); 

上面的代碼會生成錯誤,因爲數字不是函數!函數名和變量名之間沒有區別。事實上,定義功能的另一種方式看起來就像你如何定義變量:

var foo = function() { 
       alert('foo!'); 
      } 

這是因爲這樣,JavaScript不能防止重新分配,否則你不能功能,作爲一類對象的行爲重新賦值變量(純函數式語言在不允許變量重新賦值時沒有問題)。


變通和最佳實踐:

這是人們一直在說,你不應該在JavaScript中定義了太多的全局變量的原因。這包括功能。否則,它可能會與別人的代碼意外衝突。

有在JavaScript中兩個強大的功能,可以緩解這一問題:對象關閉

因爲javascript支持對象,所以應該使用面向對象的編程來限制程序中全局變量的數量。與傳統的OOP不同,當使用對象作爲集合或名稱空間時,javascript效果更好。這是因爲JavaScript沒有文件範圍,一切都是全局的。

這並不意味着你不應該像傳統OOP那樣創建封裝較小問題的小對象。這意味着如果可以的話,你應該在單個父對象中包含所有的對象。我在這裏並不意味着繼承,我的意思是在一個有關係。查看流行的庫,如jQuery和Raphael,以獲取相關示例。它們只將一個對象導出到全局範圍以避免與其他人的代碼衝突。

但是,這並不能真正保護人們不重新分配對象(因爲它們畢竟是變量)。例如,你可以輕鬆突破jQuery的通過JavaScript的其他位之前,你的HTML文件的頂部這樣做有運行的機會:

jQuery = null; 

,以保護您的代碼被篡改的方式是使用關閉。第三方代碼無法訪問您在關閉中運行的任何代碼。只要你避免那是全局的。

+0

「函數名稱只是一個賦予函數的變量「 - 這不完全正確。嘗試運行這個:'foo(); foo = 1;函數foo(){alert('foo!');}'。請參閱[this](http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname) – Jonathan

+0

仍然如此。您所展示的只是javascript的編譯和評估順序(否則會錯誤地稱爲「提升」)。試試你自己的代碼:'foo(); foo = 1; FOO();函數foo(){alert('foo!');}' – slebetman

2

只需添加一個可能的檢查以便從slebetman的回答中繼續,可以在聲明變量或函數之前使用以下命令檢查存在性。

if (typeof(functionName) == 'undefined') { 
    functionName = function() { 
     // add code here 
    } 
} 

再次,你會做此項檢查的原因是因爲你想/需要把一些在全球範圍內,儘管往往不是需要它。不使用var將其隱含在全局範圍內。

0

試試這個。它適合我!

$(document).ready(function() { 
    var all_functions = []; 
    var duplicate_functions = []; 
    var reportRecipientsDuplicate = []; 
    for (var i in window) { 

     if ((typeof window[i]).toString() == "function") { 
      if (window[i].name) { 
       all_functions.push(window[i].name); 
      } 
     } 
    } 

    var all_functions1 = all_functions.sort(); 


    for (var i = 0; i < all_functions1.length - 1; i++) { 
     if (all_functions1[i + 1] == all_functions1[i]) { 
      duplicate_functions.push(all_functions1[i]); 
     } 
    } 
    console.log("Duplicate functions on page"); 
    console.log(duplicate_functions); 
});