总之
总结
以最简单的形式,这种技术旨在将代码包装在函数范围中。
它有助于减少发生以下情况的机会:
- 与其他应用程序/库冲突
- 污染优越(全球最有可能)范围
它不检测文档何时准备就绪 - 它不是某种document.onload 也不是window.onload
通常称为Immediately Invoked Function Expression (IIFE) 或Self Executing Anonymous Function。
代码解释
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
在上面的示例中,函数中定义的任何变量(即使用 var 声明的变量)都将是“私有的”并且只能在函数范围内访问(正如 Vivin Paliath 所说)。换句话说,这些变量在函数之外是不可见/不可访问的。 See live demo.
Javascript 具有函数作用域。 “在函数中定义的参数和变量在函数之外是不可见的,而在函数内任何地方定义的变量在函数内的任何地方都是可见的。” (来自“Javascript:好的部分”)。
更多详情
替代代码
最后,之前贴的代码也可以这样写:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
See live demo.
根源
迭代 1
有一天,有人可能认为“必须有一种方法可以避免命名 'myMainFunction',因为我们只想立即执行它。”
如果你回到基础,你会发现:
-
expression: 评估值的东西。即3+11/x
-
statement:代码行做某事但它确实不评估为一个值。即if(){}
同样,函数表达式的计算结果是一个值。一个后果(我假设?)是它们可以立即被调用:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
所以我们更复杂的例子变成了:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
See live demo.
迭代 2
下一步是思考“如果我们甚至不使用var myMainFunction =!?”。
答案很简单:尝试删除它,如下所示:
function(){ console.log('mamamia!'); }();
See live demo.
它不起作用,因为“函数声明不可调用”。
诀窍在于,通过删除var myMainFunction =,我们将函数表达式转换为函数声明。有关这方面的更多详细信息,请参阅“资源”中的链接。
下一个问题是“为什么我不能把它作为一个函数表达式,而不是var myMainFunction =?
答案是“你可以”,实际上有很多方法可以做到这一点:添加+、!、-,或者用一对括号括起来(就像现在一样按照惯例完成),我相信更多。例如:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
或
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
或
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
因此,一旦将相关修改添加到我们曾经的“替代代码”中,我们就会返回与“代码解释”示例中使用的完全相同的代码
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
阅读更多关于Expressions vs Statements:
揭秘作用域
人们可能想知道的一件事是“当您没有在函数内部‘正确地’定义变量时会发生什么——即,改为进行简单的赋值?”
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
See live demo.
基本上,如果未在其当前作用域中声明的变量被赋值,那么“查找作用域链直到找到变量或到达全局作用域(此时它将创建它)” .
在浏览器环境中(与 nodejs 等服务器环境相比),全局范围由 window 对象定义。因此我们可以做到window.myOtherFunction()。
我关于此主题的“良好做法”提示是在定义任何内容时始终使用var:无论是数字、对象还是函数,甚至在全局范围内也是如此。这使得代码更简单。
注意:
- javascript 没有有
block scope(更新:在ES6 中添加了块范围局部变量。)
- javascript 只有
function scope 和global scope(浏览器环境中的window 范围)
阅读更多关于Javascript Scopes的信息:
资源
后续步骤
一旦你得到这个IIFE 概念,它就会导致module pattern,这通常是通过利用这个IIFE 模式来完成的。玩得开心:)