[JavaScript]何为变量提升?

news2024/10/6 10:38:39

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/139742129
出自【进步*于辰的博客】

关于编译与解释,详述可查阅博文《[Java]知识点》中的【编译与解释】一栏。
参考笔记二,P43.3、P46.1、P9.3。

文章目录

  • 附言
  • 1、介绍
  • 2、解答
  • 3、一种特殊情况
  • 最后

附言

你在阅读本篇文章时,会看到一些名词,如:函数作用域,也就是由 var 声明的变量的作用域的名称,它是我根据我的理解自定义的。后来我了解到,JS中似乎并没有这个概念,对应的概念好像是“词法作用域”。

我暂未系统地学习JS,故无法详细地为你说明这个概念。当然,尽管我的用词可能不对,但就目前,这有助于我的学习理解。

如果你想进一步地学习这方面的知识,推荐一篇博文《JavaScript执行机制:变量提升、作用域链、词法作用域、块级作用域、闭包和this》(转发)。

1、介绍

什么是“变量提升?

“变量提升”是指在解释时,解释器先扫描整个JS脚本,将所有声明(包括变量和函数)移动到作用域顶端的机制,其本质就是声明与定义不同步的错觉。

var 与 let 具有相同的变量提升机制,故经变量提升后(“解释”后)的脚本相同。

PS:大家可能不明其意,往下看。

先说说两种修饰符声明变量的作用域的定义:

  1. var:作用域的“上界”是变量声明处“往上”的第一个函数花括号({),故也称为“函数作用域”。var 允许重复声明和定义。
  2. let:作用域的“上界”是变量声明处“往上”的第一个花括号({).,故也称为“块级作用域”。let 不允许重复声明和定义(同一作用域)。

let 与 var 不同的是,let 声明的变量在定义之前,存在“暂时性死区”,

示例:

console.log(str)
let str = 1

输出结果:
在这里插入图片描述
因为示例代码经“变量提升”后:

let str
console.log(str)
str = 1

这就是“暂时性死区”,在定义前访问或赋值会报错。如:let str是声明,let str = 1是定义。

2、解答

1:如何理解“函数的变量提升优先于变量?”(PS:一些资料中可能会这样阐述)

事实上,之前由于我的JS功底不够扎实,也误解了这句话,以为是这样:

console.log(b)
var a = 1
var b = function() {
	return 2
}

经变量提升后:

var b
var a
console.log(b);// undefined
a = 1
b = function() {
	return 2
}

如果真的如我之前这般理解,无意义,并且也理解错误。

那么,“函数的变量提升优先于变量”这句话到底是什么意思?我从博文《JavaScript执行前的秘书——预编译》(转发)中取经得知,如下:

console.log(b)
var a = 1
function b() {
	return 2
}

经变量提升后:

function b() {
	return 2
}
var a
console.log(b);// [Function: b]
a = 1

所以,我之前是把var b = function() {}的形式误解为"函数声明”,实际上,这也是“变量声明”,只是变量值定义为函数而已。

最后,引用一段“取经”博文中的阐述:
在这里插入图片描述

2:如何解释“let 不允许重复声明和定义”?

我们先来看由 var 修饰的情况,示例:

var a = 1
var a = 2

经变量提升后:

var a
a = 1
a = 2

也就是:变量提升会将重复声明进行覆盖

再来看 let 的情况。如果两个同名的变量都由 let 修饰,报错,这是 let 的特性。大家疑惑的多是这种情况:

var a = 1
let a = 2

先解答:也会报错。为什么?这涉及到一个细节:

var 的变量提升的优先级高于 let。

也就是说,经变量提升后:

var a
let a
a = 1
a = 2

这种情况 let 同样不允许,故报错。

稍作修改:

let a = 1
var a = 2

这种情况与上述完全相同,故也不允许。

3、一种特殊情况

在上文中,我们说到,这种情况不允许:

var a = 1
let a = 2

那么,请问下面这种情况能正常执行吗?

var a = 1
{----------------------A
	let a = 2
}

要解决这个问题,就要研究 var 与 let 的作用域了,大家还记得我在上文中所述的它们的作用域的定义吗?结论:

第一个a的作用域是“全局”,而第二个a的作用域是 A 处的代码块。

因此,两个a的作用域不同,故不报错。

再给大家抛出一个问题:这样会报错吗?

let a = 1
{
	var a = 2
}

PS:相信大家看到这里,已经对 var 和 let 有了足够的掌握,这个问题就交由大家思考了。

最后,为大家补充两个结论:

  1. var 是ES5的语法,let 是ES6的语法。
  2. 定义变量时可以不用 var 或 let 修饰(即直接a = 1),那么 var 与 let 的作用是什么?var 与 let 定义 / 决定了变量的作用域。因此,定义变量时如果不用 var 或 let 修饰,就不存在“变量提升”,则在定义前访问或赋值将直接报错。

最后

其实,在日常工作中,区分var与lei的实际作用并不大,我们更关注的是业务的梳理。因此,本篇文章旨在巩固JS基础。

本文完结。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1832956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SQL:按用户名复制权限

生产系统中有一个模块是管理用户及菜单权限,它们是由3个数据表组成,关系及字段如下: 原来为每个用户添加菜单的访问权限时都是一个一个添加,但今天遇到有个新来的员工,需要具有与另一个员工相同的权限。新建一个用户后…

SQL Server 中处理重复数据:保留最新记录的两种方案

目录 首先准备测试的数据表 方案一. 使用ROW_NUMBER()函数删除重复项 方案二. 使用临时表的方式 大家在项目开发过程中,数据库几乎是每一个后端开发者必备的技能,并且经常会遇到对于数据表重复数据的处理,一般需要去除重复保留最新的记录。今天这里给大家分享两种种方案,…

【Git】-- 添加公钥到 github 或者gitlab上

仅针对系统:mac os 、 unix、linux 1、检查是否有 id_rsa.pub $ cd ~ $ ls -al ~/.ssh 注意:若已有 id_rsa.pub,则必要执行 第二步,避免覆盖掉原有正常的公钥。 配置多个 git 账号请参考:同一台电脑配置多个git账…

Python工具箱系列(五十三)

​​水印 水印是一种常见的图片处理需求。当既需要展示,又需要保护知识产权时,就需要使用文字或者图片来打水印。下面的代码展示了文字水印与图片水印的过程。 ​--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown from pat…

电源小白入门学习11——反激电源电路原理

电源小白入门学习11——反激电源、正激电源 隔离电源变压器介绍反激电源 前面我们学习了BUCK、BOOST、BUCK-BOOST 等各种各样的DCDC变换器,但是他们都有一共同的特点,即能量的传输路径时一个完整的通路,输入与输出之间不存在电气隔离&#xf…

C++链表相关内容温习回顾——移除链表元素

本文主要对之前学过的C链表相关内容进行温习回顾,并以 移除链表元素 为例,进行应用。 关于链表的基础理论可见:链表理论基础 应用示例:LeetCode 203 移除链表元素 https://leetcode.cn/problems/remove-linked-list-elements/ 0、…

Redis作者长文总结LLMs, 能够取代99%的程序员

引言 这篇文章并不是对大型语言模型(LLMs)的全面回顾。很明显,2023年对人工智能而言是特别的一年,但再次强调这一点似乎毫无意义。相反,这篇文章旨在作为一个程序员个人的见证。自从ChatGPT问世,以及后来使…

定个小目标之刷LeetCode热题(22)

这道题最容易想的就是排序后再遍历,但是时间复杂度就不是O(n)了,所以还是得用更优的解法,直接看题解,它是使用了HashSet,遍历数组,对于每一个数x,如果不存在x - 1则进入内循环,否则跳…

springboot弘德图书馆座位预约管理系统-计算机毕业设计源码07028

摘 要 在面对当今培育人才计划的压力,人们需要汲取更多的不同领域的知识来不断扩充自己的知识层面,因此他们对学习的欲望不断扩大,图书馆作为我们的学习宝地,有着不可替代的地位。但是在信息化时代,传统模式下的图书馆…

四川蔚澜时代电子商务有限公司抖音开店靠谱吗?

在数字化浪潮席卷全球的今天,电子商务以其独特的魅力和优势,成为了推动经济发展的重要引擎。作为四川地区电商服务的佼佼者,四川蔚澜时代电子商务有限公司凭借其深厚的行业积淀和前瞻的战略眼光,专注于抖音电商服务领域&#xff0…

pytest并发执行时token异常处理问题

接前面加入钩子函数处理token复用的问题,只保证了用例的串联执行,我的部分测试用例中接入了通义千问的部分接口生成测试数据,七八个场景跑完差不多快要10分钟。考虑使用并发执行。 http://t.csdnimg.cn/ACexL 使用多线程和不使用耗时差距很大…

Node-red win11安装

文章目录 前言一、安装node.js和npm二、安装Node-red三、 运行Node-red 前言 Node-RED 是一种编程工具,用于以新颖有趣的方式将硬件设备、API 和在线服务连接在一起。 它提供了一个基于浏览器的编辑器,只需单击一下即可将调色板中的各种节点轻松连接在…

EXCEL数据导入HIVE

引言 本文将论述如何将Windows本地的excel表数据,导入到虚拟机Linux系统中的Hadoop生态中的Hive数据仓库中。 实验准备 DBeaver Hive3.1(Hadoop3.1) excel数据表 实验步骤 一、首先打开虚拟机,启动Hadoop,启动hive,启动hiveserver2,连接DBeaver,成功连接展示如下…

VS2022打开.netcore2.2 问题解决

1.vs2022运行时一直提示异常 2.解决方法,双击当前的项目修改xxxx.csproj文件 把当前的版本修改为2.2.0即可重新编译运行

便携式手持气象仪:低功耗设计

TH-LSZ05便携式手持气象仪是一款轻便、操作简便的气象监测工具,集成了风向、风速、大气压、温度、湿度五项气象要素的测量功能。这些设备通常设计为体积小、重量轻,以便于用户随时携带并使用。通过使用手持气象仪,用户可以实时获取关键的气象…

MYSQL 三、mysql基础知识 7(MySQL8其它新特性)

一、mysql8新特性概述 MySQL从5.7版本直接跳跃发布了8.0版本 ,可见这是一个令人兴奋的里程碑版本。MySQL 8版本在功能上 做了显著的改进与增强,开发者对MySQL的源代码进行了重构,最突出的一点是多MySQL Optimizer优化器进行了改进。不仅在速度…

【QT5】<重点> QT网络编程

文章目录 前言 一、QT中的TCP编程 1. TCP简介 2. 服务端程序编写 3. 客户端程序编写 4. 服务端与客户端测试 二、QT中的UDP编程 1. UDP简介 2. UDP单播与广播程序 前言 本篇记录QT中TCP和UDP网络编程知识。 一、QT中的TCP编程 1. TCP简介 TCP是面向连接的、可靠的、…

关于事务流的思考

关于事务流的思考 1 事务流业务分析 ​ 不同业务可能有不同的审核流程,而activiti为大家提供了一套公用的审核功能,基于这些功能我们可以根据自己的业务需求组合出我们自己的审核流程,而这里我要实现的事务流有如下功能:角色为结…

MySQL 数据库 Navicat Premium 16.01 安装教程

MySQL 数据库 Navicat Premium 16.01 安装教程 目录 MySQL 数据库 Navicat Premium 16.01 安装教程前言安装步骤同意协议选择安装目录桌面快捷方式安装正在安装安装完成 步骤获取 前言 MySQL数据库管理用Navicat更加方便,可视化效果更好,今天给大家带来…

八股文之JVM

目录 1.JVM内存划分 2.JVM类加载过程 3.JVM垃圾回收机制GC 3.1.判断谁是垃圾 3.2.如何释放对应的内存 1.JVM内存划分 在一个Java程序运行起来之后,jvm就会从操作系统中申请一块内存,然后就会将该内存划分成多个部分,用于不同的用途。 …