浅谈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 相关文章推荐
javascript 处理HTML元素必须避免使用的一种方法
Jul 30 Javascript
jQuery EasyUI 中文API Button使用实例
Apr 14 Javascript
Javascript动态绑定事件的简单实现代码
Dec 25 Javascript
jquery中使用ajax获取远程页面信息
Nov 13 Javascript
javascript写的简单的计算器,内容很多,方法实用,推荐
Dec 29 Javascript
Extjs优化(一)删除冗余代码提高运行速度
Apr 15 Javascript
AngularJS中关于ng-class指令的几种实现方式详解
Sep 17 Javascript
angularjs定时任务的设置与清除示例
Jun 02 Javascript
纯JS实现只能输入数字的简单代码
Jun 21 Javascript
详解tween.js 中文使用指南
Jan 05 Javascript
Vue.js 图标选择组件实践详解
Dec 03 Javascript
js实现炫酷光感效果
Sep 05 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
PHP+javascript液晶时钟
2006/10/09 PHP
php中使用exec,system等函数调用系统命令的方法(不建议使用,可导致安全问题)
2012/09/07 PHP
php生成酷炫的四个字符验证码
2016/04/22 PHP
预加载css或javascript的js代码
2010/04/23 Javascript
AJAX 网页保留浏览器前进后退等功能
2011/02/12 Javascript
javascript的函数、创建对象、封装、属性和方法、继承
2011/03/10 Javascript
读jQuery之七 判断点击了鼠标哪个键的代码
2011/06/21 Javascript
js 实现浏览历史记录示例
2014/04/20 Javascript
JS 打印功能代码可实现打印预览、打印设置等
2014/10/31 Javascript
javascript正则表达式使用replace()替换手机号的方法
2015/01/19 Javascript
JavaScript操作cookie类实例
2015/03/31 Javascript
基于javascript编写简单日历
2016/05/02 Javascript
JS工作中的小贴士之”闭包“与事件委托的”阻止冒泡“
2016/06/16 Javascript
浅谈js控制li标签排序问题 js调用php函数的方法
2016/10/16 Javascript
Vue2几种常见开局方式详解
2017/09/09 Javascript
浅谈webpack4 图片处理汇总
2018/09/12 Javascript
vue2.0 如何在hash模式下实现微信分享
2019/01/22 Javascript
Element的el-tree控件后台数据结构的生成以及方法的抽取
2020/03/05 Javascript
微信小程序自定义支持图片的弹窗
2020/12/21 Javascript
[01:48:04]DOTA2-DPC中国联赛 正赛 PSG.LGD vs Elephant BO3 第一场 2月7日
2021/03/11 DOTA
Windows和Linux下使用Python访问SqlServer的方法介绍
2015/03/10 Python
一个基于flask的web应用诞生(1)
2017/04/11 Python
分享一下如何编写高效且优雅的 Python 代码
2017/09/07 Python
python如何定义带参数的装饰器
2018/03/20 Python
详解python异步编程之asyncio(百万并发)
2018/07/07 Python
python 函数中的内置函数及用法详解
2019/07/02 Python
Python替换月份为英文缩写的实现方法
2019/07/15 Python
python flask中动态URL规则详解
2019/11/22 Python
Django DRF认证组件流程实现原理详解
2020/08/17 Python
法律七进实施方案
2014/03/15 职场文书
2015年置业顾问工作总结
2015/04/07 职场文书
安全第一课观后感
2015/06/18 职场文书
公司团队口号霸气押韵
2015/12/24 职场文书
周一早安温馨问候祝福语!
2019/07/15 职场文书
python中requests库+xpath+lxml简单使用
2021/04/29 Python
在Spring-Boot中如何使用@Value注解注入集合类
2021/08/02 Java/Android