这是什么Javascript(function(){})()语法

时间:2013-07-16 17:07:28

标签: javascript

Javascript中的这种语法究竟是什么?我经常使用(或滥用?):

(function(){})();

我知道它会创建一个匿名函数然后执行它。但是,无法弄清楚为什么必须这样。这不等同于更易读的形式:

 function initSomething() {}
 initSomething();

编辑: 非常感谢所有帮助我理解Javascript成语的精彩回复。

6 个答案:

答案 0 :(得分:4)

第二个示例中的函数不再是匿名的......它的名称为initSomething

第一种语法通常用于设置闭包... trapping var x, y, z以及不在其中的内容,以便它们不会与闭包之外具有相同名称的任何其他变量冲突。

答案 1 :(得分:3)

这是一个自我调用的匿名函数。

function(){}是一个匿名函数 - 文字。

(function(){})()调用该文字。

由于这是一个调用自身的匿名函数,因此它是一个自调用的匿名函数。

第一种形式优于第二种形式的优势在于它为您提供了一种简单的方法来封装您不希望污染全局命名空间的代码。

你也不是不必要地创建一个现在是全局命名空间一部分的函数initSomething,这可能会破坏别的东西。

如果您对更多信息感兴趣,也可以查看here

答案 2 :(得分:3)

在JavaScript中,函数创建新范围。在JavaScript的整个内容周围使用函数包装器将确保您不会污染全局范围。

例如,如果您的HTML文件底部有一些JavaScript:

<script>
var test = 'hello';
alert(test);          //'hello'
alert(window.test);   //'hello'
</script>

如您所见,test变量实际上成为window对象(window.test)的属性,它实际上是JavaScript的全局范围。您不希望在window上设置变量的原因有很多,尤其是未来的兼容性问题(如果更高版本的ECMAScript为test定义window属性会怎样?)。此外,使用全局变量总是很慢,因为每当您使用test时,解释器都需要在范围链中一路跋涉。

以下功能与上述功能相同,不会污染全局范围。它使用function()声明一个匿名函数,然后使用()立即调用它而不使用任何参数。这通常称为立即调用的函数表达式或 IIFE

<script>
(function() {
    var test = 'hello';
    alert(test);          //'hello'
    alert(window.test);   //undefined
}());
</script>

请注意,这只是一个普通的匿名函数,就像任何匿名函数一样。结束大括号之后的一组parens调用匿名函数。围绕整个事物的parens告诉解释器它正在查看值,或表达式,而不是函数声明。这个值只是匿名函数运行时的结果。这使得匿名函数的工作就像一个简单的闭包,程序员可以有效地忽略它。

此外,您可以为IIFE使用两种不同的语法:

(function() {}());
(function() {})();

使用其中任何一个都不太可能有问题,但是当您的代码中出现一些语法问题时会出现some differences。 IMO你最好坚持使用第一个,这也更清楚。

-

关于你的第二个问题:是以下两个等价物吗?

(function(){})();

function initSomething() {}
initSomething();

Errm,wellll,有点。你可能会对它们的处理方式相同,因为在大多数情况下它们的工作方式相同。也就是说,在你的程序中,你将得到与任何一个相同的结果(在两种情况下你都在定义一个函数,然后调用它)。

但重要的是要注意匿名函数和函数声明之间的区别。您可以将匿名函数视为可执行文件或代码块,当您不想定义真实的命名函数时,可以将其作为粘合剂传递。因为它们是匿名的,所以它们不存在于作用域链中,例如,您不能将属性添加到匿名函数对象并在以后使用它们 - 除非您首先将它分配给变量,在这种情况下它是不再是匿名!

声明一个功能是完全不同的。它创建了一个构造函数,您可以反复使用它来创建可以继承原始函数属性的新对象(使用new)。这对许多事情都很有用,特别是在使用像AngularJS这样的框架时。

function Friend(likes_you) {
    //private property, only accessible to instances of this object
    this.likes_you = likes_you;
}

//add a function as a property of Friend's prototype -
//instances of the Friend constructor can call this function
Friend.prototype.greet = function(greeting) {
    if (this.likes_you) {
        alert(greeting);
    } else {
        alert("I don't like you");
    }
};

var you = new Friend(true);
you.greet('hello!');          //alerts 'hello!'

var guy = new Friend(false);  //can make as any Friend objects as we want
guy.greet('hello!');          //alerts "I don't like you"

当然,你不需要做这样的事情,但是知道真正做什么的JavaScript是件好事。这只是JS兔子洞的开始......

答案 3 :(得分:2)

这是立即调用的函数表达式

(function(){
  /* code */ 
}());

取自维基百科,因为它得到了很好的解释。

  

一个立即调用的函数表达式(或IIFE,发音为“iffy”)是一种JavaScript设计模式,它使用JavaScript的函数作用域生成一个词法范围。立即调用的函数表达式可用于避免块内的变量提升,防止污染全局环境,同时允许公共访问方法,同时保留函数中定义的变量的隐私。

有关更详细的说明,请参阅here

  

我知道它会创建一个匿名函数然后执行它。但是,无法弄清楚为什么必须这样。这不等同于更易读的形式:

function initSomething() {}
initSomething();

这不一样,因为initSomething仍然可以被引用,因此不是匿名的。

答案 4 :(得分:1)

你可以两种方式做到,但第一种情况是匿名函数(它没有名字,所以你可以避免冲突等等。)

答案 5 :(得分:1)

基本上它是一个未命名的(匿名)函数,只要加载函数就会立即执行。

这种方法的原因是尽可能多地保留全局范围,并将变量与可能在其他地方定义的其他变量隔离开来,你可以在函数内部定义变量和其他函数,它不会垃圾邮件所有这些都在你的全球范围内。