理解 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 相关文章推荐
一个刚完成的layout(拖动流畅,不受iframe影响)
Aug 17 Javascript
jquery 防止表单重复提交代码
Jan 21 Javascript
js去除空格的12种实用方法
Nov 08 Javascript
使用jQuery管理选择结果
Jan 20 Javascript
JavaScript类型系统之基本数据类型与包装类型
Jan 06 Javascript
老生常谈angularjs中的$state.go
Apr 24 Javascript
vue-loader教程介绍
Jun 14 Javascript
jQuery NProgress.js加载进度插件的简单使用方法
Jan 31 jQuery
10 种最常见的 Javascript 错误(频率最高)
Feb 08 Javascript
IE11下CKEditor在Bootstrap Modal中下拉问题的解决
Sep 25 Javascript
vue实现员工信息录入功能
Jun 11 Javascript
Javascript中window.name属性详解
Nov 19 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发送有附件的电子邮件-(PHPMailer使用的实例分析)
2013/04/26 PHP
解析php防止form重复提交的方法
2013/07/01 PHP
php防注入及开发安全详细解析
2013/08/09 PHP
利用yahoo汇率接口实现实时汇率转换示例 汇率转换器
2014/01/14 PHP
一个图片地址分解程序(用于PHP小偷程序)
2014/08/23 PHP
在 Laravel 项目中使用 webpack-encore的方法
2019/07/21 PHP
ASP.NET jQuery 实例17 通过使用jQuery validation插件校验ListBox
2012/02/03 Javascript
jQuery 借助插件Lavalamp实现导航条动态美化效果
2013/09/27 Javascript
JavaScript合并两个数组并去除重复项的方法
2015/06/13 Javascript
javascript框架设计之种子模块
2015/06/23 Javascript
通过隐藏iframe实现无刷新上传文件操作
2016/03/16 Javascript
AngularJS入门教程之ng-class 指令用法
2016/08/01 Javascript
详解nodejs爬虫程序解决gbk等中文编码问题
2017/04/06 NodeJs
jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)
2017/05/19 jQuery
js 公式编辑器 - 自定义匹配规则 - 带提示下拉框 - 动态获取光标像素坐标
2018/01/04 Javascript
JS的函数调用栈stack size的计算方法
2018/06/24 Javascript
Vue resource三种请求格式和万能测试地址
2018/09/26 Javascript
基于Three.js实现360度全景图片
2018/12/30 Javascript
jquery.pager.js实现分页效果
2019/07/29 jQuery
原生Vue 实现右键菜单组件功能
2019/12/16 Javascript
ES6实现图片切换特效代码
2020/01/14 Javascript
pyqt4教程之实现半透明的天气预报界面示例
2014/03/02 Python
使用Python绘制图表大全总结
2017/02/11 Python
详解python中的文件与目录操作
2017/07/11 Python
Python人脸识别初探
2017/12/21 Python
python3正则提取字符串里的中文实例
2019/01/31 Python
如何使用Python 打印各种三角形
2019/06/28 Python
馥蕾诗美国官网:Fresh美国
2019/10/09 全球购物
计算机专业推荐信范文
2013/11/20 职场文书
中学生演讲稿
2014/04/26 职场文书
单位婚育证明范本
2014/11/21 职场文书
高三毕业感言
2015/07/30 职场文书
小学一年级语文教学反思
2016/03/03 职场文书
浅谈Python列表嵌套字典转化的问题
2021/04/07 Python
手把手教你怎么用Python实现zip文件密码的破解
2021/05/27 Python
CSS浮动引起的高度塌陷问题
2022/08/05 HTML / CSS