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


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 相关文章推荐
JavaScript-世界上误解最深的语言分析
Aug 12 Javascript
js 单引号 传递方法
Jun 22 Javascript
javascript数组的使用
Mar 28 Javascript
Js参数值中含有单引号或双引号问题的解决方法
Nov 06 Javascript
JavaScript实现N皇后问题算法谜题解答
Dec 29 Javascript
浅谈vue中数据双向绑定的实现原理
Sep 14 Javascript
基于mpvue的小程序项目搭建的步骤
May 22 Javascript
JS在if中的强制类型转换方式
Jul 15 Javascript
vue使用el-upload上传文件及Feign服务间传递文件的方法
Mar 15 Javascript
详解基于React.js和Node.js的SSR实现方案
Mar 21 Javascript
对Layer UI 模块化的用法详解
Sep 26 Javascript
jstree中的checkbox默认选中和隐藏示例代码
Dec 29 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输出时间差函数代码
2013/01/28 PHP
PHP多例模式介绍
2013/06/24 PHP
非常实用的PHP常用函数汇总
2014/12/17 PHP
PHP网站开发中常用的8个小技巧
2015/02/13 PHP
php设计模式之职责链模式实例分析【星际争霸游戏案例】
2020/03/27 PHP
ie和firefox不兼容的解决方法集合
2009/04/28 Javascript
JavaScript 垃圾回收机制分析
2013/10/10 Javascript
在jquery中的ajax方法怎样通过JSONP进行远程调用
2014/04/04 Javascript
laytpl 精致巧妙的JavaScript模板引擎
2014/08/29 Javascript
JQuery基础语法小结
2015/02/27 Javascript
JavaScript数组迭代器实例分析
2015/06/09 Javascript
jQuery基础知识点总结(DOM操作)
2016/06/01 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
EditPlus中的正则表达式 实战(2)
2016/12/15 Javascript
概述一个页面从输入URL到页面加载完的过程
2016/12/16 Javascript
JavaScript求一个数组中重复出现次数最多的元素及其下标位置示例
2018/07/23 Javascript
小程序关于请求同步的总结
2019/05/05 Javascript
使用Promise封装小程序wx.request的实现方法
2019/11/13 Javascript
Vue使用Element实现增删改查+打包的步骤
2020/11/25 Vue.js
iview实现动态表单和自定义验证时间段重叠
2021/01/10 Javascript
[08:54]DOTA2-DPC中国联赛 正赛 Aster vs LBZS 选手采访
2021/03/11 DOTA
python笔记(1) 关于我们应不应该继续学习python
2012/10/24 Python
Python中MySQL数据迁移到MongoDB脚本的方法
2016/04/28 Python
使用Python读写及压缩和解压缩文件的示例
2016/07/08 Python
python数据结构链表之单向链表(实例讲解)
2017/07/25 Python
python matlibplot绘制多条曲线图
2021/02/19 Python
PyCharm 配置远程python解释器和在本地修改服务器代码
2019/07/23 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
django model的update时auto_now不被更新的原因及解决方式
2020/04/01 Python
python 爬虫爬取京东ps4售卖情况
2020/12/18 Python
小学假期安全广播稿
2014/09/28 职场文书
2014超市双十一活动策划方案
2014/09/29 职场文书
客户答谢会致辞
2015/07/30 职场文书
Vue项目打包、合并及压缩优化网页响应速度
2021/07/07 Vue.js
Python Matplotlib库实现画局部图
2021/11/17 Python
《模拟人生4》推出新补丁 “婚礼奇缘”DLC终于得到修复
2022/04/03 其他游戏