原文链接: 12 Simple (Yet Powerful) JavaScript Tips
其他链接: (译文)12个简单(但强大)的JavaScript技巧(一)
强大的立即调用函数表达式
(什么是立即调用函数表达式, 何时使用它)
IIFE (Immediately Invoked Function Expressions, 发音:“Iffy”)是立即调用函数表达式的缩写形式, 它的语法大概如下:
(function() {
//Do fun stuff
})()
这是一个立即调用的匿名函数, 它在JavaScript中有一些特别重要的作用.
它是如何工作的?
-
包围匿名函数的一对括号会把它变成函数表达式或者变量表达式.
-
这就相当于:
//不带括号: ? = function() {}; //带括号: (? = function() {}); //函数被一个不知名的变量引用了, 一对括号把它包围了, 把它变成了一个匿名的函数表达式
同样的, 我们甚至可以创建一个命名的立即调用函数表达式:
(showName = function(name) { console.log( name || "No Name"); })(); //No Name showName("Rich"); //Rich showName(); //NoName
-
记住, 当你不用var关键词创建变量的时候, JavaScript会自动判断该变量为全局变量. 在上面的例子中是没有必要使用var关键词的(因为你之后可能会调用它).
-
我们可以马上或者在这之后使用这个函数
-
但是我们不可以在之后调用匿名函数. 因为除非你创建匿名函数之后马上调用, 在这之后没有其他办法可以引用它. 这是匿名函数只可以马上调用它的原因.
-
当把匿名函数包含在一对括号里面时(字面量), 整个字面量会被运算,并且返回匿名函数的返回值. 它的返回值实质上是整个匿名函数自身, 所以我们只需要在这之后加上一对括号来马上调用它.
-
因此, 后面的一对括号等于告诉JavaScript编译器马上调用这个匿名函数, 所以它才会被称之为"立即调用函数表达式".
-
因为JavaScript基于函数块的作用域规则, 在匿名函数内声明变量都是局部变量, 所以这些局部变量没办法直接从外部获取.
-
就像其他函数一样, 你可以向匿名函数设定参数和传递变量. 你可以根据这个特性, 利用匿名函数的作用域扩展它外围函数的作用域(即闭包).
什么时候应该使用它?
-
避免污染全局作用域
IIFE最广泛的用途是避免污染全局作用域. 已经有很多JavaScript库和JavaScript高手正在使用这种技巧, 尤其是在最流行jQuery插件的开发者中. 你也应该把这个技巧应用在你的程序的主要文件中(main.js).
在这个例子中, 我使用了匿名函数把所有全局作用域的变量变成了局部变量, 所以现在全局作用域中还可以定义新的变量, 不用顾忌是否会和匿名函数内的变量在变量名上发生冲突(还包括其他库或者框架):
//所有的代码包含在立即调用函数中 (function() { var firstName = "Richard"; funtion init() { doStuff(firstName); //在这里开始插入应用程序的代码... } function doStuff() { //... } function doMoreStuff() { //... } //启动应用程序; init(); })();
-
用作条件选择器
这种使用方式还没有被广泛所知, 但它是相当强大的. 你可以不调用一个命名函数来处理复杂的运算的. 注意在三目运算符(..
?
..:
.. )中的两个匿名函数, 我尽可能多地加入空白来使语句看起来更容易理解:var unnamedDocs = [], namedDocs = ['a_bridge_runover', 'great_dreamers']; function createDoc(documentTitle) { var documentName = documentTitle ? (function(theName) { var newNamedDoc = theName.toLocaleLowerCase().replace('', '_'); nameDocs.push(newNamedDoc); return newNamedDoc; })(documentTitle) : (function() { var newUnnamedDoc = 'untitled_' + Number(namedDocs.length + 1); unnamedDocs.push(newUnnamedDoc); return newUnnamedDoc; })(); return documentName; } createDoc('Over The Rainbow'); //over_the rainbow createDoc(); //untitled_4