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


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 相关文章推荐
验证用户是否修改过页面的数据的实现方法
Sep 26 Javascript
利用jquery.qrcode在页面上生成二维码且支持中文
Feb 12 Javascript
javascript实现数独解法
Mar 14 Javascript
Javascript 计算字符串在localStorage中所占字节数
Oct 21 Javascript
jQuery实现简洁的导航菜单效果
Nov 23 Javascript
jQuery通过ajax请求php遍历json数组到table中的代码(推荐)
Jun 12 Javascript
超全面的javascript中变量命名规则
Feb 09 Javascript
详解AngularJS脏检查机制及$timeout的妙用
Jun 19 Javascript
jackson解析json字符串,首字母大写会自动转为小写的方法
Dec 22 Javascript
浅谈vuepress 踩坑记
Apr 18 Javascript
JavaScript使用闭包模仿块级作用域操作示例
Jan 21 Javascript
JS常用排序方法实例代码解析
Mar 03 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 is_subclass_of函数的一个BUG和解决方法
2014/06/01 PHP
基于thinkPHP框架实现留言板的方法
2016/10/17 PHP
php显示页码分页类的封装
2017/06/08 PHP
不常用但很实用的PHP预定义变量分析
2019/06/25 PHP
jquery下操作HTML控件的实现代码
2010/01/12 Javascript
Span元素的width属性无效果原因及解决方案
2010/01/15 Javascript
基于jQuery的消息提示插件 DivAlert之旅(二)
2010/04/01 Javascript
写了10年的Javascript也未必全了解的连续赋值运算
2011/03/25 Javascript
JS 操作Array数组的方法及属性实例解析
2014/01/08 Javascript
javascript使用正则控制input输入框允许输入的值方法大全
2014/06/19 Javascript
理解jQuery stop()方法
2014/11/21 Javascript
JavaSacript中charCodeAt()方法的使用详解
2015/06/05 Javascript
基于JavaScript短信验证码如何实现
2016/01/24 Javascript
JavaScript中使用webuploader实现上传视频功能(demo)
2017/04/10 Javascript
详解Vue.js搭建路由报错 router.map is not a function
2017/06/27 Javascript
JS中Safari浏览器中的Date
2017/07/17 Javascript
详解node.js中的npm和webpack配置方法
2018/01/21 Javascript
vue中的计算属性实例详解
2018/09/19 Javascript
利用jqgrid实现上移下移单元格功能
2018/11/07 Javascript
原生js实现可兼容PC和移动端的拖动滑块功能详解【测试可用】
2019/08/15 Javascript
[00:23]DOTA2群星共贺开放测试 25日无码时代来袭
2013/09/23 DOTA
python下载文件记录黑名单的实现代码
2017/10/24 Python
pandas 取出表中一列数据所有的值并转换为array类型的方法
2018/04/11 Python
深入浅析Python2.x和3.x版本的主要区别
2018/11/30 Python
Python中的asyncio代码详解
2019/06/10 Python
详解python websocket获取实时数据的几种常见链接方式
2019/07/01 Python
python实现复制大量文件功能
2019/08/31 Python
Python定时从Mysql提取数据存入Redis的实现
2020/05/03 Python
python 删除excel表格重复行,数据预处理操作
2020/07/06 Python
python如何调用百度识图api
2020/09/29 Python
python爬虫破解字体加密案例详解
2021/03/02 Python
canvas实现圆绘制的示例代码
2019/09/11 HTML / CSS
美国优质宠物用品购买网站:Muttropolis
2020/02/17 全球购物
行政部主管岗位职责
2013/12/28 职场文书
医院科室评语
2015/01/04 职场文书
利用Python脚本写端口扫描器socket,python-nmap
2022/07/23 Python