(译文)12个简单(但强大)的JavaScript技巧(二)

(译文)12个简单(但强大)的javaScript技巧(二)

原文链接: 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 NameshowName("Rich");//RichshowName();//NoName
  • 记住, 当你不用var关键词创建变量的时候, JavaScript会自动判断该变量为全局变量. 在上面的例子中是没有必要使用var关键词的(因为你之后可能会调用它).
  • 我们可以马上或者在这之后使用这个函数
  • 但是我们不可以在之后调用匿名函数. 因为除非你创建匿名函数之后马上调用, 在这之后没有其他办法可以引用它. 这是匿名函数只可以马上调用它的原因.


  • 当把匿名函数包含在一对括号里面时(字面量), 整个字面量会被运算,并且返回匿名函数的返回值. 它的返回值实质上是整个匿名函数自身, 所以我们只需要在这之后加上一对括号来马上调用它.
  • 因此, 后面的一对括号等于告诉JavaScript编译器马上调用这个匿名函数, 所以它才会被称之为"立即调用函数表达式".
  • 因为JavaScript基于函数块的作用域规则, 在匿名函数内声明变量都是局部变量, 所以这些局部变量没办法直接从外部获取.
  • 就像其他函数一样, 你可以向匿名函数设定参数和传递变量. 你可以根据这个特性, 利用匿名函数的作用域扩展它外围函数的作用域(即闭包).

什么时候应该使用它?

  1. 避免污染全局作用域

    IIFE最广泛的用途是避免污染全局作用域. 已经有很多JavaScript库和JavaScript高手正在使用这种技巧, 尤其是在最流行jQuery插件的开发者中. 你也应该把这个技巧应用在你的程序的主要文件中(main.js).

    在这个例子中, 我使用了匿名函数把所有全局作用域的变量变成了局部变量, 所以现在全局作用域中还可以定义新的变量, 不用顾忌是否会和匿名函数内的变量在变量名上发生冲突(还包括其他库或者框架):

    //所有的代码包含在立即调用函数中(function() {  var firstName = "Richard";  funtion init() {doStuff(firstName);//在这里开始插入应用程序的代码...  }  function doStuff() {    //...  }  function doMoreStuff() {    //...  }  //启动应用程序;  init();})();
  2. 用作条件选择器

    这种使用方式还没有被广泛所知, 但它是相当强大的. 你可以不调用一个命名函数来处理复杂的运算的. 注意在三目运算符(.. ? .. : .. )中的两个匿名函数, 我尽可能多地加入空白来使语句看起来更容易理解:

    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 rainbowcreateDoc(); //untitled_4