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

时间:2023-03-09 09:59:29
(译文)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 Name showName("Rich"); //Rich
    showName(); //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 rainbow
    createDoc(); //untitled_4