js中变量提升和函数提升
变量提升和函数提升的总结
我们在学习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中变量提升和函数提升的更多相关文章
- JS中变量名和函数名重名
今天骚凯问了一道变量名冲突的题目,感觉很有意思,顺便也复习一下预解析的一些知识,有不对的地方忘前辈大神指正,题目是这样的: var a=100; function a(){ console.log(a ...
- js中的变量提升和函数提升
从上周开始,我所在的学习小组正式开始了angular的学习,angular是全面支持es6的,所以语法上和以前的angular有了很大的不同,比如变量声明时就抛弃了var,而选择了let和const: ...
- 关于JS中变量提升的规则和原理的一点理解
关于变量提升,以前在一些教程和书籍上都听到过,平时开发中也知道有这个规律,但是今天突然在一个公开课中听到时,第一反应时一脸懵逼,然后一百度,瞬间觉得好熟悉啊,差点被这个概念给唬住了,不信我给你 ...
- JS 变量提升与函数提升
JS 变量提升与函数提升 JS变量提升 变量提升是指:使用var声明变量时,JS会将变量提升到所处作用域的顶部.举个简单的例子: 示例1 console.log(foo); // undefined ...
- js变量提升与函数提升的详细过程
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- JS——变量提升和函数提升
一.引入 在了解这个知识点之前,我们先来看看下面的代码,控制台都会输出什么 var foo = 1; function bar() { if (!foo) { var foo = 10; } aler ...
- 关于JS中变量提升的规则和原理的一点理解(二)
上篇文章中讲到变量提升和函数提升的先后顺序时蒙了,后来去查了一下资料,特别整理一下. 在<你不知道的JavaScript(上卷)>一书的第40页中写到:函数会首先被提升,然后才是变量. 书 ...
- 谈谈javascript中的变量提升还有函数提升
在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...
- JS逻辑题 技术点: 1). 变量提升 2). 函数提升 3). 预处理 4). 调用顺序
考查的技术点: 1). 变量提升 2). 函数提升 3). 预处理 4). 调用顺序 var c = 1; function c(c) { console.log(c); var c = 3; ...
随机推荐
- 重磅!GitHub官方开源新命令行工具
近日,GitHub 发布命令列工具 (Beta) 测试版,官方表示,GitHub CLI提供了一种更简单.更无缝的方法来使用Github.这个命令行工具叫做GitHub CLI,别名gh. 现在,你就 ...
- 题解 P3605 [USACO17JAN]Promotion Counting P
分块\(yyds\) ----关于线段树合并的题我用分块过掉这件事 题目传送门 先说正解 正解当然是线段树合并等一类做法了 至于解析...出门右转题解区第一篇 (就是他让我看不懂,然后用分块打的\(Q ...
- SqlServer数据库分区
在最近的项目中,在尽可能优化了sql语句后,上层仍要求对数据库进行优化,因为考虑到系统上线后数据量会非常庞大,而且这些个表的数据都有明显的时间划分,于是就引入了数据库分区的概念.摘用百度百科的定义,数 ...
- 12、创建mysql用户及赋予用户权限
1.通过help命令查看grant的用法: CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password'; GRANT ALL ON db1.* ...
- RabbitMQ重试机制
消费端在处理消息过程中可能会报错,此时该如何重新处理消息呢?解决方案有以下两种. 在redis或者数据库中记录重试次数,达到最大重试次数以后消息进入死信队列或者其他队列,再单独针对这些消息进行处理: ...
- CentOS-Docker搭建MinIO(单点)
下载镜像 $ docker pull minio/minio 创建相关目录 $ mkdir /home/minio/data /home/minio/config -p 运行镜像(自定义Access和 ...
- XCTF getit
一.查壳 是linux的文件.没加壳 二.拖入ida 分析一下逻辑,发现就是t的值就是flag. 写个exp就出来了. 三.exp分享 s='c61b68366edeb7bdce3c6820314b7 ...
- 从2021强网杯的一道题学习docx文件操作
[强网先锋]寻宝 啊对就是这道题,大佬们都贼快,菜如我还得慢慢整 key1 大佬们都一笔带过,哎,虽然简单,但是也别这么虐我们啊 我来简单写一下吧 <?php header('Content-t ...
- luogu P2710 数列
(这是个双倍经验呀! 题目描述 维护一个可以支持插入.删除.翻转.区间赋值.求和.求值和求最大子段和操作的序列.(真·简洁) solution 基本不用什么神奇操作,平衡树硬上就行.(我用的 Spla ...
- 「Ynoi2015」我回来了
「Ynoi2015」我回来了 这东西已经不是 Ynoi 了,因为太水被嫌弃了. 如何提升自己的数据结构能力?从Ynoi做起 题目链接 其实这个题很小清新的辣,而且不卡常. 由于边权为 \(1\),所以 ...