JavaScript 中的 (function() { } )() 构造是什么?

IT技术 javascript iife
2021-01-05 22:39:20

我曾经知道这是什么意思,但我现在很挣扎......

这基本上是说document.onload吗?

(function () {

})();
6个回答

它是一个立即调用的函数表达式,简称IIFE它在创建后立即执行。

它与任何事件(例如document.onload)的任何事件处理程序无关
考虑第一对括号内的部分:....它是一个正则函数表达式。再看最后一对,这个一般是加在表达式中调用函数;在这种情况下,我们的先前表达式。(function(){})();(function(){})();

当试图避免污染全局命名空间时,经常使用这种模式,因为在 IIFE 内部使用的所有变量(就像在任何其他普通函数中一样)在其范围之外是不可见的。
这就是为什么,也许,您将此构造与 for 的事件处理程序混淆window.onload,因为它通常用作:

(function(){
  // all your code here
  var foo = function() {};
  window.onload = foo;
  // ...
})();
// foo is unreachable here (it’s undefined)

Guffa建议的更正

该函数在创建后立即执行,而不是在解析后执行。整个脚本块在其中的任何代码被执行之前被解析。此外,解析代码并不自动意味着它已被执行,例如,如果 IIFE 在一个函数内,那么在调用该函数之前它不会被执行。

更新 由于这是一个非常受欢迎的话题,值得一提的是 IIFE 也可以用ES6 的箭头函数编写(就像Gajus在评论中指出的那样):

((foo) => {
 // do something with foo here foo
})('foo value')
@gion_13 创建阶段和解析阶段有什么区别?
2021-02-08 22:39:20
重要的是要注意 IFFE 是有用的,因为var关键字是全局范围的。因此,JS 开发人员必须找到一种方法来“限制”代码中的变量。
2021-02-21 22:39:20
@jlei 在我看来,js 程序的生命周期包括以下阶段:解析、创建/编译、执行。尽管实际实现(和命名 :)) )可能因浏览器而异,但我们可以通过注意解析错误、提升和运行时错误来确定代码中的这些阶段。我个人在这方面没有找到很多资源,因为它的级别太低,而且不是程序员可以控制的。您可以在此 SO 帖子中找到某种解释:stackoverflow.com/a/34562772/491075
2021-03-03 22:39:20
@sam firat 最重要的是,有 varianle 声明和 new 关键字。这意味着在您的示例中,您正在实例化由它的构造函数(匿名函数表达式)定义的新对象,并且它是通过 new 运算符调用的,而不是像 IIFE 示例中那样通过调用函数来调用。当然,该函数就像其内容的闭包一样,但到目前为止,这是一个不同的用例。
2021-03-04 22:39:20
@Pankaj — 就其本身而言,它甚至在语法上都不是有效的 JS(它是一个函数表达式,但不在表达式上下文中,因此被视为语法错误)。
2021-03-05 22:39:20

它只是一个在创建后立即执行的匿名函数。

这就像你将它分配给一个变量,然后在没有变量的情况下使用它:

var f = function () {
};
f();

在 jQuery 中,您可能会想到类似的构造:

$(function(){
});

这是绑定ready事件的简短形式

$(document).ready(function(){
});

但是上述两个构造不是IIFE

@FrenkyB 没有必要,不,但鼓励(分号在 Javascript 中实际上通常不是必需的,但这是一种很好的做法)。每一个都是恰好包含匿名函数的语句,而不是函数声明。
2021-02-11 22:39:20
@swordofpain 考虑第二个片段;通过将其转换为 IIFE,在函数末尾的 add() 是否有任何value?
2021-02-20 22:39:20
最后两个不是真正的 IIFE,因为它们是在 DOM 准备好而不是立即调用时调用的
2021-02-24 22:39:20
@swordofpain:是的,没错,它们不是 IIFE。
2021-02-26 22:39:20
末尾的分号是必需的吗?
2021-03-06 22:39:20

立即调用函数表达式 (IIFE) 立即调用函数。这只是意味着函数在定义完成后立即执行。

三个比较常见的说法:

// Crockford's preference - parens on the inside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
}());

//The OPs example, parentheses on the outside
(function() {
  console.log('Welcome to the Internet. Please follow me.');
})();

//Using the exclamation mark operator
//https://stackoverflow.com/a/5654929/1175496
!function() {
  console.log('Welcome to the Internet. Please follow me.');
}();

如果对其返回值没有特殊要求,那么我们可以这样写:

!function(){}();  // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}();  // => NaN

或者,它可以是:

~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();

你甚至可以写:

new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required
aa和赢家是 ;(function(){}());
2021-02-07 22:39:20
@Awesome_girl:并不是说有很多方法可以写同样的东西;JS 有一个松散的类型系统,其中的运算符可以对任何值类型进行操作。你可以做1 - 1,你也可以很容易地做到true - function(){}这只是一件事(中缀减法运算符),但具有不同的,甚至是无意义的操作数。
2021-02-23 22:39:20
使用 Crockford 的函数 (function(){}()) 比其他函数有什么好处?
2021-02-23 22:39:20
为什么有这么多方法可以写同样的东西?!!>_< 我不喜欢这种语言
2021-02-24 22:39:20
最后一个31.new' 是无效语法
2021-02-27 22:39:20

该构造称为立即调用函数表达式 (IIFE),这意味着它会立即执行。将其视为当解释器到达该函数时自动调用的函数。

最常见的用例:

它最常见的用例之一是限制通过var. 通过创建的变量var的范围仅限于一个函数,因此这个构造(它是围绕某些代码的函数包装器)将确保您的变量范围不会泄漏到该函数之外。

在下面的例子中,count在立即调用的函数之外将不可用,即范围count不会泄漏到函数之外。如果ReferenceError您尝试在立即调用的函数之外访问它,您应该得到一个, 。

(function () { 
    var count = 10;
})();
console.log(count);  // Reference Error: count is not defined

ES6 替代品(推荐)

在 ES6 中,我们现在可以通过let创建变量const它们都是块范围的(不同于var函数范围的)。

因此,无需在我上面提到的用例中使用复杂的 IIFE 构造,您现在可以编写更简单的代码来确保变量的作用域不会泄漏到您想要的块之外。

{ 
    let count = 10;
}
console.log(count);  // ReferenceError: count is not defined

在这个例子中,我们用来let定义count变量,它count限制了我们用大括号创建的代码块{...}

我称之为“curl监狱”。

我喜欢Curly Jail 的命名。也许它会坚持:)
2021-03-01 22:39:20

也就是说立即执行。

所以如果我这样做:

var val = (function(){
     var a = 0;  // in the scope of this function
     return function(x){
         a += x;
         return a;
     };
})();

alert(val(10)); //10
alert(val(11)); //21

小提琴:http : //jsfiddle.net/maniator/LqvpQ/


第二个例子:

var val = (function(){
     return 13 + 5;
})();

alert(val); //18
我不明白这是什么证明它的自我调用?
2021-02-10 22:39:20
@Exitos 因为它返回该函数。我再举第二个例子。
2021-02-12 22:39:20
很容易理解+1
2021-02-18 22:39:20