javascript 中自执行函数的目的是什么?
在 javascript 中,什么时候你想使用 this:
(function(){
//Bunch of code...
})();
而不是 this:
//Bunch of code...
In javascript, when would you want to use this:
(function(){
//Bunch of code...
})();
over this:
//Bunch of code...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
这都是关于变量范围的。 默认情况下,自执行函数中声明的变量仅可用于自执行函数中的代码。 这允许编写代码而无需关心变量在其他 JavaScript 代码块中的命名方式。
例如,正如 Alexander 的评论中提到的:
这将首先记录
3
,然后在下一个console.log
上抛出错误,因为foo
未定义。It's all about variable scoping. Variables declared in the self executing function are, by default, only available to code within the self executing function. This allows code to be written without concern of how variables are named in other blocks of JavaScript code.
For example, as mentioned in a comment by Alexander:
This will first log
3
and then throw an error on the nextconsole.log
becausefoo
is not defined.简单化。 看起来非常正常,几乎让人感到安慰:
但是,如果我在页面中包含一个非常方便的 javascript 库,将高级字符转换为其基本级别的表示形式,会怎么样?
等等……什么?
我的意思是,如果有人输入带有某种重音的字符,但我只想在程序中输入“英语”字符 AZ? 嗯...西班牙语“ñ”和法语“é”字符可以翻译为“n”和“e”的基本字符。
因此,有人写了一个全面的字符转换器,我可以将其包含在我的网站中......我将其包含在内。
一个问题:它有一个名为“名称”的函数,与我的函数相同。
这就是所谓的碰撞。 我们在同一范围中声明了两个具有相同名称的函数。 我们想避免这种情况。
所以我们需要以某种方式限制我们的代码范围。
在 javascript 中确定代码范围的唯一方法是将其包装在一个函数中:
这可能会解决我们的问题。 现在所有内容都被封闭起来,只能从我们的左大括号和右大括号内访问。
我们有一个函数中的函数......这看起来很奇怪,但完全合法。
只有一个问题。 我们的代码不起作用。
我们的
userName
变量永远不会回显到控制台!我们可以通过在现有代码块之后
或之前添加对函数的调用来解决此问题!
第二个问题:名称“main”尚未被使用的可能性有多大? ……非常非常苗条。
我们需要更多的范围界定。 以及一些自动执行 main() 函数的方法。
现在我们来谈谈自动执行函数(或者自动执行、自动运行等等)。
语法很尴尬。 然而,它确实有效。
当您将函数定义括在括号中并包含参数列表(另一组或括号!)时,它充当函数调用。
因此,让我们再次查看我们的代码,使用一些自动执行语法:
因此,在您阅读的大多数教程中,您现在都会受到“匿名自动执行”或类似术语的轰炸。
经过多年的专业发展,我强烈强烈建议您为您编写的每个函数命名以供调试之用。
当出现问题时(而且确实会出现问题),您将在浏览器中检查回溯。 当堆栈跟踪中的条目有名称时,总是更容易缩小代码问题范围!
Simplistic. So very normal looking, its almost comforting:
However, what if I include a really handy javascript library to my page that translates advanced characters into their base level representations?
Wait... what?
I mean, if someone types in a character with some kind of accent on it, but I only want 'English' characters A-Z in my program? Well... the Spanish 'ñ' and French 'é' characters can be translated into base characters of 'n' and 'e'.
So someone nice person has written a comprehensive character converter out there that I can include in my site... I include it.
One problem: it has a function in it called 'name' same as my function.
This is what's called a collision. We've got two functions declared in the same scope with the same name. We want to avoid this.
So we need to scope our code somehow.
The only way to scope code in javascript is to wrap it in a function:
That might solve our problem. Everything is now enclosed and can only be accessed from within our opening and closing braces.
We have a function in a function... which is weird to look at, but totally legal.
Only one problem. Our code doesn't work.
Our
userName
variable is never echoed into the console!We can solve this issue by adding a call to our function after our existing code block...
Or before!
A secondary concern: What are the chances that the name 'main' hasn't been used yet? ...so very, very slim.
We need MORE scoping. And some way to automatically execute our main() function.
Now we come to auto-execution functions (or self-executing, self-running, whatever).
The syntax is awkward as sin. However, it works.
When you wrap a function definition in parentheses, and include a parameter list (another set or parentheses!) it acts as a function call.
So lets look at our code again, with some self-executing syntax:
So, in most tutorials you read, you will now be bombarded with the term 'anonymous self-executing' or something similar.
After many years of professional development, I strongly urge you to name every function you write for debugging purposes.
When something goes wrong (and it will), you will be checking the backtrace in your browser. It is always easier to narrow your code issues when the entries in the stack trace have names!
我是它的忠实粉丝 :) 因为:
极大地 - (为什么你应该说它很好?)
更多此处。
I am a great fan :) of it because:
Enormously – (Why you should say its good?)
More here.
命名空间。 JavaScript 的作用域是函数级的。
Namespacing. JavaScript's scopes are function-level.
我已阅读所有答案,这里缺少一些非常重要的东西,我会亲吻。 “立即调用函数表达式 (IIFE)”,有两个主要原因:
第一个已经解释得很好了。 对于第二个,请研究以下示例:
注意1:我们没有将函数分配给
MyClosureObject
,更进一步调用该函数的结果 >。 请注意最后一行中的()
。注意2:关于Javascript中的函数,您还需要了解的是,内部函数可以访问函数的参数和变量,它们是在函数内部定义的。
让我们尝试一些实验:
我可以使用
getMyName
获取MyName
并且它有效:以下巧妙的方法不起作用:
但我可以设置另一个名称并获得预期的结果:
编辑: 在上面的示例中,
MyClosureObject
设计为在没有new
前缀的情况下使用,因此按照惯例,不应将其大写。I've read all answers, something very important is missing here, I'll KISS. There are 2 main reasons, why I need Self-Executing Anonymous Functions, or better said "Immediately-Invoked Function Expression (IIFE)":
The first one has been explained very well. For the second one, please study following example:
Attention 1: We are not assigning a function to
MyClosureObject
, further more the result of invoking that function. Be aware of()
in the last line.Attention 2: What do you additionally have to know about functions in Javascript is that the inner functions get access to the parameters and variables of the functions, they are defined within.
Let us try some experiments:
I can get
MyName
usinggetMyName
and it works:The following ingenuous approach would not work:
But I can set an another name and get the expected result:
Edit: In the example above
MyClosureObject
is designed to be used without thenew
prefix, therefore by convention it should not be capitalized.我不敢相信所有答案都没有提到隐含的全局变量。
(function(){})()
构造不能防止隐含的全局变量,这对我来说是更大的问题,请参阅 http://yuiblog.com/blog/2006/06/01/global-domination/基本上,该功能块确保所有依赖的“您定义的“全局变量”仅限于您的程序,它不能保护您免于定义隐式全局变量。 JSHint 等可以提供有关如何防御此行为的建议。
更简洁的
var App = {}
语法提供了类似的保护级别,并且在“公共”页面上时可以包装在功能块中。 (请参阅 Ember.js 或 SproutCore< /a> 使用此构造的库的真实示例)就
private
属性而言,除非您正在创建公共框架或库,否则它们有点被高估了,但如果您需要实现它们, Douglas Crockford 有一些好主意。I can't believe none of the answers mention implied globals.
The
(function(){})()
construct does not protect against implied globals, which to me is the bigger concern, see http://yuiblog.com/blog/2006/06/01/global-domination/Basically the function block makes sure all the dependent "global vars" you defined are confined to your program, it does not protect you against defining implicit globals. JSHint or the like can provide recommendations on how to defend against this behavior.
The more concise
var App = {}
syntax provides a similar level of protection, and may be wrapped in the function block when on 'public' pages. (see Ember.js or SproutCore for real world examples of libraries that use this construct)As far as
private
properties go, they are kind of overrated unless you are creating a public framework or library, but if you need to implement them, Douglas Crockford has some good ideas.这是一个很好的例子,说明了自调用匿名函数如何发挥作用。
输出:
10, 10, 10, 10, 10...
输出:
0, 1, 2, 3, 4...
Here's a solid example of how a self invoking anonymous function could be useful.
Output:
10, 10, 10, 10, 10...
Output:
0, 1, 2, 3, 4...
也许是范围隔离。 这样函数声明内的变量就不会污染外部命名空间。
当然,在一半的 JS 实现中,它们无论如何都会这样做。
Scope isolation, maybe. So that the variables inside the function declaration don't pollute the outer namespace.
Of course, on half the JS implementations out there, they will anyway.
是否有一个参数并且“代码堆”返回一个函数?
关闭。
something
的值由分配给a
的函数使用。something
可以有一些不同的值(for 循环)并且每次 a 有一个新函数时。Is there a parameter and the "Bunch of code" returns a function?
Closure. The value of
something
gets used by the function assigned toa
.something
could have some varying value (for loop) and every time a has a new function.简短的答案是:防止全局(或更高)范围的污染。
IIFE(立即调用函数表达式)是将脚本编写为插件、附加组件、用户的最佳实践脚本或任何期望与其他人的脚本一起使用的脚本。 这可确保您定义的任何变量不会对其他脚本产生不良影响。
这是 IIFE 表达式的另一种编写方式。 我个人更喜欢以下方法:
https://developer .mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
从上面的例子可以很清楚地看出 IIFE 也会影响效率和性能,因为预期运行的函数只有一次会被执行一次,然后永远被扔进虚空。 这意味着函数或方法声明不会保留在内存中。
Short answer is : to prevent pollution of the Global (or higher) scope.
IIFE (Immediately Invoked Function Expressions) is the best practice for writing scripts as plug-ins, add-ons, user scripts or whatever scripts are expected to work with other people's scripts. This ensures that any variable you define does not give undesired effects on other scripts.
This is the other way to write IIFE expression. I personally prefer this following method:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
From the example above it is very clear that IIFE can also affect efficiency and performance, because the function that is expected to be run only once will be executed once and then dumped into the void for good. This means that function or method declaration does not remain in memory.
一个区别是您在函数中声明的变量是局部变量,因此当您退出函数时它们就会消失,并且它们不会与其他或相同代码中的其他变量冲突。
One difference is that the variables that you declare in the function are local, so they go away when you exit the function and they don't conflict with other variables in other or same code.
首先,您必须访问 MDN IIFE ,现在关于此的一些要点
First you must visit MDN IIFE , Now some points about this
自执行函数用于管理变量的范围。
变量的作用域是定义它的程序区域。
全局变量具有全局作用域; 它在 JavaScript 代码中的任何位置定义,并且可以从脚本中的任何位置访问,甚至可以在函数中访问。 另一方面,在函数内声明的变量仅在函数体内定义。
它们是局部变量,具有局部作用域,并且只能在该函数内访问。 函数参数也算作局部变量,并且仅在函数体内定义。
如下所示,您可以访问函数内部的全局变量,还要注意,在函数体内,局部变量优先于同名的全局变量。
因此,基本上,自执行函数允许编写代码,而无需关心变量在其他 JavaScript 代码块中的命名方式。
Self executing function are used to manage the scope of a Variable.
The scope of a variable is the region of your program in which it is defined.
A global variable has global scope; it is defined everywhere in your JavaScript code and can be accessed from anywhere within the script, even in your functions. On the other hand, variables declared within a function are defined only within the body of the function.
They are local variables, have local scope and can only be accessed within that function. Function parameters also count as local variables and are defined only within the body of the function.
As shown below, you can access the global variables variable inside your function and also note that within the body of a function, a local variable takes precedence over a global variable with the same name.
So basically a self executing function allows code to be written without concern of how variables are named in other blocks of javascript code.
您可以使用此函数返回值:
You can use this function to return values :
由于 Javascript 中的函数是一等对象,通过这种方式定义它,它可以有效地定义一个“类”,就像 C++ 或 C# 一样。
该函数可以定义局部变量,并在其中包含函数。 内部函数(实际上是实例方法)将有权访问局部变量(实际上是实例变量),但它们将与脚本的其余部分隔离。
Since functions in Javascript are first-class object, by defining it that way, it effectively defines a "class" much like C++ or C#.
That function can define local variables, and have functions within it. The internal functions (effectively instance methods) will have access to the local variables (effectively instance variables), but they will be isolated from the rest of the script.
javascript中的自调用函数:
自调用表达式会自动调用(启动),无需被调用。 自调用表达式在创建后立即被调用。 这主要用于避免命名冲突以及实现封装。 在此函数之外无法访问变量或声明的对象。 为了避免最小化(filename.min)的问题,始终使用自执行函数。
Self invoked function in javascript:
A self-invoking expression is invoked (started) automatically, without being called. A self-invoking expression is invoked right after its created. This is basically used for avoiding naming conflict as well as for achieving encapsulation. The variables or declared objects are not accessible outside this function. For avoiding the problems of minimization(filename.min) always use self executed function.
实际上,上面的函数将被视为没有名称的函数表达式。
用左括号和右括号包裹函数的主要目的是避免污染全局空间。
函数表达式内的变量和函数变为私有(即,它们在函数外部不可用)。
Actually, the above function will be treated as function expression without a name.
The main purpose of wrapping a function with close and open parenthesis is to avoid polluting the global space.
The variables and functions inside the function expression became private (i.e) they will not be available outside of the function.
考虑到你的简单问题:“在 javascript 中,你什么时候想使用这个:...”
我喜欢 @ken_browning 和 @sean_holding 的答案,但这是我没有看到提到的另一个用例:
其中 Node.insert 是一些异步动作。
我不能在函数声明中没有 async 关键字的情况下调用 wait,并且我不需要命名函数供以后使用,但需要等待插入调用,或者我需要一些其他更丰富的功能(谁知道?) 。
Given your simple question: "In javascript, when would you want to use this:..."
I like @ken_browning and @sean_holding's answers, but here's another use-case that I don't see mentioned:
where Node.insert is some asynchronous action.
I can't just call await without the async keyword at the declaration of my function, and i don't need a named function for later use, but need to await that insert call or i need some other richer features (who knows?).
使用此方法是为了关闭。 请阅读此链接,了解有关闭包的更多信息。
Use of this methodology is for closures. Read this link for more about closures.
看起来这个问题已经得到了回答,但无论如何我都会发布我的意见。
我知道什么时候我喜欢使用自执行函数。
该函数允许我使用一些额外的代码来定义 childObjects 的属性和属性,以实现更清晰的代码,例如设置常用的变量或执行数学方程; 哦! 或错误检查。 与仅限于嵌套对象实例化语法相反......
编码通常有很多晦涩的方法来做很多相同的事情,让你想知道,“为什么要麻烦呢?” 但新的情况不断出现,你不能再仅仅依赖基本/核心原则。
It looks like this question has been answered all ready, but I'll post my input anyway.
I know when I like to use self-executing functions.
The function allows me to use some extra code to define the childObjects attributes and properties for cleaner code, such as setting commonly used variables or executing mathematic equations; Oh! or error checking. as opposed to being limited to nested object instantiation syntax of...
Coding in general has a lot of obscure ways of doing a lot of the same things, making you wonder, "Why bother?" But new situations keep popping up where you can no longer rely on basic/core principals alone.
有3件事。
例如,顶级初始化,小部件初始化可以通过自调用的烦人函数来包装来运行。 例如,
There are 3 things.
Top level initialisation for exmaple, widget initialisation can be wrapped by self invoking annoymous function to run. For example,
IIRC 它允许您创建私有属性和方法。
IIRC it allows you to create private properties and methods.