我想知道这是什么意思:
(function () {
})();
这是否基本意味着document.onload
?
我想知道这是什么意思:
(function () {
})();
这是否基本意味着document.onload
?
(function(obj){
// Do something with this obj
})(object);
从这里开始:
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);
})();
它不需要比那更加复杂。
Uncaught SyntaxError: Unexpected token )
而不是任何关于箭头函数的提醒。你能否分享一个在箭头函数出错的情况下的 fiddle? - Script47这是一个函数表达式,它代表立即调用函数表达式(IIFE)。IIFE只是一个在创建后立即执行的函数。因此,不需要等到调用该函数时才执行,而是立即执行IIFE。让我们通过示例构造IIFE。假设我们有一个add函数,它接受两个整数作为参数并返回它们的和,
步骤1:定义函数
function add (a, b){
return a+b;
}
add(5,5);
(function add (a, b){
return a+b;
})
//add(5,5);
(function add (a, b){
return a+b;
})(5,5);
使用IFFE的主要原因是为了在函数内部保留一个私有作用域。在您的JavaScript代码中,您希望确保不会覆盖任何全局变量。有时候您可能会无意中定义一个变量来覆盖一个全局变量。例如,让我们假设我们有一个名为iffe.html的HTML文件,在标签中定义如下代码:
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
好的,上面的代码将不会出现任何问题地执行,现在假设你无意或有意声明了一个名为document的变量。
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
const document = "hi there";
console.log(document);
</script>
</body>
如果你尝试重新声明不可配置的全局属性document,你将会遇到SyntaxError语法错误。
但是,如果你希望声明一个名为documet的变量,可以使用IFFE方法实现。
<body>
<div id = 'demo'></div>
<script>
(function(){
const document = "hi there";
this.document.getElementById("demo").innerHTML = "Hello JavaScript!";
console.log(document);
})();
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
输出:
让我们通过另一个例子来尝试,假设我们有一个如下的计算器对象-
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
</script>
</body>
现在它运行得很好,但是如果我们意外地重新分配计算器对象的值呢?
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
calculator = "scientific calculator";
console.log(calculator.mul(5,5));
</script>
</body>
如果不使用IFFE,你将会遇到一个TypeError: calculator.mul 不是一个函数的错误。
但是通过使用IFFE,我们可以创建一个私有作用域,在其中创建另一个名为calculator的变量并使用它。
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
var cal = (function(){
var calculator = {
sub:function(a,b){
return a-b;
},
div:function(a,b){
return a/b;
}
}
console.log(this.calculator.mul(5,10));
console.log(calculator.sub(10,5));
return calculator;
})();
console.log(calculator.add(5,10));
console.log(cal.div(10,5));
</script>
</body>
function
的块形式结合起来,就会与函数调用冲突。我喜欢反例,因为它们能很好地展现逻辑,并且其他人都没有列出任何反例。您可能会问:"为什么浏览器不能看到 function(){}()
并假设它是一个表达式?" 让我们通过三个例子来对比一下这个问题。
var x;
// Here, fibonacci is a block function
function fibonacci(x) {
var value = x < 2 ? x : fibonacci(x-1) + fibonacci(x-2);
if (x === 9) console.log("The " + x + "th fibonacci is: " + value);
return value;
}
(x = 9);
console.log("Value of x: " + x);
console.log("fibonacci is a(n) " + typeof fibonacci);
当我们将函数转化为表达式时,观察事物如何发生变化。
var x;
// Here, fibonacci is a function expression
(function fibonacci(x) {
var value = x < 2 ? x : fibonacci(x-1) + fibonacci(x-2);
if (x === 9) console.log("The " + x + "th fibonacci is: " + value);
return value;
})
(x = 9);
console.log("Value of x: " + x);
console.log("fibonacci is a(n) " + typeof fibonacci);
var x;
// Here, fibonacci is a function expression
! function fibonacci(x) {
var value = x < 2 ? x : fibonacci(x-1) + fibonacci(x-2);
if (x === 9) console.log("The " + x + "th fibonacci is: " + value);
return value;
}
(x = 9);
console.log("Value of x: " + x);
console.log("fibonacci is a(n) " + typeof fibonacci);
fibonacci
是块时,它仅对最后一个 console.log
可见。在这三个示例中,fibonacci
对自己可见,从而允许 fibonacci
调用自身,即递归。
function hello() {console.log("Hello World")}
(x) => console.log("hello " + x)
console.log("If you are reading this, no errors occurred");
虽然函数块可以正常工作,但跟随箭头函数的函数表达式会产生语法错误:
! function hello() {console.log("Hello World")}
(x) => console.log("hello " + x)
console.log("If you are reading this, no errors occurred");
这里存在歧义,第二行的 (x)
是调用前一行函数还是箭头函数的参数。
需要注意的是,随着时间的推移,箭头函数确实被纳入了ECMAScript标准,并且不是语言初始设计的因素;我想表达的是,区分表达式函数和块函数有助于使JavaScript的语法更加合乎逻辑和连贯。
自执行函数通常用于封装上下文并避免名称冲突。在 (function(){..})() 内部定义的任何变量都不是全局变量。
代码:
var same_name = 1;
var myVar = (function() {
var same_name = 2;
console.log(same_name);
})();
console.log(same_name);
生成以下输出:
2
1
var same_name = 1; var myVar = function() { var same_name = 2; console.log(same_name); }; myVar(); console.log(same_name);
将会有相同的结果。 - domenicr自执行匿名函数。它在创建时立即执行。
一个简短的例子是:
function prepareList(el){
var list = (function(){
var l = [];
for(var i = 0; i < 9; i++){
l.push(i);
}
return l;
})();
return function (el){
for(var i = 0, l = list.length; i < l; i++){
if(list[i] == el) return list[i];
}
return null;
};
}
var search = prepareList();
search(2);
search(3);
这被称为IIFE——立即调用函数表达式。以下是一个示例,展示了它的语法和用法。它用于将变量的使用范围限制在函数内部,而不是超出函数。
最初的回答:
它被称为IIFE-立即调用函数表达式。以下是一个示例,展示了它的语法和用法。它用于仅将变量的使用范围限制在函数内部,而不是超出函数。
(function () {
function Question(q,a,c) {
this.q = q;
this.a = a;
this.c = c;
}
Question.prototype.displayQuestion = function() {
console.log(this.q);
for (var i = 0; i < this.a.length; i++) {
console.log(i+": "+this.a[i]);
}
}
Question.prototype.checkAnswer = function(ans) {
if (ans===this.c) {
console.log("correct");
} else {
console.log("incorrect");
}
}
var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0);
var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2);
var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1);
var questions = [q1, q2, q3];
var n = Math.floor(Math.random() * questions.length)
var answer = parseInt(prompt(questions[n].displayQuestion()));
questions[n].checkAnswer(answer);
})();
这里已经有很多好的答案了,但是我也想提供我的两分钱 :p
你可以使用IIFE(立即调用函数表达式)来:
避免全局命名空间污染。
在 IIFE 中定义的变量(或者任何普通函数)不会覆盖全局范围内的定义。
保护代码不被外部代码访问。
在 IIFE 中定义的所有内容只能在 IIFE 内部访问。它可以防止代码被外部代码修改。只有你明确返回作为函数结果或设置为外部变量的值才能被外部代码访问。
避免为不需要重复使用的函数命名。
尽管在 IIFE 模式中可以使用命名函数,但通常不这样做,因为没有必要重复调用它。
IIFE 通常以以下方式使用:
(function(param){
//code here
})(args);
()
,并在匿名函数之前使用void
运算符。void function(param){
//code here
}(args);
(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 () {})
(function() {
const foo = 10; // all variables inside here are scoped to the function block
console.log(foo);
})();
console.log(foo); // referenceError foo is scoped to the IIFE
当我们处理大型代码库和/或导入各种库时,命名冲突的机会增加。当我们编写与之相关的某些代码部分(因此使用相同的变量)放在IIFE内部时,所有变量和函数名称都作用于IIFE的函数括号中。这减少了命名冲突的可能性,并使您可以更轻松地对它们进行命名(例如,您不必添加前缀)。
另一个使用案例是记忆化,其中缓存对象不是全局的:
var calculate = (function() {
var cache = {};
return function(a) {
if (cache[a]) {
return cache[a];
} else {
// Calculate heavy operation
cache[a] = heavyOperation(a);
return cache[a];
}
}
})();