浅析函数声明和函数表达式——函数声明的声明提前


Posted in Javascript onMay 03, 2016

前两天班级聚会,除了吃喝玩乐就是睡觉扯淡,甚是喜悦,真是独乐乐不如众乐乐啊。

PS:毕业的或即将毕业的有时间能聚就聚吧,毕了业以后属于自己的时间能聚到一块儿可就少太多了。

现在有点时间来看点东西总结些东西了,又因为前段时间片片断断地看了看JavaScript的函数部分,所以抽时间总结下函数的相关部分,当然,里面有些部分都是自己的理解,如果有理解的不对的地方还请小伙伴们不吝指出。

这一节我结合自己的理解和小伙伴们聊一下函数声明的声明提前。

注:有的地方也叫函数声明提升。翻译的不一样,意思一样,大家理解就行。理解万岁!

在聊函数声明的声明提前之前,有必要介绍下函数定义的几种方法,大部分小伙伴们应该都不陌生。了解的或者不想了解的就痛快地一滚轮滚下去吧,不熟悉的或者想再熟悉一下的就放慢脚步起步走。

定义函数的方法

定义函数的方法主要有三种:

1.函数声明(Function Declaration)
2.函数表达式Function Expression)
3.new Function构造函数
其中,经常使用的是函数声明和函数表达式的函数定义方法,这两种方法有着很微妙的区别和联系,而且这两种方法的使用也容易混淆,所以这篇文章主要总结下这两种函数定义方法的相关知识点,当然本文的主题依然是关于函数提前的。

函数声明的典型格式:

function functionName(arg1, arg2, ...){
  <!-- function body -->
}

函数表达式

•函数表达式的典型格式:

var variable=function(arg1, arg2, ...){
      <!-- function body -->
}

包含名称(括弧,函数名)的函数表达式:

var variable=function functionName(arg1, arg2, ...){
    <!-- function body -->
}

像上面的带有名称的函数表达式可以用来递归:

var variable=function functionName(x){
    if(x<=1)
      return 1;
    else
      return x*functionName(x);
}

声明提前

var声明提前

小伙伴们应该都听说过声明提前的说法,我想在此再次重申一遍,因为声明提前是函数声明和函数表达式的一个重要区别,对于我们进一步理解这两种函数定义方法有着重要的意义。

但是再说函数声明提前之前呢,有必要说一下var声明提前。

先给出var声明提前的结论:

变量在声明它们的脚本或函数中都是有定义的,变量声明语句会被提前到脚本或函数的顶部。但是,变量初始化的操作还是在原来var语句的位置执行,在声明语句之前变量的值是undefined。

上面的结论中可以总结出三个简单的点:

1.变量声明会提前到函数的顶部;
2.只是声明被提前,初始化不提前,初始化还在原来初始化的位置进行初始化;
3.在声明之前变量的值是undefined。

还是来例子实在:

var handsome='handsome';
function handsomeToUgly(){
  alert(handsome);
  var handsome='ugly';
  alert(handsome);
}
handsomeToUgly();

正确的输出结果是:
先输出undefined,然后输出ugly。

错误的输出结果是:
先输出handsome,然后输出ugly。

这里正是变量声明提前起到的作用。该handsome局部变量在整个函数体内都是有定义的,在函数体内的handsome变量压住了,哦不对,是覆盖住了同名的handsome全局变量,因为变量声明提前,即var handsome被提前至函数的顶部,就是这个样子:

var handsome='handsome';
function handsomeToUgly(){
  var handsome;
  alert(handsome);
  var handsome='ugly';
  alert(handsome);
}
handsomeToUgly();

所以说在alert(handsome)之前,已经有了var handsome声明,由上面提到的

在声明之前变量的值是undefined
所以第一个输出undefined。

又因为上面提到的:

只是声明被提前,初始化不提前,初始化还在原来初始化的位置进行初始化
所以第二个输出ugly。

函数声明提前
接下俩我们结合var声明提前开始聊函数声明的声明提前。

函数声明的声明提前小伙伴们应该很熟悉,举个再熟悉不过的例子。

sayTruth();<!-- 函数声明 -->
function sayTruth(){
  alert('myvin is handsome.');
}

sayTruth();<!-- 函数表达式 -->
var sayTruth=function(){
  alert('myvin is handsome.');
}

小伙伴们都知道,对于函数声明的函数定义方法,即上面的第一种函数调用方法是正确的,可以输出myvin is handsome.的真理,因为函数调用语句可以放在函数声明之后。而对于函数表达式的函数定义方法,即上面的第二种函数调用的方法是不能输出myvin is handsome.的正确结果的。

结合上面的myvin is handsome.例子,函数声明提前的结论似乎很好理解,不就是在使用函数声明的函数定义方法的时候,函数调用可以放在任意位置嘛。对啊,你说的很对啊,小伙伴,我都不知道怎么反驳你了。那就容我再扯几句。

从小伙伴所说的

不就是在使用函数声明的函数定义方法的时候,函数调用可以放在任意位置嘛
可以引出一点:

函数声明提前的时候,函数声明和函数体均提前了。

而且:

函数声明是在预执行期执行的,就是说函数声明是在浏览器准备执行代码的时候执行的。因为函数声明在预执行期被执行,所以到了执行期,函数声明就不再执行(人家都执行过了自然就不再执行了)。

上面是一点。

函数表达式为什么不能声明提前
我们再说一点:为什么函数表达式不能像函数声明那样进行函数声明提前呢?

辛亏我知道一点儿,否则真不知道我该怎么回答呢?

咳咳,按照我的理解给小伙伴们解释一下下:

我们上面说了var的声明提前,注意我上面提过的:

只是声明被提前,初始化不提前,初始化还在原来初始化的位置进行初始化

Ok,我们把函数表达式摆在这看看:

var variable=function(arg1, arg2, ...){
          <!-- function body -->
}

函数表达式就是把函数定义的方式写成表达式的方式(貌似是白说,但是这对于解释和理解为毛函数表达式不能函数声明提前具有良好的疗效),就是把一个函数对象赋值给一个变量,所以我们把函数表达式写成这个样子:

var varible=5看到这,也许小伙伴们会明白了,一个是把一个值赋值给一个变量,一个是把函数对象赋值给一个变量,所以对于函数表达式,变量赋值是不会提前的,即function(arg1, arg2, ...){<!-- function body -->}是不会提前的,所以函数定义并没有被执行,所以函数表达式不能像函数声明那样进行函数声明提前。

函数声明提前的实例分析

还是那句话,还是例子来的实在:

sayTruth();
if(1){
  function sayTruth(){alert('myvin is handsome')};
}
else{
  function sayTruth(){alert('myvin is ugly')};
}

在浏览器不抛出错误的情况下(请自行测试相应的浏览器是否有抛出错误的情况,为啥我不测试?我能说我懒么。。。),浏览器的输出结果是输出myvin is ugly(我不愿承认,但是事实就是这样啊啊啊啊,难道道出了人丑就该多读书??????)。

为什么呢?当然是声明提前了。因为函数声明提前,所以函数声明会在代码执行前进行解析,执行顺序是这样的,先解析function sayTruth(){alert('myvin is handsome')},在解析function sayTruth(){alert('myvin is ugly')},覆盖了前面的函数声明,当我们调用sayTruth()函数的时候,也就是到了代码执行期间,声明会被忽略,所以自然会输出myvin is ugly(好残酷的现实。。。)。忘了的可以看上面说过的:

函数声明是在预执行期执行的,就是说函数声明是在浏览器准备执行代码的时候执行的。因为函数声明在预执行期被执行,所以到了执行期,函数声明就不再执行了(人家都执行过了自然就不再执行了)。

小了个结

关于函数声明的函数提前(提升)就聊到这里先,希望我的理解和扯淡能够对有需要的小伙伴有所帮助。

当然,实践出真知。对事物的了解、认知和运用还是在于多看多用多总结,记得有句名言,是讲声明和实践的:“动起来,为新的声明喝彩。”。

以上这篇浅析函数声明和函数表达式——函数声明的声明提前就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js身份证验证超强脚本
Oct 26 Javascript
File, FileReader 和 Ajax 文件上传实例分析(php)
Apr 27 Javascript
学习javascript面向对象 理解javascript原型和原型链
Jan 04 Javascript
基于JQuery实现图片上传预览与删除操作
May 24 Javascript
Angular-Ui-Router+ocLazyLoad动态加载脚本示例
Mar 02 Javascript
jQuery插件zTree实现删除树子节点的方法示例
Mar 08 Javascript
vue.js实现条件渲染的实例代码
Jun 22 Javascript
JS和jQuery通过this获取html标签中的属性值(实例代码)
Sep 11 jQuery
JavaScript学习总结(一) ECMAScript、BOM、DOM(核心、浏览器对象模型与文档对象模型)
Jan 07 Javascript
使用Angular CLI快速创建Angular项目的一些基本概念和写法小结
Apr 22 Javascript
微信小程序 弹窗输入组件的实现解析
Aug 12 Javascript
JS获取当前时间的年月日时分秒及时间的格式化的方法
Dec 18 Javascript
详解JavaScript异步编程中jQuery的promise对象的作用
May 03 #Javascript
jQuery的promise与deferred对象在异步回调中的作用
May 03 #Javascript
JavaScript的MVVM库Vue.js入门学习笔记
May 03 #Javascript
聊一聊JavaScript作用域和作用域链
May 03 #Javascript
小白谈谈对JS原型链的理解
May 03 #Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
May 03 #Javascript
JQuery的Pager分页器实现代码
May 03 #Javascript
You might like
什么是调频(FM)、调幅(AM)、短波(SW)、长波(LW)
2021/03/01 无线电
php面向对象 字段的声明与使用
2012/06/14 PHP
php cURL和Rolling cURL并发方式比较
2013/10/30 PHP
PHP5.3安装Zend Guard Loader图文教程
2014/09/29 PHP
yii去掉必填项中星号的方法
2015/12/28 PHP
php数据库操作model类(使用__call方法)
2016/11/16 PHP
Yii Framework框架使用PHPExcel组件的方法示例
2019/07/24 PHP
php生成HTML文件的类方法
2019/10/11 PHP
jquery与google map api结合使用 控件,监听器
2010/03/04 Javascript
jQuery.extend()、jQuery.fn.extend()扩展方法示例详解
2014/05/08 Javascript
用jquery修复在iframe下的页面锚点失效问题
2014/08/22 Javascript
node.js中的fs.symlinkSync方法使用说明
2014/12/15 Javascript
学习javascript的闭包,原型,和匿名函数之旅
2015/10/18 Javascript
基于JavaScript实现div层跟随滚动条滑动
2016/01/12 Javascript
JavaScript开发者必备的10个Sublime Text插件
2016/02/27 Javascript
简单解析JavaScript中的__proto__属性
2016/05/10 Javascript
基于zepto.js简单实现上传图片
2016/06/21 Javascript
网络传输协议(http协议)
2016/11/18 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
2017/03/09 Javascript
手机端转换rem适应
2017/04/01 Javascript
基于vue-video-player自定义播放器的方法
2018/03/21 Javascript
深入Node TCP模块的理解
2019/03/13 Javascript
详解小程序如何动态绑定点击的执行方法
2019/11/26 Javascript
浅谈vue-props的default写不写有什么区别
2020/08/09 Javascript
vue-cli脚手架的.babelrc文件用法说明
2020/09/11 Javascript
利用Python中的pandas库对cdn日志进行分析详解
2017/03/07 Python
django foreignkey外键使用的例子 相当于left join
2019/08/06 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
如何在python开发工具PyCharm中搭建QtPy环境(教程详解)
2020/02/04 Python
工商企业管理应届生求职信
2013/11/03 职场文书
煤矿机修工岗位职责
2014/02/07 职场文书
国际贸易专业自荐信
2014/06/10 职场文书
高中生自我评价范文2015
2015/03/03 职场文书
简单的辞职信范文(2016最新版)
2015/05/12 职场文书
2016年教师学习廉政准则心得体会
2016/01/20 职场文书
合同补充协议书
2016/03/24 职场文书