变量提升和函数提升的总结

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

  我们都知道 var 声明的变量有变量提升,而 let 声明的变量和 const 声明的常量没有变量提升,但是为什么 let 声明的变量就不会变量提升呢?

首先我们得理解变量和函数的创建过程:

  变量声明 ==>变量初始化 ==>变量赋值

  函数声明 ==> 初始化 ==> 赋值

而变量提升和函数提升要完成的工作为:

  变量声明 ==> 变量初识化(undefined)

  函数声明 ==> 初始化 ==> 赋值(仅仅是赋值,并没有运行函数体)

暂时性死区的概念:

  ES6规定,如果代码区块中存在 let 和 const 命令声明的变量,这个区块对这些变量从一开始就形成了封闭作用域,直到声明语句完成,这些变量才能被访问(获取或设置),否则就会报错 ReferenceError。这在语法上称为“暂时性死区”,即代码块开始到变量声明语句完成之间的区域。通过 var 声明的变量拥有变量提升,没有暂时性死区。

  因为有暂时性死区的存在,所以 let 声明的变量和 const 声明的常量才 不能 变量提升

  

  从变量创建过程来理解:

  let 声明被提升了,但是并没有做初始化工作

  const 声明被提升,也是没有做初始化工作(const只有声明和初始化过程,没有赋值过程)

    let 和 const 都没有提升所要满足的工作,所以就无法提升

  var 的声明被提升,初始化被提升

  function 的声明、初始化、和赋值都被提升

var 声明的变量提升(声明、初始化都被提升,但是赋值没有提升)

  实例  

  console.log(a)  // undefined

  var a = 'hello world'

  console.log(a)  // 'hello world'

  实际执行过程如下

  var a

  console.log(a)  // undefined

  a = 'hello world'

  console.log(a)  // 'hello world'

function 声明的函数提升(声明、初始化、赋值都提升了)

  实例  

  fn()  // 'hello world'

  function fn() { console.log('hello world') }

  fn()  // 'hello world'

  实际执行过程如下

  function fn() { console.log('hello world') }  // 注意:此时函数体并没有运行

  fn()  // 'hello world'

  fn()  // 'hello world'

既有 var 声明的变量提升,又有 function 声明的函数提升

  实例

  变量名和函数名不同名  

  console.log(a)  // undefined

  fn()

  var a = 100

  console.log(a)  // 100

  function fn() {

    console.log(a)  // undefined

    var a = 10

    console.log(a)  // 10

   }

  var a = 200

  console.log(a)  // 200

  实际执行过程如下 

  function fn() {

    console.log(a)  

    var a = 10

    console.log(a)   

   }

  var a  (全局变量)

  var a  (局部变量)

  console.log(a)  // undefined

  fn()  // undefined  10

  a = 100

  console.log(a)  // 100

  a = 200

  console.log(a)  // 200

  变量名和函数名同名 

  情况一:变量由 函数类型 变为 基本数据类型(如 Number)

  var a = 100

  console.log(a)  // 100

  a()  // 报错(TypeError:a is not a function)

  function a() {

    console.log('hello world') 

   }

  实际执行过程如下

  function a() {

    console.log('hello world') 

   }

  var a  // 用 var 重新声明了变量 a,但此时变量 a 指向的还是函数体本身,值未改变

  a = 100  //  重新给 a 赋值为 100,a 的值发生了改变,由函数类型变为了number类型

  console.log(a)  // 100

  a()  // 报错:此时 a 已经不是函数 a 了

 

  情况二:变量重新赋值,但未立即改变变量的值

  console.log(a)  // a(){ console.log('hello world')}  即 a 函数本身

  a()  // 'hello world'

  var a = 100

  var a = 200

  var a = 300

  console.log(a)  // 300

  function a() {

    console.log('hello world') 

   }

  实际执行过程如下

  function a() {

    console.log('hello world')

   }

  var a  //  此时虽然重新声明了 a 变量,但是并没有改变 a 的值,此时的 a 还是个函数

  console.log(a)  // a(){ console.log('hello world')}  即 a 函数本身

  a = 100  // 重新给 a 变量赋值 100

  a = 200  // 重新给 a 变量赋值 200

  a = 300  // 重新给 a 变量赋值 300

  console.log(a)  // 100(此时变量 a 已经由 函数类型变为 基本数据类型number,且值为 100)

  a()  // 报错:此时 a 已经不是函数 a 了

用 let 定义的变量和用 const 定义的常量 没有提升

用 let 定义的变量

  在变量定义之前使用改变量 会报错

  console.log(a)  // 报错  Cannot access 'a' before initialization

  let a = 10

  

  在变量定义之后使用改变量 才能正常运行

  let a = 10  

  console.log(a)  // 10

总结:

  1. 用 var 定义的变量有变量提升,用 function 定义的函数有函数提升

  2. 函数提升优先级高于变量提升,即优先执行函数提升

  3. let 定义的变量和 const 定义的常量不会提升

  4. 重复用 var 定义的同一个变量是合法的,如果重复的声明有初始值,那就赋值;如果没有初始值,那么它不会对变量原来保存的值不会产生影响

  5. 不能用 let 重复定义同一个变量,会造成错误

js中变量提升和函数提升的更多相关文章

  1. JS中变量名和函数名重名

    今天骚凯问了一道变量名冲突的题目,感觉很有意思,顺便也复习一下预解析的一些知识,有不对的地方忘前辈大神指正,题目是这样的: var a=100; function a(){ console.log(a ...

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

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

  3. 关于JS中变量提升的规则和原理的一点理解

        关于变量提升,以前在一些教程和书籍上都听到过,平时开发中也知道有这个规律,但是今天突然在一个公开课中听到时,第一反应时一脸懵逼,然后一百度,瞬间觉得好熟悉啊,差点被这个概念给唬住了,不信我给你 ...

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

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

  5. js变量提升与函数提升的详细过程

    大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...

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

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

  7. 关于JS中变量提升的规则和原理的一点理解(二)

    上篇文章中讲到变量提升和函数提升的先后顺序时蒙了,后来去查了一下资料,特别整理一下. 在<你不知道的JavaScript(上卷)>一书的第40页中写到:函数会首先被提升,然后才是变量. 书 ...

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

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

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

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

随机推荐

  1. 分布式系统ID的生成方法之UUID、数据库、算法、Redis、Leaf方案

    一般单机或者单数据库的项目可能规模比较小,适应的场景也比较有限,平台的访问量和业务量都较小,业务ID的生成方式比较原始但是够用,它并没有给这样的系统带来问题和瓶颈,所以这种情况下我们并没有对此给予太多 ...

  2. Centos8.3、mysql8.0主从复制实战记录

    引言 最近又上线了一个项目,感觉自己这段时间收获不少就想把自己做这个项目用的技术总结梳理一下.这个项目是我自己发起,领导们不是特别重视所以得到资源有限,资源有限的情况我只能选择手动搭建数据库环境,资源 ...

  3. 【模拟7.14】B. 熟练剖分(tree) (概率DP)

    一道概率神题,考试时没读清题考完看了学长的玄学题解看了好几个小时 首先f[i][j]表示在点 i 为根的子树中,向下最长轻链长度小于等于 j 的概率. 首先递归下去并求出子树大小,然后枚举重儿子,枚举 ...

  4. [Linux]经典面试题 - 系统管理 - 备份策略

    [Linux]经典面试题 - 系统管理 - 备份策略 目录 [Linux]经典面试题 - 系统管理 - 备份策略 一.备份目录 1.1 系统目录 1.2 服务目录 二.备份策略 2.1 完整备份 2. ...

  5. 通过RenderDoc真机抓取数据来落地验证和解决特效性能的问题

    前言 需求是来自于我在为我司的一个线上RPG游戏做特效的性能优化的过程中,需要验证对特效的一个改动是否能够提高性能,当然这个改动是在不影响美术效果的前提. 特效性能问题 技能特效 主角的一个大招(技能 ...

  6. hdu 6034 贪心模拟 好坑

    关键在排序!!! 数组间的排序会超时,所以需要把一个数组映射成一个数字,就可以了 #include <bits/stdc++.h> using namespace std; typedef ...

  7. MIT6.828 Preemptive Multitasking(上)

    Lab4 Preemptive Multitasking(上) PartA : 多处理器支持和协作多任务 在实验的这部分中,我们首先拓展jos使其运行在多处理器系统上,然后实现jos内核一些系统功能调 ...

  8. mysql中,一个数字加上null,结果为null

    在mysql中,一个数字加上null,结果为null. 这个问题是我用update语句时遇见的,就像下边的例子 update tableName set number = number + x 这里的 ...

  9. RabbitMQ 安装与界面管理

    RabbitMQ 安装与界面管理 RabbitMQ概述 官网:https://www.rabbitmq.com/ RabbitMQ是部署最广泛的开源消息代理. RabbitMQ拥有成千上万的用户,是最 ...

  10. yoyogo v1.7.6 增强程序优雅退出和K8s Readiness检查

    YoyoGo (Go语言框架)一个简单.轻量.快速.基于依赖注入的微服务框架( web .grpc ),支持Nacos/Consoul/Etcd/Eureka/k8s /Apollo等 . 本次更新增 ...