我想知道这是什么意思:
(function () {
})();
这是在说document。onload吗?
我想知道这是什么意思:
(function () {
})();
这是在说document。onload吗?
当前回答
(function () {
})();
这被称为IIFE(立即调用函数表达式)。它是著名的JavaScript设计模式之一,是现代Module模式的核心和灵魂。顾名思义,它在创建后立即执行。此模式创建一个隔离的或私有的执行范围。
在ECMAScript 6之前的JavaScript使用词法作用域,因此IIFE用于模拟块作用域。(在ECMAScript 6中,通过引入let和const关键字,块范围是可能的。) 关于词汇范围问题的参考
用IIFE模拟块作用域
使用IIFE的性能优势是能够通过减少范围查找来将常用的全局对象(如window、document等)作为参数传递。(请记住,JavaScript在局部作用域和全局作用域的链中寻找属性)。因此,在局部作用域中访问全局对象可以减少查找时间,如下所示。
(function (globalObj) {
//Access the globalObj
})(window);
其他回答
这是一个更深入的解释,为什么你会使用这个:
“使用IIFE的主要原因是确保数据隐私。因为JavaScript的var将变量限定在包含变量的函数内,所以任何在IIFE中声明的变量都不能被外部世界访问。”
http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-expressions.html
TL;DR:表达式可以括在圆括号中,如果函数的表达式和块形式组合在一起,则会与函数调用冲突。
我喜欢反例,因为它们描绘了一幅伟大的逻辑图景,而其他人没有列出任何反例。你可能会问,“为什么浏览器不能看到function(){}(),而只是假设它是一个表达式?”让我们用三个例子来比较这个问题。
var x; //这里fibonacci是一个block函数 函数fibonacci(x) { Var值= x < 2 ?X: fibonacci(X -1) + fibonacci(X -2); if (x === 9) console.log("The " + x + "th fibonacci is: " + value); 返回值; } (x = 9); console.log(" x的值:" + x); Console.log ("fibonacci is a(n) ")+ typeof fibonacci);
当我们将函数转换为表达式时,观察事情是如何变化的。
var x; //这里fibonacci是一个函数表达式 函数fibonacci(x) { Var值= x < 2 ?X: fibonacci(X -1) + fibonacci(X -2); if (x === 9) console.log("The " + x + "th fibonacci is: " + value); 返回值; }) (x = 9); console.log(" x的值:" + x); Console.log ("fibonacci is a(n) ")+ typeof fibonacci);
当你使用not-operator而不是圆括号时,也会发生同样的事情,因为这两个操作符都将语句转换为表达式:
var x; //这里fibonacci是一个函数表达式 ! 函数fibonacci(x) { Var值= x < 2 ?X: fibonacci(X -1) + fibonacci(X -2); if (x === 9) console.log("The " + x + "th fibonacci is: " + value); 返回值; } (x = 9); console.log(" x的值:" + x); Console.log ("fibonacci is a(n) ")+ typeof fibonacci);
通过将函数转换为表达式,它由它下面的两行(x = 9)执行。由于表达式函数和块函数的行为是分开的,所以这两个例子都运行得很好,没有歧义(规范方面)。
名字的作用域
另一个重要的观察是,命名块函数对整个作用域可见,而函数表达式只对其本身可见。换句话说,fibonacci只对第一个示例中的最后一个console.log是块时可见。在这三个例子中,fibonacci对自身是可见的,允许fibonacci调用自身,这是递归。
箭头功能
逻辑的另一个方面是箭头函数。如果块函数和表达式函数的定义合并在一起,规范将不得不包括箭头函数的任意规则和例外:
函数hello() {console.log(" hello World")} (x) => console.log("hello " + x) console.log("如果你正在阅读,没有发生错误");
虽然函数块工作正常,但函数表达式后面跟着箭头函数会产生语法错误:
! 函数hello() {console.log(" hello World")} (x) => console.log("hello " + x) console.log("如果你正在阅读,没有发生错误");
这里,第二行的(x)是调用前一行的函数还是箭头函数的函数参数是不明确的。
请注意,箭头函数多年来确实符合ECMAScript标准,在语言的初始设计中并不是一个因素;我的观点是,表达式函数和块函数之间的区别有助于JavaScript语法更有逻辑性和连贯性。
这是一个自调用匿名函数。
查看W3Schools对自调用函数的解释。
函数表达式可以“自调用”。 自动调用(启动)自调用表达式,无需 被称为。 函数表达式将自动执行 后面跟着()。 不能自调用函数声明。
从这里开始:
var b = 'bee';
console.log(b); // global
把它放在一个函数中,它就不再是全局的了——这是你的主要目标。
function a() {
var b = 'bee';
console.log(b);
}
a();
console.log(b); // ReferenceError: b is not defined -- *as desired*
立即调用函数——哎呀:
function a() {
var b = 'bee';
console.log(b);
}(); // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
使用括号来避免语法错误:
(function a() {
var b = 'bee';
console.log(b);
})(); // OK now
你可以省略函数名:
(function () { // no name required
var b = 'bee';
console.log(b);
})();
不需要比这更复杂了。
以下代码:
(function () {
})();
称为立即调用函数表达式(IIFE)。
它之所以被称为函数表达式,是因为Javascript中的(yourcode)操作符将其强制转换为表达式。函数表达式和函数声明的区别如下:
// declaration:
function declaredFunction () {}
// expressions:
// storing function into variable
const expressedFunction = function () {}
// Using () operator, which transforms the function into an expression
(function () {})
表达式只是一组可以求值为单个值的代码。对于上面例子中的表达式,这个值是一个单独的函数对象。
在得到表达式后,计算结果为函数对象,然后可以立即使用()操作符调用函数对象。例如:
(函数(){ Const foo = 10;//这里的所有变量都是函数块的作用域 console.log (foo); }) (); console.log (foo);// referenceError foo的作用域是IIFE
为什么这个有用?
当我们处理大型代码库和/或导入各种库时,命名冲突的几率会增加。当我们在IIFE中编写相关(因此使用相同的变量)的代码的某些部分时,所有的变量和函数名都被限定在IIFE的函数括号内。这减少了命名冲突的可能性,让你在命名时更粗心(例如,你不必在它们前面加上前缀)。