javascript 中的 Init 函数及其工作原理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4212149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Init function in javascript and how it works
提问by Alex Djioev
I often see the following code:
我经常看到下面的代码:
(function () {
// init part
})();
but I never could get my head around how it works. I find the last brackets especially confusing. Could someone explain how it works in terms of Execution Contexts (EC) and Variable Objects (VO)?
但我永远无法理解它是如何工作的。我发现最后一个括号特别令人困惑。有人可以解释它在执行上下文 (EC) 和变量对象 (VO) 方面的工作原理吗?
采纳答案by ken
That pattern will create a new execution context (EC) in which any local variable objects (VO's) will live, and will likewise die when the EC exits. The only exception to this lifetime is for VO's which become part of a closure.
该模式将创建一个新的执行上下文 (EC),其中任何局部变量对象 (VO) 都将存在,并且在 EC 退出时同样会消亡。此生命周期的唯一例外是成为闭包一部分的 VO 。
Please note that JavaScript has no magic "init" function. You might associate this pattern with such since most any self-respecting JS library (jQuery, YUI, etc.) will do this so that they don't pollute the global NS more than they need to.
请注意,JavaScript 没有神奇的“init”函数。您可能会将此模式与此类相关联,因为大多数自尊的 JS 库(jQuery、YUI 等)都会这样做,这样它们就不会比需要的更多地污染全局 NS。
A demonstration:
演示:
var x = 1; // global VO
(function(){
var x = 2; // local VO
})();
x == 1; // global VO, unchanged by the local VO
The 2nd set of "brackets" (those are actually called parens, or a set of parentheses), are simply to invoke the function expression directly preceding it (as defined by the prior set of parenthesis).
第二组“括号”(那些实际上称为括号,或一组括号),只是调用直接在它前面的函数表达式(由前一组括号定义)。
回答by Andrew
The way I usually explain this to people is to show how it's similar to other JavaScript patterns.
我通常向人们解释这一点的方式是展示它与其他 JavaScript 模式的相似之处。
First, you should know that there are two ways to declare a function (actually, there's at least five, but these are the two main culprits):
首先,你应该知道有两种方法可以声明一个函数(实际上至少有五种,但这是两个主要的罪魁祸首):
function foo() {/*code*/}
function foo() {/*code*/}
and
和
var foo = function() {/*code*/};
var foo = function() {/*code*/};
Even if this construction looks strange, you probably use it all the time when attaching events:
即使这个结构看起来很奇怪,你可能在附加事件时一直使用它:
window.onload=function(){/*code*/};
window.onload=function(){/*code*/};
You should notice that the second form is not much different from a regular variable declaration:
您应该注意到第二种形式与常规变量声明没有太大区别:
var bar = 5;
var baz = 'some string';
var foo = function() {/*code*/};
But in JavaScript, you always have the choice between using a value directly or through a variable. If bar
is 5
, then the next two statements are equivalent:
但是在 JavaScript 中,您总是可以选择直接使用值还是通过变量使用值。如果bar
是5
,那么接下来的两个语句是等价的:
var myVal = bar * 100; // use 'bar'
var myVal = 5 * 100; // don't use 'bar'
Well, if you can use 5
on its own, why can't you use function() {\*code*\}
on its own too? In fact, you can. And that's called an anonymous function. So these two examples are equivalent as well:
那么,如果你可以单独使用5
,为什么你不能单独使用function() {\*code*\}
呢?事实上,你可以。这就是所谓的匿名函数。所以这两个例子也是等价的:
var foo = function() {/*code*/}; // use 'foo'
foo();
(function(){/*code*/})(); // don't use 'foo'
The only difference you should see is in the extra brackets. That's simply because if you start a line with the keyword function
, the parser will think you are declaring a function using the very first pattern at the top of this answer and throw a syntax error exception. So wrap your entire anonymous function inside a pair of braces and the problem goes away.
您应该看到的唯一区别是额外的括号。这仅仅是因为如果您以关键字 开始一行function
,解析器会认为您正在使用此答案顶部的第一个模式声明一个函数并抛出语法错误异常。因此,将整个匿名函数包装在一对大括号内,问题就会消失。
In other words, the following three statements are valid:
换句话说,以下三个陈述是有效的:
5; // pointless and stupid
'some string'; // pointless and stupid
(function(){/*code*/})(); // wonderfully powerful
[EDIT in 2020]
[2020年编辑]
The previous version of my answer recommended Douglas Crockford's form of parens-wrapping for these "immediately invoked anonymous functions". User @RayLoveless recommended in 2012 to use the version shown now. Back then, before ES6 and arrow functions, there was no obvious idiomatic difference; you simply had to prevent the statement starting with the function
keyword. In fact, there were lots of ways to do that. But using parens, these two statements were syntactically and idiomatically equivalent:
我的回答的前一个版本推荐了 Douglas Crockford 对这些“立即调用的匿名函数”的括号包装形式。用户@RayLoveless 在 2012 年推荐使用现在显示的版本。那时候,在 ES6 和箭头函数之前,没有明显的惯用差异;您只需阻止以function
关键字开头的语句。事实上,有很多方法可以做到这一点。但是使用括号,这两个语句在语法和惯用语上是等效的:
( function() { /* code */}() );
( function() { /* code */} )();
But user @zentechinc's comment below reminds me that arrow functions change all this. So now only one of these statements is correct.
但是下面用户@zentechinc 的评论提醒我箭头函数改变了这一切。所以现在这些陈述中只有一个是正确的。
( () => { /* code */ }() ); // Syntax error
( () => { /* code */ } )();
Why on earth does this matter? Actually, it's pretty easy to demonstrate. Remember an arrow function can come in two basic forms:
为什么这很重要?实际上,演示起来很容易。请记住,箭头函数可以有两种基本形式:
() => { return 5; }; // With a function body
() => { console.log(5); };
() => 5; // Or with a single expression
() => console.log(5);
Without parens wrapping this second type of arrow function, you end up with an idiomatic mess:
如果没有括号包装第二种类型的箭头函数,你最终会得到一个惯用的混乱:
() => 5(); // How do you invoke a 5?
() => console.log(5)(); // console.log does not return a function!
回答by Guffa
The code creates an anonymous function, and then immediately runs it. Similar to:
该代码创建一个匿名函数,然后立即运行它。相似:
var temp = function() {
// init part
}
temp();
The purpose of this construction is to create a scope for the code inside the function. You can declare varaibles and functions inside the scope, and those will be local to that scope. That way they don't clutter up the global scope, which minimizes the risk for conflicts with other scripts.
这种构造的目的是为函数内部的代码创建一个作用域。您可以在作用域内声明变量和函数,这些变量和函数将是该作用域的局部变量。这样它们就不会弄乱全局范围,从而最大限度地降低与其他脚本发生冲突的风险。
回答by SEoF
I can't believe no-one has answered the ops question!
我不敢相信没有人回答操作问题!
The last set of brackets are used for passing in the parameters to the anonymous function. So, the following example creates a function, then runs it with the x=5 and y=8
最后一组括号用于将参数传递给匿名函数。因此,以下示例创建一个函数,然后使用 x=5 和 y=8 运行它
(function(x,y){
//code here
})(5,8)
This may seem not so useful, but it has its place. The most common one I have seen is
这可能看起来不太有用,但它有它的用处。我见过的最常见的一种是
(function($){
//code here
})(jQuery)
which allows for jQuery to be in compatible mode, but you can refer to it as "$" within the anonymous function.
这允许 jQuery 处于兼容模式,但您可以在匿名函数中将其称为“$”。
回答by Alvaro
Self invoking anonymous function (SIAF)
自调用匿名函数 (SIAF)
Self-invoking functions runs instantly, even if DOM isn't completely ready.
即使 DOM 还没有完全准备好,自调用函数也会立即运行。
回答by Manoj Saini
In simple word you can understand that whenever page load, by this second pair of brackets () function will have called default.We need not call the function.It is known as anonymous function.
简单来说你可以理解,每当页面加载时,通过这第二对括号()函数都会调用default。我们不需要调用该函数。它被称为匿名函数。
i.e.
IE
(function(a,b){
//Do your code here
})(1,2);
It same like as
它和
var test = function(x,y) {
// Do your code here
}
test(1,2);
回答by user3724769
Its is called immediatly invoking function expression (IIFE). Mainly associated with the JavaScript closure concept. Main use is to run the function before the global variable changed, so that the expected behaviour of code can be retained.
它被称为立即调用函数表达式(IIFE)。主要与 JavaScript 闭包概念相关。主要用途是在全局变量改变之前运行该函数,从而可以保留代码的预期行为。