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


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 相关文章推荐
javascript 日期时间函数(经典+完善+实用)
May 27 Javascript
jquery学习笔记 用jquery实现无刷新登录
Aug 08 Javascript
jquery.boxy弹出框(后隔N秒后自动隐藏/自动跳转)
Jan 15 Javascript
jQuery事件绑定.on()简要概述及应用
Feb 07 Javascript
jquery快捷动态绑定键盘事件的操作函数代码
Oct 17 Javascript
离开当前页面前使用js判断条件提示是否要离开页面
May 02 Javascript
js实现简单的选项卡效果
Feb 23 Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
May 18 Javascript
vue实现codemirror代码编辑器中的SQL代码格式化功能
Aug 27 Javascript
微信小程序实现比较功能的方法汇总(五种方法)
Mar 07 Javascript
JavaScript或jQuery 获取option value值方法解析
May 12 jQuery
JQuery插件tablesorter表格排序实现过程解析
May 28 jQuery
详解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
php实现的发送带附件邮件类实例
2014/09/22 PHP
PHP保存带BOM文件的方法
2015/02/12 PHP
php获取json数据所有的节点路径
2015/05/17 PHP
PHP实现自动识别原编码并对字符串进行编码转换的方法
2016/07/13 PHP
IOS 开发之NSDictionary转换成JSON字符串
2017/08/14 PHP
PHP超低内存遍历目录文件和读取超大文件的方法
2019/05/01 PHP
动态添加js事件实现代码
2009/03/12 Javascript
asp.net+js 实现无刷新上传解析csv文件的代码
2010/05/17 Javascript
jquery随意添加移除html的实现代码
2011/06/21 Javascript
Chosen 基于jquery的选择框插件使用方法
2012/05/30 Javascript
jquery 扑捉回车键事件代码
2014/04/24 Javascript
jQuery实现自定义下拉列表
2015/01/05 Javascript
js面向对象之静态方法和静态属性实例分析
2015/01/10 Javascript
jquery中filter方法用法实例分析
2015/02/06 Javascript
浅谈javascript中onbeforeunload与onunload事件
2015/12/10 Javascript
第三篇Bootstrap网格基础
2016/06/21 Javascript
JS简单判断字符在另一个字符串中出现次数的2种常用方法
2017/04/20 Javascript
Nodejs进阶:express+session实现简易登录身份认证
2017/04/24 NodeJs
初学node.js中实现删除用户路由
2019/05/27 Javascript
vue中注册自定义的全局js方法
2019/11/15 Javascript
Vue-cli3多页面配置详解
2020/03/22 Javascript
[53:20]2018DOTA2亚洲邀请赛 4.1 小组赛 A组加赛 VG vs OG
2018/04/03 DOTA
python实现简单聊天应用 python群聊和点对点均实现
2017/09/14 Python
Django教程笔记之中间件middleware详解
2018/08/01 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
Python+opencv+pyaudio实现带声音屏幕录制
2019/12/23 Python
解决PyCharm不在run输出运行结果而不是再Console里输出的问题
2020/09/21 Python
澳大利亚厨房和家用电器购物网站:Bing Lee
2021/01/11 全球购物
大学生毕业自我鉴定范文
2013/09/19 职场文书
八年级语文教学反思
2014/02/11 职场文书
食品工程专业求职信
2014/06/15 职场文书
化学工程专业求职信
2014/08/10 职场文书
临时租车协议范本
2014/09/23 职场文书
向雷锋同志学习倡议书
2015/04/27 职场文书
毕业生捐书活动倡议书
2015/04/27 职场文书
2015年新农村建设指导员工作总结
2015/07/24 职场文书