9

背景: 我对 C++ 有自学成才的爱好者级别的理解,这已经转化为对 javascript 的类似理解。为了更好地理解 javascript,我决定编写一个 Greasemonkey 脚本来解决 Google 如何处理来自同一域的多个结果的问题。

我写了我的剧本,而且非常简单。现在我觉得这个脚本可能对其他人有用,所以我想发布它。不过,在我这样做之前,我想确定我没有发布不负责任的代码。

我知道糟糕的垃圾收集经常被认为是扩展的问题,并且对我需要在 javascript 中做些什么来防止这种情况进行了一些研究。似乎答案是任何包含在函数中的内存都将在该函数退出时被回收。这似乎解释了为什么我查看的一些流行脚本被包装在一个原本无用的函数中。

这让我想到了这些问题:

  1. 我应该如何处理我的基本 javascript 函数以确保它不会泄漏内存?
  2. 这是我在许多脚本中看到的答案:

    (function(){  
        //code goes here    
    })();
    
  3. 在上面的代码中,第一个括号的用途是什么?这对我来说似乎是多余的。

  4. 当我试图理解该行时,我将其重写为:

    (function main(){  
        //code goes here  
    })   
    main();  
    

这个想法是这只是调用以前未命名的函数。然而这并没有奏效,为什么呢?

我对一般答案更感兴趣,但如果需要,这里是我当前的代码: http: //pastebin.com/qQWKfnJT

4

3 回答 3

9

这种模式(将一个函数包裹在一对括号中,然后在第一对括号之后放置另一对)称为“我立即调用函数表达式”模式(简称IIFE )。它所做的是定义一个匿名函数,然后立即执行它。第一组括号将函数标记为表达式,而不是语句。第二组执行从第一个表达式返回的函数:

// This:
(function(){
    // Todo: Add code
})();

// Translates *approximately* to this:
var _anonymous_function_2723113 = function() {
    // Todo: Add code
};
_anonymous_function_2723113();
delete _anonymous_function_2723113;

至于为什么当你给它一个名字时这个函数不起作用,我建议阅读kangaxx 关于这个主题的文章,特别是在他触及命名函数表达式的地方。简而言之,当您有一个命名函数表达式(而不是语句)时,该名称应该仅可用于函数的范围。

三个和四个 - 至于避免内存泄漏,IIFE 不是避免内存泄漏的方法(正如@elclanrs 所指出的,它只是帮助您避免污染全局范围)。为避免内存泄漏,请避免循环引用(请记住,闭包可能是循环引用的来源)。

祝你好运,并享受自己!

于 2012-08-17T01:30:29.757 回答
0

下面是一个可以使用匿名函数的示例: 让我们有 4 个元素的 id:id_1、id_2、id_3... 我们也希望循环遍历每个元素并分配 onclick 事件。

for (var i=0; i<5; i++) {
    document.getElementById("id_"+i).onclick = function()  {alert(i)}
}

但是当您单击元素时,它们中的每一个都会发出相同的警报 - 4. 原因是在 JavaScript 闭包中,只有最后一个值被存储为局部变量。你可以做什么:

for (var i=0; i<5; i++) {
(function(n){
    document.getElementById("id_"+n).onclick = function() {alert(n)};
})(i);

}

于 2012-08-17T01:50:48.147 回答
-1

SO中已经有很多关于这个问题的答案......这是一个自我执行的功能。它在许多情况下用于保护您的代码免受全局范围的影响。它也以其他方式编写:

function(){}()
(function(){})()
(function(){}())
!function(){}()
(function(){}).call(this)
于 2012-08-17T01:30:18.743 回答