大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新......

在这里我会从 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变量提升与函数提升的详细过程的更多相关文章

  1. js中的变量提升和函数提升

    从上周开始,我所在的学习小组正式开始了angular的学习,angular是全面支持es6的,所以语法上和以前的angular有了很大的不同,比如变量声明时就抛弃了var,而选择了let和const: ...

  2. 浅谈JS变量声明和函数声明提升

    先来两个问题 很多时候,在直觉上,我们都会认为JS代码在执行时都是自上而下一行一行执行的,但是实际上,有一种情况会导致这个假设是错误的. a = 2; var a; console.log(a); 按 ...

  3. JS 变量提升与函数提升

    JS 变量提升与函数提升 JS变量提升 变量提升是指:使用var声明变量时,JS会将变量提升到所处作用域的顶部.举个简单的例子: 示例1 console.log(foo); // undefined ...

  4. JS逻辑题 技术点: 1). 变量提升 2). 函数提升 3). 预处理 4). 调用顺序

    考查的技术点:  1). 变量提升 2). 函数提升  3). 预处理  4). 调用顺序 var c = 1; function c(c) { console.log(c); var c = 3; ...

  5. JS——变量提升和函数提升

    一.引入 在了解这个知识点之前,我们先来看看下面的代码,控制台都会输出什么 var foo = 1; function bar() { if (!foo) { var foo = 10; } aler ...

  6. js中变量提升和函数提升

    变量提升和函数提升的总结 我们在学习JavaScript时,会遇到变量提升和函数提升的问题,为了理清这个问题,现做总结如下,希望对初学者能有所帮助 我们都知道 var 声明的变量有变量提升,而 let ...

  7. JavaScript系列文章:变量提升和函数提升

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...

  8. JavaScript:变量提升和函数提升

    第一篇文章中提到了变量的提升,所以今天就来介绍一下变量提升和函数提升.这个知识点可谓是老生常谈了,不过其中有些细节方面博主很想借此机会,好好总结一下. 今天主要介绍以下几点: 1. 变量提升 2. 函 ...

  9. 谈谈javascript中的变量提升还有函数提升

    在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...

随机推荐

  1. vue2.0在android5.0白屏, es6转es5保证浏览器兼容性

    1. 安装 npm install --save-dev babel-preset-es2015 2. 安装 npm install --save-dev babel-preset-stage-3 3 ...

  2. Django模板继承和引用

    一.模板继承 1.模板继承可以在创建一个基本“骨架”后,被其它子模板继承并覆盖,通过修改基础模板可以修改子模板中的所有框架 2.在模板teacher文件夹下创建基础模板 {% block xxx}与{ ...

  3. apt-get update 问题

    W: 仓库 “cdrom://Ubuntu 16.04.1 LTS _Xenial Xerus_ - Release amd64 (20160719) xenial Release” 没有 Relea ...

  4. PyCharm 安装教程(Windows)

    python教程 http://www.runoob.com/python3/python3-basic-syntax.html PyCharm 是一款功能强大的 Python 编辑器,具有跨平台性, ...

  5. 1021. Deepest Root DFS 求最长无环路径

    第一次出现超时 ac不了的题 思路一:对于每个节点用一次dfs dfs中 记录到当前的最长路径,若大于最长,则清除set,并加入当前节点 思路二:先查找只有一个相邻节点的节点进行dfs,由于可能存在闭 ...

  6. usb 枚举流程

    Linux-USB总线驱动分析 如下图所示,以windows为例,我们插上一个没有USB设备驱动的USB,就会提示你安装驱动程序 为什么一插上就有会提示信息? 是因为windows自带了USB总线驱动 ...

  7. linux时区和时间设置

    1,修改时区 调整时区使用tzselect [root@lyn ~]# hwclock Tue Nov :: PM AST -0.198205 seconds [root@lyn ~]# tzsele ...

  8. kubernetes CSI 插件机制学习笔记

    前言 最近在极客时间订阅了kubernetes的专栏,这篇文章是想记录一下自己学习 CSI 插件机制 (container-storage-interface) 的过程,加深一下记忆. 准备工作 老师 ...

  9. C#中数组、ArrayList和List三者的区别 转

    在C#中数组,ArrayList,List都能够存储一组对象,那么这三者到底有什么样的区别呢. 数组 数组在C#中最早出现的.在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单. ...

  10. 华为SSH认证配置

    [设备型号]华为switch-S5700s ————1: [SW1] rsa/dsa local-key-pair create #创建本地密钥对 The key name will be: SW1_ ...