js变量提升与函数提升的详细过程
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新......
- github:https://github.com/Daotin/Web
- 微信公众号:Web前端之巅
- 博客园:http://www.cnblogs.com/lvonve/
在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!

js变量提升与函数提升的详细过程
先来看两个栗子,下面的两段代码分别输出什么?
// 代码段1
function foo() {
var a = 1;
function a() {}
console.log(a);
}
foo();
// 代码段2
function foo() {
var a;
function a() {}
console.log(a);
}
foo();
答案是:代码段1打印的是1,代码段2打印的是 a() 函数。
为什么会这样呢?这就涉及到js中的变量提升和函数提升的具体过程了。
1、变量的提升
js是怎么创建变量的呢?
如下面的代码:
var a = 1;
var b = 2;
js在解析上面的代码的时候,其实会按照下面的方式进行解析的:
var a;
var b;
a = 1;
b = 2;
所以 js 并不是在我们定义一个变量的时候,声明完成之后立即赋值,而是把所有用到的变量全部声明之后,再到变量的定义的地方进行赋值,变量的声明的过程就是变量的提升。
所以我们看下下面的栗子:
function foo() {
var a = 1;
console.log(a);
console.log(b);
var b = 2;
}
foo();
上面的代码在js的眼中是这样解析的:
function foo() {
var a;
var b;
a = 1;
console.log(a); // 1
console.log(b); // undefined
b = 2;
}
foo();
所以输出的 a 的值为1, b的值为 undefined。
变量在声明提升的时候,是全部提升到作用域的最前面,一个接着一个的。但是在变量赋值的时候就不是一个接着一个赋值了,而是赋值的位置在变量原本定义的位置。原本js定义变量的地方,在js运行到这里的时候,才会进行赋值操作,而没有运行到的变量,不会进行赋值操作。
所以变量的提升,提升的其实是变量的声明,而不是变量的赋值。
2、函数的提升
函数的提升和变量的提升类似,都是提升到作用域的最开始的位置,只不过变量的提升是分两步的,第一步是变量声明的提升,第二步是变量的赋值。而函数的提升是直接将整个函数整体提升到作用域的最开始位置,相当于剪切过去的样子。
3、变量提升和函数提升的顺序
在作用域中,不管是变量还是函数,都会提升到作用域最开始的位置,不同的是,函数的提升后的位置是在变量提升后的位置之后的。
举个栗子:
下面的代码输出什么?
function foo() {
console.log(a);
var a = 1;
console.log(a);
function a() {}
console.log(a);
}
foo();
上面的代码在js眼中是这样解析的:
function foo() {
var a;
function a() {}
console.log(a); // a()
a = 1;
console.log(a); // 1
console.log(a); // 1
}
foo();
所以从上面的栗子可以看到,变量的提升是在函数提升之前的,但是变量赋值的部分是在js原型到变量定义的位置才给变量赋值的,而函数提升是相当于直接剪切到最前面的。
我们再看一个更加复杂一点的栗子:
function foo() {
console.log(a);
var a = 1;
console.log(a);
function a() {}
console.log(a);
console.log(b);
var b = 2;
console.log(b);
function b() {}
console.log(b);
}
foo();
js是这样解析的:
function foo() {
var a;
var b;
function a() {}
function b() {}
console.log(a); // a()
a = 1;
console.log(a); // 1
console.log(a); // 1
console.log(b); // b()
b = 2;
console.log(b); // 2
console.log(b);// 2
}
foo();
最后,注意:只有声明的变量和函数才会进行提升,隐式全局变量不会提升。
下面的栗子中,b不会进行变量提升。
function foo() {
console.log(a);
console.log(b); // 报错
b = 'aaa';
var a = 'bbb';
console.log(a);
console.log(b);
}
foo();
4、参考链接
js变量提升与函数提升的机制: https://segmentfault.com/a/1190000008568071

js变量提升与函数提升的详细过程的更多相关文章
- js中的变量提升和函数提升
从上周开始,我所在的学习小组正式开始了angular的学习,angular是全面支持es6的,所以语法上和以前的angular有了很大的不同,比如变量声明时就抛弃了var,而选择了let和const: ...
- 浅谈JS变量声明和函数声明提升
先来两个问题 很多时候,在直觉上,我们都会认为JS代码在执行时都是自上而下一行一行执行的,但是实际上,有一种情况会导致这个假设是错误的. a = 2; var a; console.log(a); 按 ...
- JS 变量提升与函数提升
JS 变量提升与函数提升 JS变量提升 变量提升是指:使用var声明变量时,JS会将变量提升到所处作用域的顶部.举个简单的例子: 示例1 console.log(foo); // undefined ...
- JS逻辑题 技术点: 1). 变量提升 2). 函数提升 3). 预处理 4). 调用顺序
考查的技术点: 1). 变量提升 2). 函数提升 3). 预处理 4). 调用顺序 var c = 1; function c(c) { console.log(c); var c = 3; ...
- JS——变量提升和函数提升
一.引入 在了解这个知识点之前,我们先来看看下面的代码,控制台都会输出什么 var foo = 1; function bar() { if (!foo) { var foo = 10; } aler ...
- js中变量提升和函数提升
变量提升和函数提升的总结 我们在学习JavaScript时,会遇到变量提升和函数提升的问题,为了理清这个问题,现做总结如下,希望对初学者能有所帮助 我们都知道 var 声明的变量有变量提升,而 let ...
- JavaScript系列文章:变量提升和函数提升
第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...
- JavaScript:变量提升和函数提升
第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...
- 谈谈javascript中的变量提升还有函数提升
在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...
随机推荐
- spring深入学习(一)-----IOC容器
spring对于java程序员来说,重要性不可言喻,可以想象下如果没有他,我们要多做多少工作,下面一个系列来介绍下spring(5.x版本). spring模块 IOC概念 spring中最重要的两个 ...
- abaqus的umat在vs中debug调试
配置参考:https://www.jishulink.com/content/post/333909 常见错误:http://blog.sina.com.cn/s/blog_6116bc050100e ...
- 使用java开发spark的wordcount程序(多种实现)
package spark; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; impo ...
- 回头来学习wpf的FlowDocument
学习了一段时间的electron,其实是一个神奇的开发方式,让人神往.但其打印和ocx或是activeX方面还是让我不大放心去使用.毕竟当前首要任务还是window的应用开发. 于是重新学习wpf的F ...
- Centos7配置hadoop伪分布式
修改hostname(可选) 通过下面命令查看hostname信息 hostnamectl 通过下面命令修改hostname hostnamectl set-hostname gy01 如图所示 下面 ...
- 扁平化promise调用链(译)
这是对Flattened Promise Chains的翻译,水平有限请见谅^ ^. Promises对于解决复杂异步请求与响应问题堪称伟大.AngularJS提供了$q和$http来实现它:还有很多 ...
- 初识大数据(二. Hadoop是什么)
hadoop是一个由Apache基金会所发布的用于大规模集群上的分布式系统并行编程基础框架.目前已经是大数据领域最流行的开发架构.并且已经从HDFS.MapReduce.Hbase三大核心组件成长为一 ...
- Spring-AspectJ 配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- Debian 9.x "stretch" 安装 vnStat 统计服务器流量
vnStat 是一款开源的 Linux 下统计网卡流量的软件,可以很方便地查看当前.当天.当月的流量统计报告,下面我们介绍下在 Debian 9.x 下安装 vnstat 的简单方法 首先,使用 ip ...
- Jupyter-NoteBook-你应该知道的N个小技巧
智能决策上手系列教程索引 不断更新部分内容来自于翻译整理 多行输出 在Notebook的中开头cell中添加以下代码可以实现多行输出: from IPython.core.interactiveshe ...