理解 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 相关文章推荐
CSS+Jquery实现页面圆角框方法大全
Dec 24 Javascript
使用Firebug对js进行断点调试的图文方法
Apr 02 Javascript
Jquery实现侧边栏跟随滚动条固定(兼容IE6)
Apr 02 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
Jun 23 Javascript
jQuery内存泄露解决办法
Dec 13 Javascript
jquery实现input框获取焦点的方法
Feb 06 Javascript
Vue+Express实现登录状态权限验证的示例代码
May 05 Javascript
JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】
May 12 Javascript
原生js canvas实现鼠标跟随效果
Aug 02 Javascript
vue实现路由懒加载的3种方法示例
Sep 01 Javascript
js获取url页面id,也就是最后的数字文件名
Sep 25 Javascript
原生JavaScript实现刮刮乐
Sep 29 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项目打包方法
2008/02/18 PHP
PHP中用正则表达式清除字符串的空白
2011/01/17 PHP
常用的PHP数据库操作方法(MYSQL版)
2011/06/08 PHP
PHP中empty和isset对于参数结构的判断及empty()和isset()的区别
2015/11/15 PHP
PHP如何通过AJAX方式实现登录功能
2015/11/23 PHP
Laravel5.1自定义500错误页面示例
2016/10/09 PHP
PHP hebrev()函数用法讲解
2019/02/21 PHP
分享27个jQuery 表单插件集合推荐
2011/04/25 Javascript
js使用数组判断提交数据是否存在相同数据
2013/11/27 Javascript
Jquery异步提交表单代码分享
2015/03/26 Javascript
JQuery插件jcarousellite的参数中文说明
2015/05/11 Javascript
jquery实现最简单的滑动菜单效果代码
2015/09/12 Javascript
JavaScript操作HTML元素和样式的方法详解
2015/10/21 Javascript
Angular利用trackBy提升性能的方法
2018/01/26 Javascript
vue.js 实现评价五角星组件的实例代码
2018/08/13 Javascript
js中getter和setter用法实例分析
2018/08/14 Javascript
使用angularjs.foreach时return的问题解决
2018/09/30 Javascript
javascript中函数的写法实例代码详解
2018/10/28 Javascript
微信小程序带动画弹窗组件使用方法详解
2018/11/27 Javascript
微信小程序如何播放腾讯视频的实现
2019/09/20 Javascript
python装饰器的特性原理详解
2019/12/25 Python
PyTorch-GPU加速实例
2020/06/23 Python
利用PyQt5+Matplotlib 绘制静态/动态图的实现代码
2020/07/13 Python
用python读取xlsx文件
2020/12/17 Python
Python自动化测试基础必备知识点总结
2021/02/07 Python
Bluebella美国官网:英国性感内衣品牌
2018/10/04 全球购物
瑞典度假品牌:OAS
2019/05/28 全球购物
李维斯牛仔裤荷兰官方网站:Levi’s NL
2020/08/23 全球购物
会计学自我鉴定
2014/02/06 职场文书
高校教师自荐信范文
2014/03/13 职场文书
求职信怎么写范文
2014/05/26 职场文书
学校地质灾害防治方案
2014/06/10 职场文书
爱牙日宣传活动总结
2015/02/05 职场文书
2015年小学校长工作总结
2015/05/19 职场文书
2016春季幼儿园小班开学寄语
2015/12/03 职场文书
详解PHP设计模式之依赖注入模式
2021/05/25 PHP