Javascript 为什么是自动执行匿名函数

Javascript 为什么是自动执行匿名函数,javascript,anonymous-function,Javascript,Anonymous Function,今天我遇到了一个关于自动执行函数的交叉点,但不知怎么的,我最终还是知道了 自动执行匿名函数,然后我读了这篇文章: 问题是,我不知道为什么要使用自动执行匿名函数,因为如果我需要执行以下操作: var test = "a"; (function(foo) { alert(foo); })(test); var test = "a"; alert(foo); 我可以做一些像: var test = "a"; (function(f

今天我遇到了一个关于自动执行函数的交叉点,但不知怎么的,我最终还是知道了 自动执行匿名函数,然后我读了这篇文章:

问题是,我不知道为什么要使用自动执行匿名函数,因为如果我需要执行以下操作:

var test = "a";
(function(foo) {
    alert(foo);
})(test);
var test = "a";
alert(foo);
我可以做一些像:

var test = "a";
(function(foo) {
    alert(foo);
})(test);
var test = "a";
alert(foo);
还是我错过了什么

也可以对函数中的任何代码执行此操作,但我使用alert()使其变得简单


更新: 即使我已经接受并回答了这个问题,我还是想分享我的发现,如果以后有人遇到这个问题:)

使用此符号,我们还可以创建一个无休止的循环,如下所示:

(function loop(){
    // do something here
    loop();
)();

您描述的语法通常被称为“立即调用的函数表达式”或IIFE

常见的用例之一是模拟私有变量:

var ns = (function () {
    var x = 1; // "private"
    return {
        getX: function () {
            return x;
        }
    }
}());
ns.getX(); // 1
ns.x; // undefined because x is "private"

在该示例中,
x
变量是IIFE的局部变量。它不能直接从外面进入。但是,由于它是由
getX
方法引用的,该方法可在IIFE之外访问(因为它是返回对象的一部分),因此对
x
的引用保持活动状态。这就是术语“闭包”的含义。您描述的语法通常被称为“立即调用的函数表达式”或IIFE

常见的用例之一是模拟私有变量:

var ns = (function () {
    var x = 1; // "private"
    return {
        getX: function () {
            return x;
        }
    }
}());
ns.getX(); // 1
ns.x; // undefined because x is "private"

在该示例中,
x
变量是IIFE的局部变量。它不能直接从外面进入。但是,由于它是由
getX
方法引用的,该方法可在IIFE之外访问(因为它是返回对象的一部分),因此对
x
的引用保持活动状态。这就是术语“闭包”通常的含义。如果您只是在内部执行一个
警报,那么自动执行函数实际上并不有用

考虑一下这样的情况:

(function(foo) {
    var a = ..
    // do something with a and foo
})(test);

这里的优点是
a
在方法内部是“私有的”,不能在方法外部使用。因此,
a
不会最终成为一个全局变量,也不会被使用相同名称变量的其他javascript片段覆盖。

如果只在内部执行一个
警报,则自执行函数并不是真正有用的

考虑一下这样的情况:

(function(foo) {
    var a = ..
    // do something with a and foo
})(test);

这里的优点是
a
在方法内部是“私有的”,不能在方法外部使用。因此,
a
不会最终成为一个全局变量,也不会被其他使用相同名称变量的javascript覆盖。

使用IIFE的原因有两个:

1)禁止乱扔垃圾

var a = 'foo';
alert(a);
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs

两个示例都做相同的事情,但在第二个示例中,外部范围内没有变量

2)状态捕获

var a = 'foo';
alert(a);
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs


第一个示例警告
,而第二个示例警告
foo
。你会发现这种技术特别适用于循环。

使用iLife有几个原因:

1)禁止乱扔垃圾

var a = 'foo';
alert(a);
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs

两个示例都做相同的事情,但在第二个示例中,外部范围内没有变量

2)状态捕获

var a = 'foo';
alert(a);
var a = 'foo';
window.setTimeout(function() { alert(a); }, 1);
a = 'bar';
vs


第一个示例警告
,而第二个示例警告
foo
。您会发现这种技术特别适用于循环。

您最初的示例不值得在匿名函数中执行,因此理解为什么要使用这种技术是一个糟糕的示例。下面是一个探索状态捕获的好例子:

var list = [{id: 1, data: null}, ...];

for (var i = 0; i < list.length; i++) {
  (function(item) {
    // start async request, for each item in the list, in the order of the list
    asyncAjax("get-data-from-somewhere.json?what=" + list[i].id, function (response) {
      // thats the on success callback, which gets executed when the server responded
      // each item will have different response times, therefore the order of response is various
      // if we would use simply list[i].data, it wouldn't work correctly, because "i" would has the value of list.length, because the iteration has been finished yet.
      item.data = response;
    });
  })(list[i]);   // the function will preserve the reference to the list item inside, until the function has been fully executed
}

(function(private) {})(outer)

但是第二个更好,因为它对读者来说更明显。

您最初的示例不值得在匿名函数中执行,因此理解为什么要使用此技术是一个糟糕的示例。下面是一个探索状态捕获的好例子:

var list = [{id: 1, data: null}, ...];

for (var i = 0; i < list.length; i++) {
  (function(item) {
    // start async request, for each item in the list, in the order of the list
    asyncAjax("get-data-from-somewhere.json?what=" + list[i].id, function (response) {
      // thats the on success callback, which gets executed when the server responded
      // each item will have different response times, therefore the order of response is various
      // if we would use simply list[i].data, it wouldn't work correctly, because "i" would has the value of list.length, because the iteration has been finished yet.
      item.data = response;
    });
  })(list[i]);   // the function will preserve the reference to the list item inside, until the function has been fully executed
}

(function(private) {})(outer)

但是第二个更好,因为它对读者来说更为明显。

关键行:“我所知道的是,这些小优点对于封装功能和避免全局名称空间中的内容非常有用。”关键行:“我所知道的是,这些小优点对于封装功能和防止全局命名空间中的内容非常有用。“你的答案很好,我喜欢它,我肯定会考虑使用它,但我会接受它,但Tibos的回答更适合我的问题。你的答案是伟大的,我喜欢它,我一定会考虑使用它的某个时候,我会接受它,但Tibos的答案更适合我的问题非常感谢你。f@st答:),我接受了,但是我更喜欢“禁止乱扔垃圾”,我不太同意第二个“状态捕获”的说法。事实上,现在更常见的是使用bind方法来避免暴露在那里的问题。不过,它在幕后使用了相同的技术。非常感谢您的支持f@st答:),我接受了,但我更喜欢“禁止乱扔垃圾”,我不太同意第二种“状态捕获”,事实上,现在更常见的是使用bind方法来避免暴露在那里的问题。不过,它在幕后使用了同样的技术。