在 javascript 中,你什么时候想使用这个:
(function(){
//Bunch of code...
})();
在这个:
//Bunch of code...
在 javascript 中,你什么时候想使用这个:
(function(){
//Bunch of code...
})();
在这个:
//Bunch of code...
这都是关于变量作用域的。默认情况下,自执行函数中声明的变量仅可用于自执行函数内的代码。这允许编写代码而无需考虑变量在其他 JavaScript 代码块中的命名方式。
例如,正如Alexander在评论中提到的:
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
这将首先记录3
,然后在下一个错误,console.log
因为foo
未定义。
简单化。看起来很正常,几乎令人欣慰:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
但是,如果我在我的页面中包含一个非常方便的 javascript 库,将高级字符转换为它们的基本级别表示怎么办?
等等……什么?
我的意思是,如果有人输入带有某种口音的字符,但我的程序中只想要“英语”字符 AZ?嗯……西班牙语的'ñ' 和法语的'é' 字符可以被翻译成'n' 和'e' 的基本字符。
所以有人写了一个全面的字符转换器,我可以将它包含在我的网站中......我包含它。
一个问题:它有一个名为“name”的函数,与我的函数相同。
这就是所谓的碰撞。我们在同一个作用域中声明了两个同名的函数。我们想避免这种情况。
所以我们需要以某种方式限定我们的代码。
在 javascript 中限定代码范围的唯一方法是将其包装在一个函数中:
function main() {
// We are now in our own sound-proofed room and the
// character-converter library's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
那可能会解决我们的问题。现在一切都被封闭了,只能从我们的左括号和右括号中访问。
我们在一个函数中有一个函数......看起来很奇怪,但完全合法。
只有一个问题。我们的代码不起作用。我们的userName
变量永远不会回显到控制台中!
我们可以通过在我们现有的代码块之后添加对我们的函数的调用来解决这个问题......
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
或者之前!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
次要问题:尚未使用名称“main”的可能性有多大?...非常非常苗条。
我们需要更多的范围。以及一些自动执行我们的 main() 函数的方法。
现在我们来讨论自动执行功能(或自执行、自运行,等等)。
((){})();
语法像罪一样笨拙。但是,它有效。
当您将函数定义包装在括号中并包含参数列表(另一个集合或括号!)时,它充当函数调用。
因此,让我们再次查看我们的代码,使用一些自执行语法:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
因此,在您阅读的大多数教程中,您现在会被“匿名自执行”或类似术语轰炸。
经过多年的专业发展,我强烈建议您为您为调试目的编写的每个函数命名。
当出现问题(并且会)时,您将在浏览器中检查回溯。它总是更容易缩小你的代码的问题时,在堆栈跟踪中的条目有名字!
非常冗长,我希望它有所帮助!
自调用(也称为自动调用)是指函数在定义后立即执行。这是一个核心模式,是许多其他 JavaScript 开发模式的基础。
我是它的忠实粉丝 :) 因为:
非常——(你为什么要说它好?)
更多在这里。
命名空间。JavaScript 的作用域是函数级的。
我不敢相信没有一个答案提到隐含的全局变量。
该(function(){})()
构造不能防止隐含的全局变量,这对我来说是更大的问题,请参阅http://yuiblog.com/blog/2006/06/01/global-domination/
基本上,功能块确保您定义的所有相关“全局变量”仅限于您的程序,它不能保护您免于定义隐式全局变量。JSHint等可以提供有关如何防御这种行为的建议。
更简洁的var App = {}
语法提供了类似的保护级别,并且在“公共”页面上时可能会被包装在功能块中。(有关使用此构造的库的真实示例,请参阅Ember.js或SproutCore)
就private
属性而言,除非您正在创建公共框架或库,否则它们有点被高估了,但是如果您需要实现它们,Douglas Crockford有一些好主意。