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 ...
随机推荐
- 从pdf 文件中抽取特定的页面
前段时间买了一个kindle 电子书阅读器.我想用它来读的pdf文档.当然最主要是用来读python标准库&mysql的官方文档. 问题就来了.这两个都是大头书.之前用mac看还好.用kind ...
- Linux 硬链接和软链接
硬链接:ln 源文件 新建名 指向同一个文件,并独立存在.当源文件删除不会影响硬链接文件的读取.不能跨文件系统和目录建连接. 例:新建一个文件吧!名字test 硬链接为t1. 查看文件,发现2个文件最 ...
- verilog gtkwave
gtkwave,开源波形显示软件 来自 bluesky1 博客.http://blog.sina.com.cn/s/blog_566ca6330100c0t3.html~type=v5_one& ...
- jQuery 插件分享-非常优秀的tab插件tabulous- 学徒帮
干货jquery插件分享之tab. tab 选项卡切换,在日常开发中也是一种比较常见的呈现控件,今天这个tab控件效果还是蛮喜欢的,推荐给大家有用到的场景可以试试: tabulous.js A jQu ...
- vue中config/index.js:配置的详细理解
当我们需要和后台分离部署的时候,必须配置config/index.js: 用vue-cli 自动构建的目录里面 (环境变量及其基本变量的配置) var path = require('path') ...
- WebService或HTTP服务端接收请求转发消息到另一个服务端-实现思路
1.需求结构(WebService) A客户端<->B服务端<->C服务端 说明: a.在B服务端上面添加配置项(1.是否转发消息到C服务端:2.C服务端IP和端口): b.A ...
- [转]第2台Tomcat端口变更失败解决办法
原文链接:http://blog.csdn.net/preterhuman_peak/article/details/41803361 今天在服务器上部署了两个Tomcat.于是将其中一个的serve ...
- repcached与mysql缓存測试
使用gem安装mysql引擎 gem install mysql(假设安装失败.请查找一些依赖组建是否安装,比如mysql-devel) 编写ruby脚本,先获取mysql数据,之后从memcache ...
- 115个Java面试题和答案(上)
转自:http://www.importnew.com/10980.html 本文我们将要讨论Java面试中的各种不同类型的面试题,它们可以让雇主测试应聘者的Java和通用的面向对象编程的能力.下面的 ...
- gsoap 学习 1-由wsdl文件生成h头文件
开始前先看一下用户向导吧 http://www.cs.fsu.edu/~engelen/soap.html 中左侧点击Documentation 英语水平确实有限,有些内容可能说的不准确,敬请参考向导 ...