js 匿名函数-立即调用的函数表达式
先提个问题,
单独写匿名函数为什么报错?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,
undefinedis 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系列(4):立即调用的函数表达式
js 匿名函数-立即调用的函数表达式的更多相关文章
- LR常用函数以及调用自定义函数
2.LR常用函数以及调用自定义函数 2.1.LR常用函数以及对信息的判断 2.1.1. LR内部自定义函数 在LR脚本中定义变量和编写自定义函数,需将变量的声明放在脚本其他内容的上方,否则会提示[il ...
- python27期day09:函数的初始、函数的定义、函数的调用、函数的返回值、函数的参数、作业题。
1.函数的作用:封装代码.大量的减少了重复的代码. 2.全局空间:顶行写的就是全局空间. 图解 : 3.函数的定义: def 是一个关键字.申明要定义一个函数 my_len 函数的名字.遵循变量命名的 ...
- Python基础(函数,函数的定义,函数的调用,函数的参数,递归函数)
1.函数 我们知道圆的面积计算公式为: S = πr2 当我们知道半径r的值时,就可以根据公式计算出面积.假设我们需要计算3个不同大小的圆的面积: r1 = 12.34 r2 = 9.08 r3 = ...
- 在成员函数中调用虚函数(关于多态的注意事项)------新标准c++程序设计
类的成员函数之间可以互相调用.在成员函数(静态成员函数.构造函数和析构函数除外)中调用其他虚成员函数的语句是多态的.例如: #include<iostream> using namespa ...
- Python---7函数(调用&定义函数)
函数 Python内置了很多有用的函数,我们可以直接调用. 要调用一个函数,需要知道函数的名称和参数,比如求绝对值的函数abs(),只有一个参数.可以直接从Python的官方网站查看文档: http: ...
- JavaScript中函数引用调用和函数直接调用的区别
首先看下面的代码: var x = 1 var f1 = function( f ) { var x = 2 ; f( ' console.log( x ) ' ) } var f2 = funct ...
- java如何在函数中调用主函数的数组
import javax.swing.JOptionPane; public class Test { /** * @zdz */ public static void main(String[] a ...
- 写一方法计算实现任意个整数之和.在主调函数中调用该函数,实现任意个数之和。(使用params参数)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- daemon_init函数:调用该函数把普通进程转变为守护进程
#include <unistd.h> #include <syslog.h> #include <fcntl.h> #include <signal.h&g ...
随机推荐
- 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 ...
- 使用Sigar获取服务器信息
Sigar简介 Sigar是Hyperic-hq产品的基础包,是Hyperic HQ主要的数据收集组件.它用来从许多平台收集系统和处理信息. 这些平台包括:Linux, Windows, Solari ...
- Atitit.js javascript异常处理机制与java异常的转换.js exception process Voae
Atitit.js javascript异常处理机制与java异常的转换.js exception processVoae 1. 1. javascript异常处理机制 1 2. 2. Web前后台异 ...
- CA证书的信认
为什么不同的品牌证书,价钱不一样: 衡量证书一般是看通用型,就是大家认不认你,或者说,你买的证书的根证书有没有被设备内置,内置了,你就是可信的, 没内置,就没法用.
- jquery 获取各种高宽
获取浏览器显示区域(可视区域)的高度 : $(window).height(); 获取浏览器显示区域(可视区域)的宽度 : $(window).width(); 获取页面的文档高度 $ ...
- 巧用set比较大小,缩短时间复杂度
struct Node { long long a; long long b; long long c; long long num; int i; bool operator < (const ...
- dp之完全背包poj1787(完全背包以及路径记录 推荐)
题意:有四种硬币,1分,5分,10分,25分,分别有a,b,c,d种,给出一个n分钱,要求你求出组成n分钱最多需要的硬币数量,并且输出组成它的各种硬币的数量...... 学到的东西:这个题目我是用两种 ...
- eclipse生成export生成jar详解
使用eclipse打jar包可能还有很多人不是很了解,今天特意测试整理一番. 打jar包有3种形式 JAR file JAR Javadoc ja ...
- 最新PHPcms9.6.0 任意文件上传漏洞
在用户注册处抓包: 然后发送到repeater POC: siteid=&modelid=&username=z1aaaac121&password=aasaewee311as ...
- Ubuntu 12.04下LAMP环境的搭建
首先 apt-get install update 一下 sudo apt-get install update 安装MySQL 的服务端和客户端 sudo apt-get install mysql ...