先提个问题,

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

如图:

第二种情况在 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 后面的内容当成 表达式 去解析,在这里就是把匿名函数当成表达式去解析,自然就不会报错了。

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

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

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

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

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

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

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

举一反三,换个格式:

逻辑上也是一样,因为外面有大括号,所以 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):立即调用的函数表达式

js 匿名函数-立即调用的函数表达式的更多相关文章

  1. LR常用函数以及调用自定义函数

    2.LR常用函数以及调用自定义函数 2.1.LR常用函数以及对信息的判断 2.1.1. LR内部自定义函数 在LR脚本中定义变量和编写自定义函数,需将变量的声明放在脚本其他内容的上方,否则会提示[il ...

  2. python27期day09:函数的初始、函数的定义、函数的调用、函数的返回值、函数的参数、作业题。

    1.函数的作用:封装代码.大量的减少了重复的代码. 2.全局空间:顶行写的就是全局空间. 图解 : 3.函数的定义: def 是一个关键字.申明要定义一个函数 my_len 函数的名字.遵循变量命名的 ...

  3. Python基础(函数,函数的定义,函数的调用,函数的参数,递归函数)

    1.函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = ...

  4. 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计

    类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...

  5. Python---7函数(调用&定义函数)

    函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs(),只有一个参数.可以直接从Python的官方网站查看文档: http: ...

  6. JavaScript中函数引用调用和函数直接调用的区别

    首先看下面的代码: var x = 1 var f1 = function( f ) { var x = 2 ; f( ' console.log( x ) ' ) } var f2 =  funct ...

  7. java如何在函数中调用主函数的数组

    import javax.swing.JOptionPane; public class Test { /** * @zdz */ public static void main(String[] a ...

  8. 写一方法计算实现任意个整数之和.在主调函数中调用该函数,实现任意个数之和。(使用params参数)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  9. daemon_init函数:调用该函数把普通进程转变为守护进程

    #include <unistd.h> #include <syslog.h> #include <fcntl.h> #include <signal.h&g ...

随机推荐

  1. ERRORS:<class 'Salesman.admin.UsrMngUserAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.

    在使用django admin的过程中 遇到了这个错误 . Both 'fieldsets' and 'fields' are specified. django.core.management.ba ...

  2. 使用Sigar获取服务器信息

    Sigar简介 Sigar是Hyperic-hq产品的基础包,是Hyperic HQ主要的数据收集组件.它用来从许多平台收集系统和处理信息. 这些平台包括:Linux, Windows, Solari ...

  3. Atitit.js javascript异常处理机制与java异常的转换.js exception process Voae

    Atitit.js javascript异常处理机制与java异常的转换.js exception processVoae 1. 1. javascript异常处理机制 1 2. 2. Web前后台异 ...

  4. CA证书的信认

    为什么不同的品牌证书,价钱不一样: 衡量证书一般是看通用型,就是大家认不认你,或者说,你买的证书的根证书有没有被设备内置,内置了,你就是可信的, 没内置,就没法用.

  5. jquery 获取各种高宽

    获取浏览器显示区域(可视区域)的高度 :   $(window).height();   获取浏览器显示区域(可视区域)的宽度 : $(window).width();   获取页面的文档高度   $ ...

  6. 巧用set比较大小,缩短时间复杂度

    struct Node { long long a; long long b; long long c; long long num; int i; bool operator < (const ...

  7. dp之完全背包poj1787(完全背包以及路径记录 推荐)

    题意:有四种硬币,1分,5分,10分,25分,分别有a,b,c,d种,给出一个n分钱,要求你求出组成n分钱最多需要的硬币数量,并且输出组成它的各种硬币的数量...... 学到的东西:这个题目我是用两种 ...

  8. eclipse生成export生成jar详解

    使用eclipse打jar包可能还有很多人不是很了解,今天特意测试整理一番. 打jar包有3种形式 JAR file               JAR Javadoc              ja ...

  9. 最新PHPcms9.6.0 任意文件上传漏洞

    在用户注册处抓包: 然后发送到repeater POC: siteid=&modelid=&username=z1aaaac121&password=aasaewee311as ...

  10. Ubuntu 12.04下LAMP环境的搭建

    首先 apt-get install update 一下 sudo apt-get install update 安装MySQL 的服务端和客户端 sudo apt-get install mysql ...