2012-09-11 55 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); 
});