全面了解函数声明与函数表达式、变量提升


Posted in Javascript onAugust 09, 2016

函数的声明方式

在定义一个函数的时候通常有两种声明方式:

foo(){};   // 函数声明
var foo = function(){};  // 函数表达式

不同之处

1、函数表达式后面加括号可以直接执行
2、函数声明会提前预解析

预解析

让我们先看一个例子:

foo();     // 函数声明
foo_later();   // foo_later is not a function

function foo(){ console.log('函数声明'); }
var foo_later = function(){ console.log('函数表达式'); }

可以看到,函数声明foo被预解析了,它可以在其自身代码之前执行;而函数表达式foo_later则不能。要解决这个问题,我们先要弄清楚JavaScript解析器的工作机制。

变量提升(hoist)

JavaScript解析器会在自身作用域内将变量和函数声明提前(hoist),也就是说,上面的例子其实被解析器理解解析成了以下形式:

function foo(){ console.log('函数声明'); }  // 函数声明全部被提前
var foo_later;   // 函数表达式(变量声明)仅将变量提前,赋值操作没有被提前

foo();       
foo_later();   


foo_later = function(){ console.log('函数表达式'); }

这样也就可以解释,为什么在函数表达式之前调用函数,会返回错误了,因为它还没有被赋值,只是一个未定义变量,当然无法被执行。

同样的,我们也可以试着猜测下面这段代码的输出结果:

console.log(declaredLater);  

var declaredLater = "Now it's defined!";

console.log(declaredLater);

该段代码可以被解析成一下形式:

 

var declaredLater;     

console.log(declaredLater);  // undefined

declaredLater = "Now it's defined!";

console.log(declaredLater);  // Now it's defined!

 变量声明被提到最前(所以不会报出变量不存在的错误),但赋值没有被提前,所以第一次的输出结果是undefined。

需要注意的是

由于函数声明会被预解析,所以不要使用此种方法来声明不同函数。尝试猜想下面例子的输出结果:

if(true){
 function aaa(){
  alert('1');
 } 
}
else{
 function aaa(){
  alert('2');
 }
}

aaa();

与我们预想的不同,该段代码弹出的是“2”.这是因为两个函数声明在if语句被执行之前就被预解析了,所以if语句根本没有用,调用aaa()的时候直接执行了下面的函数。

总结

通过上面的讲解可以总结如下:

•变量的声明被提前到作用域顶部,赋值保留在原地

•函数声明整个“被提前”

•函数作为值赋给变量时只有变量“被提前”了,函数没有“被提前”

通过练习上面的实例自己多感受一下。另外,作为最佳实践:变量声明一定要放在作用域/函数的最上方(JavaScript 只有函数作用域!)。

以上这篇全面了解函数声明与函数表达式、变量提升就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
解决 FireFox 下[使用event很麻烦] 的问题.
Aug 22 Javascript
让低版本浏览器支持input的placeholder属性(js方法)
Apr 03 Javascript
jquery ui对话框实例代码
May 10 Javascript
js获取GridView中行数据的两种方法 分享
Jul 13 Javascript
获取非最后一列td值并将title设为该值的方法
Oct 30 Javascript
jquery使用animate方法实现控制元素移动
Mar 27 Javascript
学习JavaScript设计模式之代理模式
Jan 12 Javascript
javascript稀疏数组(sparse array)和密集数组用法分析
Dec 28 Javascript
React Native开发封装Toast与加载Loading组件示例
Sep 08 Javascript
JavaScript实现移动端带transition动画的轮播效果
Mar 24 Javascript
vue中移动端调取本地的复制的文本方式
Jul 18 Javascript
JavaScript中reduce()的用法
May 11 Javascript
jQuery 生成svg矢量二维码
Aug 09 #Javascript
浅谈JavaScript中变量和函数声明的提升
Aug 09 #Javascript
浅谈js基本数据类型和typeof
Aug 09 #Javascript
js中判断变量类型函数typeof的用法总结
Aug 09 #Javascript
详解js实现线段交点的三种算法
Aug 09 #Javascript
完美解决jQuery符号$与其他javascript 库、框架冲突的问题
Aug 09 #Javascript
jQuery对checkbox 复选框的全选全不选反选的操作
Aug 09 #Javascript
You might like
PHP中读取照片exif信息的方法
2014/08/20 PHP
Laravel 5 学习笔记
2015/03/06 PHP
新手常遇到的一些jquery问题整理
2010/08/16 Javascript
纯文字版返回顶端的js代码
2013/08/01 Javascript
javaScript使用EL表达式的几种方式
2014/05/27 Javascript
nodejs开发环境配置与使用
2014/11/17 NodeJs
jQuery实现网页抖动的菜单抖动效果
2015/08/07 Javascript
使用Vue.js创建一个时间跟踪的单页应用
2016/11/28 Javascript
jQuery实现别踩白块儿网页版小游戏
2017/01/18 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
Angular中$state.go页面跳转并传递参数的方法
2017/05/09 Javascript
Require.JS中的几种define定义方式示例
2017/06/01 Javascript
vue动画打包后失效问题的解决方法
2018/09/18 Javascript
详解vue更改头像功能实现
2019/04/28 Javascript
Vue+Element ui 根据后台返回数据设置动态表头操作
2020/09/21 Javascript
Vue获取微博授权URL代码实例
2020/11/04 Javascript
[00:08]DOTA2勇士令状等级奖励“天外飞星”
2019/05/24 DOTA
python中使用xlrd、xlwt操作excel表格详解
2015/01/29 Python
python实现简单的socket server实例
2015/04/29 Python
Phantomjs抓取渲染JS后的网页(Python代码)
2016/05/13 Python
Django中使用极验Geetest滑动验证码过程解析
2019/07/31 Python
Jupyter Notebook 文件默认目录的查看以及更改步骤
2020/04/14 Python
python和node.js生成当前时间戳的示例
2020/09/29 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
日本7net购物网:书籍、漫画、杂志、DVD、游戏邮购
2017/02/17 全球购物
小班秋游活动方案
2014/02/22 职场文书
信用社主任竞聘演讲稿
2014/05/23 职场文书
大学生工作求职信
2014/06/23 职场文书
安徽导游词
2015/02/12 职场文书
西安事变观后感
2015/06/12 职场文书
培训学校2015年度工作总结
2015/07/20 职场文书
教育教学工作反思
2016/02/24 职场文书
关于JavaScript回调函数的深入理解
2021/06/27 Javascript
缓存替换策略及应用(以Redis、InnoDB为例)
2021/07/25 Redis
C#连接ORACLE出现乱码问题的解决方法
2021/10/05 Oracle
十大最强水系宝可梦,最美宝可梦排第三,榜首大家最熟悉
2022/03/18 日漫