浅谈JavaScript 声明提升


Posted in Javascript onSeptember 14, 2020

1 引例及基本原理

在学习JavaScript声明提升之前,我们先看下面这个例子:

console.log(a);
var a=2;

运行结果会是什么?你可能会有以下的猜测:

1.报错ReferenceError: a is not defined;

2.打印2;

3.打印undefined。

正确的结果是第三种,打印undefined。

下面让我们来看看具体的原因。其实,对于var a=2;这条语句,JavaScript会将其视为两个声明:

  1. 定义声明var a,会在编译阶段进行;
  2. 赋值声明a=2,会留在原地等待执行阶段进行。

而所谓的声明提升:就是JavaScript会把var变量声明和函数声明都会被提升到各自作用域的顶部,而赋值操作并不会被提升。
因此,上面的例子实际是按照这样的流程来处理:

var a;
console.log(a);
a=2;

我们还需要知道,不仅仅是var变量声明会提升,函数声明同样也会提升,现在来看下面这个例子

foo();
function foo(){
 console.log(a);
 var a=2;
}

这个例子的运行结果为:打印undefined。这段代码实际上会被理解为为下面的形式:

function foo(){
 var a;
 console.log(a);
 a=2;
}
foo();

2 关于声明提升的常见问题

2.1 函数表达式

先看一个函数表达式的例子:

console.log(foo);
var foo=function(){}

上面代码的运行结果为:打印undefined。实际上,变量标识符foo被提升了,但它的赋值操作并没有被提升,我们可以理解为下面的形式:

var foo;
console.log(foo);
foo=function(){}

结论:函数声明会被提升,但函数表达式不会被提升。

2.2 声明的优先级

如果在同一个作用域内,存在同名的函数声明和var变量声明,那么会发生什么样的情况呢?我们同样再来看一个例子:

function a(){}
var a;
console.log(a);
var a;
function a(){}
console.log(a);

上面的两种写法,运行结果均为打印a(){}。也就是说,如果在同一个作用域内,存在同名的函数声明和var变量声明,则函数声明的优先级更高。
还有一种情况:如果同一个作用域内,存在多个同名的函数声明。这种情况下,后面声明的会覆盖前面声明的。

3 练习题

3.1 第一题

var getName = function() {
 console.log(1);
}
function getName() {
 console.log(2);
}
getName();

答案:打印1

解析:提升后的顺序如下

var getName;//与函数声明同名,故失效
function getName() {
 console.log(2);
}
getName = function() {//赋值
 console.log(1);
};
getName();

3.2 第二题

var a = 1;
function b(){
 a = 10;
 return;
 function a(){
  console.log(a);
 } 
}
b();
console.log(a);

答案:打印1

解析:首先,我们需要梳理清楚声明的提升。
本题有几个关键点,我们需要明白:

函数b内的a函数虽然在return之后,但它并没有失效,它会发生声明提升,从而提升到b函数作用域的顶部。

很多童鞋(比如我TAT)可能会错误地认为这题的答案是10,认为我们在最后调用了b函数,修改了全局变量a。实际上,由于函数a发生了声明提升,导致在函数b内“遮蔽”了全局作用域中的变量a,因此,a=10;其实是将函数a重新赋值。为了进一步测验,大家可以把a函数注释掉,会发现此时的答案就变成了10。

注:本题还涉及到了闭包的相关知识,这一题详细的解析请见参考资料[2],讲得非常详细。

var a;//全局变量a发生了声明提升
function b(){
 function a(){//函数a发生声明提升
   console.log(a);
  }
 a = 10;//因为函数a离它最近,因此赋值给函数a
 return; 
}
a = 1;//赋值给了全局变量a
b();
console.log(a);

4 参考资料

[1] 《你不知道的JavaScript》

[2] js中变量名与函数名重名的问题,Charles_Tian

[3] 函数声明与变量声明的提升机制优先级问题,一个菜鸟的奋斗史

以上就是浅谈JavaScript 声明提升的详细内容,更多关于JavaScript 声明提升的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
33个优秀的jQuery 教程分享(幻灯片、动画菜单)
Jul 08 Javascript
Javascript 鼠标移动上去小三角形滑块缓慢跟随效果
Apr 26 Javascript
在页面上用action传递参数到后台出现乱码的解决方法
Dec 31 Javascript
Bootstrap实现提示框和弹出框效果
Jan 11 Javascript
bootstrap 模态框(modal)实现水平垂直居中显示
Jan 23 Javascript
详谈js使用in和hasOwnProperty获取对象属性的区别
Apr 25 Javascript
JS常用正则表达式总结【经典】
May 12 Javascript
bootstrap table方法之expandRow-collapseRow展开或关闭当前行数据
Aug 09 Javascript
关于laydate.js加载laydate.css路径错误问题解决
Dec 27 Javascript
详解Angular调试技巧之报错404(not found)
Jan 31 Javascript
Vue监听页面刷新和关闭功能
Jun 20 Javascript
layui 动态设置checbox 选中状态的例子
Sep 02 Javascript
详解vue 中 scoped 样式作用域的规则
Sep 14 #Javascript
详解JavaScript 高阶函数
Sep 14 #Javascript
vue实现简单计算商品价格
Sep 14 #Javascript
Vue中添加滚动事件设置的方法详解
Sep 14 #Javascript
JavaScript位置参数实现原理及过程解析
Sep 14 #Javascript
swiper自定义分页器的样式
Sep 14 #Javascript
js+canvas实现转盘效果(两个版本)
Sep 13 #Javascript
You might like
Windows下PHP5和Apache的安装与配置
2006/09/05 PHP
PHP使用CURL实现多线程抓取网页
2015/04/30 PHP
php post json参数的传递和接收处理方法
2018/05/31 PHP
php支付宝APP支付功能
2020/07/29 PHP
PDO::getAvailableDrivers讲解
2019/01/28 PHP
javascript Array.sort() 跨浏览器下需要考虑的问题
2009/12/07 Javascript
jquery中输入验证中一个不错的效果
2010/08/21 Javascript
Javascript WebSocket使用实例介绍(简明入门教程)
2014/04/16 Javascript
jQuery实现浮动层随浏览器滚动条滚动的方法
2015/09/22 Javascript
javascript实现任务栏消息提示的简单实例
2016/05/31 Javascript
js实现数组去重方法及效率?Ρ? target=
2017/02/14 Javascript
vue.js中指令Directives详解
2017/03/20 Javascript
vue js秒转天数小时分钟秒的实例代码
2018/08/08 Javascript
bootstrap里bootstrap动态加载下拉框的实例讲解
2018/08/10 Javascript
vue 配置多页面应用的示例代码
2018/10/22 Javascript
微信小程序发送短信验证码完整实例
2019/01/07 Javascript
在Webpack中用url-loader处理图片和字体的问题
2020/04/28 Javascript
[04:09]2014DOTA2国际邀请赛Ti西雅图 历届冠军相继出局 BBC综述今日比赛
2014/07/20 DOTA
Python聚类算法之DBSACN实例分析
2015/11/20 Python
对python requests发送json格式数据的实例详解
2018/12/19 Python
keras的backend 设置 tensorflow,theano操作
2020/06/30 Python
Python爬虫开发与项目实战
2020/12/16 Python
去除python中的字符串空格的简单方法
2020/12/22 Python
全球最大的在线橄榄球商店:Lovell Rugby
2018/05/20 全球购物
Crocs欧洲官网:Crocs Europe
2020/01/14 全球购物
《回乡偶书》教学反思
2014/04/12 职场文书
学术诚信承诺书
2014/05/26 职场文书
通信工程专业求职信
2014/06/04 职场文书
大学生简短的自我评价
2014/09/12 职场文书
客服专员岗位职责
2015/02/10 职场文书
关于迟到的检讨书
2015/05/06 职场文书
反腐倡廉影片观后感
2015/06/08 职场文书
西游降魔篇观后感
2015/06/15 职场文书
golang判断key是否在map中的代码
2021/04/24 Golang
Python3.8官网文档之类的基础语法阅读
2021/09/04 Python
Win2008系统搭建DHCP服务器
2022/06/25 Servers