zoukankan      html  css  js  c++  java
  • IIFE(立即执行函数表达式)

    我们经常会看到这样的写法:

    ;(fuction () {
        // do something
    })()
    

    这就是一个简单的IIFE(立即执行函数表达式,immediately-invoked function expression)了。

    这样的写法有什么好处呢?来简单分析一下。

    1. 开头的分号

    我们都知道,js是可以加分号或者不加分号的,在某些情况下,不加分号会让解析器解析出错,举个例子:

    var 
        a = 0
        , b = 0
    ;
    a = b + 3
    (b = a)
    // Uncaught TypeError: 3 is not a function
    

    解析代码的时候,a = b + 3和(b = a)这两条语句之间没有明确的分界,回车和空格会自动被忽略。解析器会认为这是一句。所以,此时会认为3是一个函数,b=a是他的参数。
    在知乎的这个问题下,尤大做了解释。

    真正会导致上下行解析出问题的 token 有 5 个:括号,方括号,正则开头的斜杠,加号,减号。我还从没见过实际代码中用正则、加号、减号作为行首的情况,所以总结下来就是一句话:一行开头是括号或者方括号的时候加上分号就可以了,其他时候全部不需要。其实即使是这两种情况,在实际代码中也颇为少见。

    ok,回到我们的例子,我们的例子就是以括号开头的,如果上一个语句没有加分号,很可能会出现这样问题,这个分号就是为了防止这样的情况发生,称之为防御性分号。

    2. function(){}

    函数有两种声明方式:

    function foo () {}
    var foo = function () {}
    

    这两种声明方式的不同之处在于,使用var声明的函数不会自动提升到顶部。也就是说,不能在var声明函数的语句之前调用函数,否则会抛出undefined的错误。
    function () {}这种形式被称为匿名函数。匿名函数没有名字,也就是没有指针,是无法在其他地方调用的。
    将匿名函数赋值给foo,则可以通过foo来调用。
    当然还有办法调用它,就是例子中的两对括号。第一对括号将匿名函数包装成了一个表达式,而第二对括号意思就是立即执行它。

    function () {console.log('a')} // 报错 Uncaught SyntaxError: Unexpected token (
    (function () {console.log('a')}) // 返回函数定义 ƒ () {console.log('a')},没有log
    (function () {console.log('a')})() // a
    function foo() {console.log('a')}() // 报错 Uncaught SyntaxError: Unexpected token )
    

    第一行,因为不是合法的声明方式,希望找到函数名的地方是‘(’,所以抛出了该异常。
    第二行,()中的语句被当成了表达式,解析器会认为是var声明的方式。
    第三行,自执行。
    第四行,function foo() {console.log('a')}是正确的函数声明方式,被正确解析。接下来的一对括号依次解析,括号里需要有表达式,但是没有,所以会抛出这样的异常。

    3. 好处

    IIFE的好处就是不会污染全局变量,就在当前的函数体的作用域下进行操作,保证了父作用域的干净,如果return出一些函数,那这些函数就形成了闭包。
    我们常用IIFE来写module。

    var counter = (function(){
      var i = 0;
    
      return {
        get: function(){
          return i;
        },
        set: function( val ){
          i = val;
        },
        increment: function() {
          return ++i;
        }
      };
    })()
    

    Refer:

    1. 维基百科:立即调用函数表达式
    2. 知乎:JavaScript 语句后应该加分号么?
  • 相关阅读:
    DateTimePicker控件在WinXP下的BUG
    SmartAssembly .net混淆后,无法找到部分类型
    RPC_E_SERVERFAULT excel com操作错误
    System.Reflection.ReflectionTypeLoadException
    login SMTP send mail error : Unable to read data from the transport connection: net_io_connectionclosed
    静态类无法实现接口
    Combobox出现System.Data.DataRowView的原因
    .net 4.0 : Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.Binder.****'
    EOS 主节点同步
    使用tcpdump抓取EOS帐户创建与交易数据
  • 原文地址:https://www.cnblogs.com/liuyongjia/p/7896923.html
Copyright © 2011-2022 走看看