理解 javascript 中的函数表达式与函数声明


Posted in Javascript onJuly 07, 2017

常用闭包的同学肯定很清楚下面一段代码:

//通常的闭包写法
(function () {
 ...
}())

那么我们的问题来了,为什么要在 function () {...}() 之外用圆括号包裹呢?解答这个问题,就需要我们理解 Javascript 中函数表达式与函数声明的概念。

函数定义带来的错误

虽然 function () {...} 看上去像是一个函数声明,但是由于没有函数名,它的本质其实是一个函数表达式。我们看下规范中对于函数声明与函数表达式的定义:

理解 javascript 中的函数表达式与函数声明

可以看出来,函数声明是必须带有函数名的。所以在直接执行 function () {...}() 时候会报语法错误,原因就是函数表达式被尝试解析为函数声明时没有找到函数名。

理解 javascript 中的函数表达式与函数声明

那么我们继续尝试写上函数名的情况:

function fn () {...}()

理解 javascript 中的函数表达式与函数声明

仍然会提示语法错误,不过这次的出错的位置在后面 () 中的 ) 上。

先不解释为什么,看接下来的示例:

理解 javascript 中的函数表达式与函数声明

从这个结果可以看出,函数声明之后的 () 会被解析为分组运算符,而不是函数调用。那么如何才能使函数执行呢?

如何正确解析函数表达式

根据规范,函数表达式必须在 Expression 中才能进行正确的语法解析。恰巧 () 在作为分组运算符时,里面的内容会被认为是 Expression。

(function () {...}())
(function () {...})()

上述两种写法都是正确的。第一种写法比较清晰,函数表达式被正确解析并调用。第二种写法中,解析器首先处理 (function () {...}) 部分,由于分组运算符不会对其中内容进行 GetValue 操作,所以在语句结束时,其中的函数表达式被直接返回,之后的 () 则表示函数调用。

我们来简单的用一个例子表示一下:

var a = function () {...}
(a()) //形同 (function () {...}())
(a)() //形同 (function () {...})()

这个例子稍有不恰当,因为直接执行 a() 是可行的,而直接执行 function () {...}() 则不行,原因就是上面提到的,function () {...} 被尝试解析为函数声明而引发了语法错误。

其他方式

上面我们提到通过 () 分组运算符,可以将匿名函数正确的理解为函数表达式。同理,我们也可以通过许多其他的运算符将函数表达式正确执行。

!function () {}()
void function () {}()
+function () {}()
-function () {}()
if (function () {}()) {} 
...

由于很多操作符会改变函数返回值,比如 !function () {return 0}void function () {}()+ function () {}() 等,所以我们一般使用 () 将匿名函数包裹使其被正确解析为函数表达式。

参考文章

http://www.zhihu.com/question/40902815/answer/88787368

http://www.zhihu.com/question/20292224

Javascript 相关文章推荐
枚举JavaScript对象的函数
Dec 22 Javascript
jquery $.ajax()取xml数据的小问题解决方法
Nov 20 Javascript
JQUERY设置IFRAME的SRC值的代码
Nov 30 Javascript
dreamweaver 安装Jquery智能提示
Apr 02 Javascript
浅谈jQuery的offset()方法及示例分享
Jul 17 Javascript
jquery+ajax请求且带返回值的代码
Aug 12 Javascript
js中遍历Map对象的简单实例
Aug 08 Javascript
bootstrap中使用google prettify让代码高亮的方法
Oct 21 Javascript
浅谈ECMAScript6新特性之let、const
Aug 02 Javascript
解析vue中的$mount
Dec 21 Javascript
详解axios中封装使用、拦截特定请求、判断所有请求加载完毕)
Apr 09 Javascript
JavaScript的一些小技巧分享
Jan 06 Javascript
彻底解决 webpack 打包文件体积过大问题
Jul 07 #Javascript
JS仿QQ好友列表展开、收缩功能(第一篇)
Jul 07 #Javascript
JS仿QQ好友列表展开、收缩功能(第二篇)
Jul 07 #Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
Jul 07 #Javascript
详解vue.js+UEditor集成 [前后端分离项目]
Jul 07 #Javascript
JS实现搜索关键词的智能提示功能
Jul 07 #Javascript
vue.js国际化 vue-i18n插件的使用详解
Jul 07 #Javascript
You might like
PHP.MVC的模板标签系统(二)
2006/09/05 PHP
PHP Token(令牌)设计
2008/03/15 PHP
php时间不正确的解决方法
2008/04/09 PHP
详解PHP执行定时任务的实现思路
2015/12/21 PHP
CodeIgniter视图使用注意事项
2016/01/20 PHP
Smarty模板变量调节器用法分析
2016/05/23 PHP
php版交通银行网银支付接口开发入门教程
2016/09/26 PHP
php实现生成code128条形码的方法详解
2017/07/19 PHP
Thinkphp 框架基础之源码获取、环境要求与目录结构分析
2020/04/27 PHP
ext 列表页面关于多行查询的办法
2010/03/25 Javascript
各浏览器对click方法的支持差异小结
2011/07/31 Javascript
JS完成代码前最好对其做5件事
2013/04/07 Javascript
javascript获取隐藏元素(display:none)的高度和宽度的方法
2014/06/06 Javascript
初步使用Node连接Mysql数据库
2016/03/03 Javascript
全面总结Javascript对数组对象的各种操作
2017/01/22 Javascript
js常用DOM方法详解
2017/02/04 Javascript
vue使用iframe嵌入网页的示例代码
2020/06/09 Javascript
JavaScript使用小插件实现倒计时的方法讲解
2019/03/11 Javascript
使用React-Router实现前端路由鉴权的示例代码
2020/07/26 Javascript
AI人工智能 Python实现人机对话
2017/11/13 Python
python中kmeans聚类实现代码
2018/02/23 Python
python实现zabbix发送短信脚本
2018/09/17 Python
python ddt数据驱动最简实例代码
2019/02/22 Python
python实现扫描ip地址的小程序
2019/04/16 Python
Python文件操作方法详解
2020/02/09 Python
Python pandas如何向excel添加数据
2020/05/22 Python
python 如何区分return和yield
2020/09/22 Python
IE浏览器单独写CSS样式的几种方法
2014/10/14 HTML / CSS
初级会计求职信范文
2014/02/15 职场文书
春季运动会广播稿大全
2014/02/19 职场文书
事业单位考察材料范文
2014/12/25 职场文书
导游词欢迎词
2015/02/02 职场文书
广告公司文案策划岗位职责
2015/04/14 职场文书
2015年社区平安建设工作总结
2015/05/13 职场文书
法制工作总结2015
2015/07/23 职场文书
pandas DataFrame.shift()函数的具体使用
2021/05/24 Python