zoukankan      html  css  js  c++  java
  • js 匿名函数-立即调用的函数表达式

    先提个问题,

    单独写匿名函数为什么报错?return 匿名函数 为什么不报错?

    如图:

    image

    第二种情况在 f 还没有执行的时候,就报错了,,,当然这得归因于函数声明语句声明提前(发生在代码执行之前)的原因;

    先说下高程下匿名函数的定义:

    匿名函数(anonymous function),function 关键字后面没有标识符,(匿名函数有时候也叫拉姆达函数。)匿名函数的name 属性是空字符串。

    在把函数当成值来使用的情况下,都可以使用匿名函数。

    回答开头的问题:

    单独写匿名函数为什么报错?

    高程上说:因为JavaScript 将function 关键字当作一个函数声明语句的开始,而函数声明语句 function 关键字后面应该是 函数名,这里后面跟圆括号,当然会报错。

    换一种理解就是:解析器可以把它当作匿名函数表达式,也可以当做函数声明语句去解析,但是默认情况下,是当成函数声明语句去解析的,所以这个时候会报错,除非在某些位置只能当做表达式去解析,就不会有歧义报错了;

    return 匿名函数 为什么不报错?

    根据 MDN 上的解释:

    return语句终止函数的执行,并返回一个指定的值给函数调用者。

    return [[expression]]; 

    表达式的值会被返回。如果忽略,则返回 undefined。 

    The expression whose value is to be returned. If omitted, undefined is returned instead.

    所以,猜测 js 引擎把 return 后面的内容当成 表达式 去解析,在这里就是把匿名函数当成表达式去解析,自然就不会报错了。

    同样的道理,下面代码也不会报错,并且正确执行:

    image

    因为 var 声明的 = 后面跟着的应该是表达式,所以 js 引擎把后面的内容当做匿名函数表达式去解析,这样,在函数表达式之后,加上(),自然就是调用函数了,这也没什么问题。

    所以,在有歧义的地方,我们需要消除歧义,告诉解析器把 匿名函数表达式 当成 表达式 去解析,而不是采取默认的函数声明语句;

    方法: 高程说:加个括号()就可以了,如图;

    image

    这样就可以消除歧义,标注()里的是表达式,而不是语句;

    既然已经转成函数表达式了,那么在函数表达式后面加上(),

    image

    自然就是执行函数了,这就是大名鼎鼎的立即调用的函数表达式(IIFE),也称自执行函数。

    举一反三,换个格式:

    image

    逻辑上也是一样,因为外面有大括号,所以 js 引擎会把里面的内容作为表达式去解析,而不是作为语句去执行(因为函数调用也是表达式)。

    这就与 ES6 之前的模块化联系起来了,

    var module1=(function() {
        // 把涉及的变量都放在这个匿名函数内,避免了全局变量污染问题;
        var i = 0;
    
        function(x) {
            return x + 1
        }
    })();

    这个代码是不是很熟悉?如果不关心最外层的匿名函数的返回值或不怕难以阅读,也就是 module1 的值,你可以在匿名函数括号外加上一些其他符号,只要不影响内部函数的运行就行了,常见的有:

    !function () { /* code */ } ();
    ~function () { /* code */ } ();
    -function () { /* code */ } ();
    +function () { /* code */ } ();

    参考资料:

    JavaScript高级程序设计-第3版-中

    JavaScript权威指南-第6版-中

    更多:

    深入理解JavaScript系列(4):立即调用的函数表达式

  • 相关阅读:
    C++常用库
    如何学好VC和MFC(各前辈学*方法及感受整理)(五)
    如何学好VC和MFC(各前辈学习方法及感受整理)(一)
    基于Winsock API的VC网络编程实战
    const int *p和int * const p的区别(常量指针与指向常量的指针) .
    java中的“包”与C#中的“命名空间
    vc加载lib文件的方法
    C|C++中的静态全局变量,静态局部变量,全局变量,局部变量的区别
    如何学好VC和MFC(各前辈学习方法及感受整理)(三)
    如何学好VC和MFC(各前辈学习方法及感受整理)(二)
  • 原文地址:https://www.cnblogs.com/xianshenglu/p/8387006.html
Copyright © 2011-2022 走看看