JavaScript中函数表达式和函数声明及函数声明与函数表达式的不同


Posted in Javascript onNovember 15, 2015

函数表达式和函数声明

在ECMAScript中,创建函数的最常用的两个方法是函数表达式和函数声明,两者期间的区别是有点晕,因为ECMA规范只明确了一点:函数声明必须带有标示符(Identifier)(就是大家常说的函数名称),而函数表达式则可以省略这个标示符:

函数声明:

function 函数名称 (参数:可选){ 函数体 }

函数表达式:

function 函数名称(可选)(参数:可选){ 函数体 }

所以,可以看出,如果不声明函数名称,它肯定是表达式,可如果声明了函数名称的话,如何判断是函数声明还是函数表达式呢?ECMAScript是通过上下文来区分的,如果function foo(){}是作为赋值表达式的一部分的话,那它就是一个函数表达式,如果function foo(){}被包含在一个函数体内,或者位于程序的最顶部的话,那它就是一个函数声明。

function foo(){} // 声明,因为它是程序的一部分
 var bar = function foo(){}; // 表达式,因为它是赋值表达式的一部分
 new function bar(){}; // 表达式,因为它是new表达式
 (function(){
  function bar(){} // 声明,因为它是函数体的一部分
 })();

还有一种函数表达式不太常见,就是被括号括住的(function foo(){}),他是表达式的原因是因为括号 ()是一个分组操作符,它的内部只能包含表达式,我们来看几个例子:

  function foo(){} // 函数声明
  (function foo(){}); // 函数表达式:包含在分组操作符内

命名函数表达式

提到命名函数表达式,理所当然,就是它得有名字,前面的例子var bar = function foo(){};就是一个有效的命名函数表达式,但有一点需要记住:这个名字只在新定义的函数作用域内有效,因为规范规定了标示符不能在外围的作用域内有效:

var f = function foo(){
  return typeof foo; // foo是在内部作用域内有效
 };
 // foo在外部用于是不可见的
 console.log(typeof foo); // "undefined"
 console.log(f()); // "function"
var f = function foo(){
return foo; // foo是在内部作用域内有效
};
// foo在外部用于是不可见的
console.log(typeof foo); // "undefined"
console.log( f()==f); // "function"
console.log(f.name);//foo

既然,这么要求,那命名函数表达式到底有啥用啊?为啥要取名?

正如我们开头所说:给它一个名字就是可以让调试过程更方便,因为在调试的时候,如果在调用栈中的每个项都有自己的名字来描述,那么调试过程就太爽了,感受不一样嘛。

ps:JS中函数声明与函数表达式的不同

Js中的函数声明是指下面的形式:

function functionName(){ 
}

这样的方式来声明一个函数,而函数表达式则是类似表达式那样来声明一个函数,如:

var functionName = function(){ 
}

可能很多朋友在看到这两一种写法时会产生疑惑,这两种写法差不多,在应用中貌似也都是可行的,那他们有什么差别呢?

 事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的。对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同定义其它基本类型的变量一样,只在执行到某一句时也会对其进行解析,所以在实际中,它们还是会有差异的,具体表现在,当使用函数声明的形式来定义函数时,可将调用语句写在函数声明之前,而后者,这样做的话会报错。

Javascript 相关文章推荐
javascript 写类方式之五
Jul 05 Javascript
基于jquery的给文章加入关键字链接
Oct 26 Javascript
javascript学习笔记(十) js对象 继承
Jun 19 Javascript
js 回车提交表单两种实现方法
Dec 31 Javascript
js数组中如何随机取出一个值
Jun 13 Javascript
extjs 分页使用jsp传递数据示例
Jul 29 Javascript
整理JavaScript对DOM中各种类型的元素的常用操作
May 05 Javascript
JavaScript学习笔记整理_简单实现枚举类型,扑克牌应用
Sep 19 Javascript
angular.js指令中的controller、compile与link函数的不同之处
May 10 Javascript
详解vee-validate的使用个人小结
Jun 07 Javascript
vue安装遇到的5个报错及解决方法
Jun 12 Javascript
vue深度监听(监听对象和数组的改变)与立即执行监听实例
Sep 04 Javascript
浅谈JavaScript中的对象及Promise对象的实现
Nov 15 #Javascript
javascript 中的 delete及delete运算符
Nov 15 #Javascript
详解JavaScript函数对象
Nov 15 #Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
Nov 15 #Javascript
深入浅析JavaScript中prototype和proto的关系
Nov 15 #Javascript
apply和call方法定义及apply和call方法的区别
Nov 15 #Javascript
JavaScript和HTML DOM的区别与联系及Javascript和DOM的关系
Nov 15 #Javascript
You might like
DC宇宙的第一个英雄,堪称动漫史鼻祖,如今成为美国文化的象征
2020/04/09 欧美动漫
PHP函数eval()介绍和使用示例
2014/08/20 PHP
PHP 读取大文件并显示的简单实例(推荐)
2016/08/12 PHP
PHP flush 函数使用注意事项
2016/08/26 PHP
php 类中的常量、静态属性、非静态属性的区别
2017/04/09 PHP
PHP实现的简单sha1加密功能示例
2017/08/27 PHP
javascript下对于事件、事件流、事件触发的顺序随便说说
2010/07/17 Javascript
javascript event 事件解析
2011/01/31 Javascript
用JQuery实现表格隔行变色和突出显示当前行的代码
2012/02/10 Javascript
javascript parseInt() 函数的进制转换注意细节
2013/01/08 Javascript
模拟多级复选框效果的jquery代码
2013/08/13 Javascript
深入浅析JavaScript中的scrollTop
2016/07/11 Javascript
JS常用知识点整理
2017/01/21 Javascript
详解angular中通过$location获取路径(参数)的写法
2017/03/21 Javascript
angular.js + require.js构建模块化单页面应用的方法步骤
2017/07/19 Javascript
vue-cli如何引入bootstrap工具的方法
2017/10/19 Javascript
node 使用 async 控制并发的方法
2018/05/07 Javascript
vue移动端监听滚动条高度的实现方法
2018/09/03 Javascript
微信小程序实现左滑动删除效果
2020/03/30 Javascript
jquery实现商品sku多属性选择功能(商品详情页)
2019/12/20 jQuery
合并Excel工作薄中成绩表的VBA代码,非常适合教育一线的朋友
2009/04/09 Python
Python算法的时间复杂度和空间复杂度(实例解析)
2019/11/19 Python
python实现高斯判别分析算法的例子
2019/12/09 Python
Django设置Postgresql的操作
2020/05/14 Python
如何利用python进行时间序列分析
2020/08/04 Python
python 实现音频叠加的示例
2020/10/29 Python
Canvas环形饼图与手势控制的实现代码
2019/11/08 HTML / CSS
Boden英国官网:英国知名原创时装品牌
2018/11/06 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
机电专业毕业生推荐信
2013/11/10 职场文书
入党思想汇报怎么写
2014/04/03 职场文书
英文求职信范文
2014/05/23 职场文书
毕业设计致谢语
2015/05/14 职场文书
高中运动会前导词
2015/07/20 职场文书
新郎结婚感言
2015/07/31 职场文书
Spring Boot 排除某个类加载注入IOC的操作
2021/08/02 Java/Android