【面试题】【ES6】let和const命令 (面试必看)

news2024/11/25 16:43:41

  给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:前端面试题库

1、let命令

基本用法

用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

let只能出现在当前作用域的顶层。

for循环中,使用let声明循环变量i,当前的i只在本轮循环有效,每一次循环的i都是一个新的变量。

for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

不存在变量提升现象

变量提升:变量可以在声明之前使用,使用var声明的变量会自动提升到函数作用域顶部。

==》具体争议转看下文“关于是否存在变量提升的争议问题”

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError 受到let约束
  let tmp;
}
复制代码

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,TDZ)

在没有引入lettypeof是绝对安全,不会出错的 typeof对于没有声明的变量会显示undefined不会报错,但是对于未声明的变量会报错ReferenceError

总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

不允许重复声明

注意区分重复冗余声明和嵌套声明

2、块级作用域

存在意义

ES5只有全局作用域和函数作用域

解决以下场景问题:

  1. 内层变量可能会覆盖外层变量。
  2. 用来计数的循环变量泄露为全局变量。

ES6的块级作用域

let为JavaScript新增了块级作用域。
ES6允许块级作用域的任意嵌套。
内层作用域可以定义外层作用域的同名变量。

块级作用域的出现,实际上使得获得广泛应用的**匿名立即执行函数表达式(匿名 IIFE)**不再必要了。

块级作用域与函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。
为了避免块级作用域内声明的函数的处理规则对老代码产生很大的影响,减轻不兼容问题,ES6允许浏览器有自己的行为方式,规则如下:

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

根据这三条规则,浏览器的 ES6 环境中,块级作用域内声明的函数,行为类似于var声明的变量。
考虑到环境导致的行为差异太大,应该避免在块级作用域内声明函数。如果确实需要,也应该写成函数表达式,而不是函数声明语句。

// 块级作用域内部的函数声明语句,建议不要使用
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 块级作用域内部,优先使用函数表达式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}
复制代码

ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

3、const命令

基本用法

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const的作用域与let命令相同:只在声明所在的块级作用域内有效。

const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

const声明的常量,也与let一样不可重复声明。

本质

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

对于简单数据类型,值就是保存变量的内存地址【常量】;复合数据类型,变量指向的内存地址保存的只是一个指向实际数据的指针

const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

因此使用const声明一个对象,对象的属性是可变的,但是不能改变对象为另一个对象(不能改变指针的指向)。

冻结对象,无法改变对象属性应该使用Object.freeze方法。

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};
复制代码

ES6声明变量的六种方法

ES5

  1. var
  2. function

ES6

  1. let
  2. const
  3. import
  4. class

4、顶层对象的属性

顶层对象,在浏览器环境指的是window对象,在 Node 指的是global对象。

ES5 之中,顶层对象的属性与全局变量是等价的。

顶层对象的属性与全局变量挂钩带来的问题:

  1. 首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);
  2. 其次,程序员很容易不知不觉地就创建了全局变量(比如打字出错);
  3. 最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。
  4. 另一方面,window对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。

从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

  • var命令和function命令声明的全局变量,依旧是顶层对象的属性;
  • let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。

5、globalThis对象

JavaScript 语言存在一个顶层对象,它提供全局环境(即全局作用域),所有代码都是在这个环境中运行。

但是,顶层对象在各种实现里面是不统一的。

  • 浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window
  • 浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self
  • Node 里面,顶层对象是global,但其他环境都不支持。

很难找到一种方法在所有情况下都取到顶层对象,因此ES2020引入了globalThis作为顶层对象。

关于是否存在变量提升的争议问题

在学习该部分知识时,依据的是ES6入门教程以及MDN中文文档的内容,没有过多参看其他官方文档,便断定letconst不存在变量提升。但经过大佬指点后拜读了mdn英文文档,文档中描述了letconstclass来说是存在变量提升的,以下做详细解释。

MDN英文文档说明存在以下三种认为是变量提升(Hositing)的行为:

【原文】Hoisting is not a term normatively defined in the ECMAScript specification. The spec does define a group of declarations as HoistableDeclaration, but this only includes function, function*, async function, and async function* declarations. Hoisting is often considered a feature of var declarations as well, although in a different way. In colloquial terms, any of the following behaviors may be regarded as hoisting:

【翻译】Hosting(变量提升)不是 ECMAScript 规范中规范定义的术语。该规范确实将一组声明定义为HoistableDeclaration,但这仅包括函数,函数*,异步函数和异步函数*声明。变量提升通常也被认为是var声明的一个特征,尽管方式不同。通俗地说,有下列行为之一,可视为变量提升:

  1. Being able to use a variable's value in its scope before the line it is declared. ("Value hoisting")

【翻译】能够在声明变量的行之前在其范围内使用变量的值。(“值变量提升”)

【实例】ECMAScript规范说明中写到作为HoistableDeclaration的四种function声明:functionfunction*async functionasync function*

  1. Being able to reference a variable in its scope before the line it is declared, without throwing a ReferenceError, but the value is always undefined. ("Declaration hoisting")

【翻译】能够在声明该变量的行之前在其作用域中引用该变量,而不会引发ReferenceError,但该值始终未定义。(“声明变量提升”)

【实例】var命令的变量提升

  1. The declaration of the variable causes behavior changes in its scope before the line in which it is declared.

【翻译】变量的声明会导致在声明它的行之前在其作用域中发生行为更改。

【实例】letconstclass声明命令(也统称为词汇声明lexical declarations)

看到这里有个问题:既然存在变量提升,为何ES6入门和MDN中文文档中都没有注明呢?

MDN英文文档也给出了解释:

因为暂时性死区的存在,严格禁止了在变量声明前进行使用,所以很多地方都认为letconstclass声明命令不存在变量提升。这种异议也合理的,因为变量提升并不是一个被定义到ECMAScript中的普遍认可的术语(universally-agreed term)。但是暂时性死区可能会导致其范围内发生其他可观察到的变化,这表明是存在着变量提升的。

实例如下:

【原文】If the const x = 2 declaration is not hoisted at all (as in, it only comes into effect when it's executed), then the console.log(x) statement should be able to read the x value from the upper scope. However, because the const declaration still "taints" the entire scope it's defined in, the console.log(x) statement reads the x from the const x = 2 declaration instead, which is not yet initialized, and throws a ReferenceError. Still, it may be more useful to characterize lexical declarations as non-hoisting, because from a utilitarian perspective, the hoisting of these declarations doesn't bring any meaningful features.

【翻译】如果说 const x = 2的声明完全没有被变量提升(那么它只在执行时生效),那么console.log(x)应该是能够从上层作用域中读取到x的值的。但此处因为const的声明依然“污染”到了它定义的整个作用域,所以console.log(x)语句实际上读取到的是const x = 2 声明的x,并抛出ReferenceError。尽管如此,将词汇声明(lexical declarations) 描述为非变量提升可能更有用,因为从功利的角度来看,这些变量提升不会带来任何有意义的特征。

【注意】以下这种情况不属于变量提升:

{
  var x = 1;
}
console.log(x); // 1
复制代码

因为这里没有“先访问后声明”,这里只是因为var声明没有在块范围内。

结论

综上所述,实际上letconst是存在变量提升的,但通常不会刻意去这样描述,因为从功利的角度来看,这些变量提升并不会带来任何有意义的特征。

  给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:前端面试题库

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

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

相关文章

全国计算机三级嵌入式 - 题库 - 真题(含答案) - 未来教育 - 视频讲解 - 资料获取

全国全国计算机三级嵌入式等级考试 1. 考题大纲 历年不一样。但是换汤不换药。 2. 考试真题 历年全部考题、真题。包含全部答案。 3. 未来教育 考点、知识点、历年真题视频讲解。 4. 资料获取 在本人的博客上传资源里!!!下载不易&#xff0…

[附源码]计算机毕业设计springboot勤工俭学管理小程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

论文投稿指南——中文核心期刊推荐(计算机技术)

>>>深度学习Tricks&#xff0c;第一时间送达<<< &#x1f680; 写在前面 &#x1f431;‍&#x1f3cd; 本期开始&#xff0c;小海带会定期推荐各专业领域的中文核心期刊及论文投稿网址&#xff0c;供大家交流参考 ~ 《中文核心期刊要目总览》——是学术界…

功率放大器主要性能指标是什么(功率放大器工作状态的分类)

电子仪器中&#xff0c;放大器末级都要带动一定的负载&#xff0c;所以末级电路不仅要求可以输出较大幅度电压&#xff0c;而且要求输出较大幅度电流&#xff0c;也就是要求放大器能够对负载输出较大的功率&#xff0c;这种测试仪器就被称为功率放大器。 功率放大器主要性能指标…

人脸检测-级联卷积

人脸检测有好多种cv都有自带 说到人脸检测&#xff0c;应该是近几年不老的话题了&#xff0c;如果要将这技术真的落实到现在产品&#xff0c;其实还有很长的路&#xff0c;不知道大家有没有发现&#xff0c;很多无人超市开始走下坡路&#xff0c;也许不仅仅是技术的原因之一吧…

idea中LeetCode无法正常使用

在风诡云谲的互联网职场中&#xff0c;随时准备好简历和刷题能力是非常必要的&#xff01;在工作时间“光明正大”刷题的神器——LeetCode插件&#xff01; 原来&#xff1a;idea 2019&#xff1b;LeetCode 6.8 目前&#xff1a;idea 2020.3&#xff1b;LeetCode 8.4 一 ide…

ARM-A架构入门基础(四)Cache

14天学习训练营导师课程&#xff1a;周贺贺《ARMv8/ARMv9架构-快速入门》 1. 定义 Cache是ARM中一块可高速访问的内存块&#xff0c;每块cache包含&#xff1a; 主要的内存地址信息&#xff1b;缓存数据。 2. Cache模型 速度方面&#xff1a;L1 cache > L2 cache > L…

从json中获取嵌套对象值(Oracle中的json_value和MySQL中的JSON_EXTRACT) 以及Oracle和MySQL处理日期语法的不同

从json中获取嵌套对象值&#xff08;Oracle中的json_value和MySQL中的JSON_EXTRACT&#xff09; 以及Oracle和MySQL处理日期语法的不同1. 从json中获取嵌套对象值1.1 Oracle 的 json_value1.2 MySQL 的 JSON_EXTRACT2. 日期问题2.1 MySQL2.1.1 获取指定日期2.1.1.1 DATE_SUB() …

高等数学(第七版)同济大学 习题10-4 (后7题)个人解答

高等数学&#xff08;第七版&#xff09;同济大学 习题10-4&#xff08;后7题&#xff09; 函数作图软件&#xff1a;Mathematica 8.设球占有闭区域Ω{(x,y,z)∣x2y2z2≤2Rz}&#xff0c;它在内部各点处的密度的大小等于该点到坐标原点的距离的平方&#xff0c;试求这球的质心…

九、Sentinel熔断与限流

Sentinel实现熔断与限流 Sentinel介绍 官网 https://github.com/alibaba/Sentinel 中文 https://github.com/alibaba/Sentinel/wiki/介绍 是什么 一句话解释&#xff0c;之前的Hystrix 能干嘛 去哪下 https://github.com/alibaba/Sentinel/releases 怎么玩 https://sp…

vue学习笔记:还不会上传文件,10分钟教会你使用input file上传文件

最近在写一个用户上传MP3文件到服务器的小案例&#xff0c;我写一个这样的界面&#xff1a; 当用户点击input的时候&#xff0c;其实这里并不是input的样式&#xff0c;而是一个div将代替了input的原生样式&#xff0c;这样比较好看一点&#xff1a; <div class"addre…

Pycharm 安装配置 pyQt5 图文操作(全)

目录前言1. 安装模块2. Pycharm 配置 pyQt52.1 配置QtDesigner2.2 配置PyUic2.3 配置pyrcc3. pyQt5界面前言 Qt是开源的GUI库&#xff0c;自带的QtDesigner 可以轻松构建界面&#xff0c;而且有非常全面的工具代码库和APIpyQt 是 Qt 库的Python版本&#xff0c;目前最新版本是…

数据库--------代数运算和关系运算

目录 传统的集合运算专门的关系运算例题1例题2关系代数的运算按运算符的不同可分为传统的集合运算和专门的关系运算两类。 传统的集合运算 并(∪): 差(-): 交(∩): 笛卡尔积():R的每一行S的矩阵 示例:

A-Level化学例题解析及练习(分子间作用力和沸点)

今日知识点&#xff1a;Intermolecular forces and boiling points 例题 Q: Nitrogen, N2, and carbon monoxide, CO, both have Mr 28. The boiling point of N2 is 77 K. The boiling point of CO is 82 K.What could be responsible for this difference in boiling point…

[附源码]计算机毕业设计JAVA校园共享单车系统

[附源码]计算机毕业设计JAVA校园共享单车系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

LinkedList源码分析

LinkedList源码分析 注意:本笔记分析对象为 Java8 版本,随版本不同,源码会发生变化。 基本介绍与类图 LinkedList 同时实现了 List 接口和 Deque 对口,也就是收它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(stack)。 这样看来,linke…

能力提高篇--协调能力【对接】

作为一名安防技术支持工程师&#xff0c;正常情况下我们的日常主要为解决问题&#xff0c;然而对于重大项目或者复杂项目&#xff0c;更多的情况下我们的职责为收集客户需求&#xff0c;拉通研发侧评估&#xff0c;确认需求&#xff0c;确认程序交付时间&#xff0c;测试和最终…

基于jsp+mysql+ssm协同办公系统-计算机毕业设计

项目介绍 本公司文档协同办公管理系统采用SSM&#xff08;SpringSpringMVCMyBatis&#xff09;框架开发,主要包括系统用户管理模块、用户信息模块、文件信息管理、个人事务管理、资料信息管理、登录模块、和退出模块等多个模块. 本系统主要包含了等系统用户管理、用户信息管理…

蓝桥杯---动态规划(1)

动态规划专题&#xff08;1&#xff09;1.糖果&#xff08;状压dp&#xff09;2.调手表&#xff08;状压dp)3.矩阵计数(状压dp)4.蒙德里安的梦想&#xff08;状压dp模板题&#xff09;5.跳跃&#xff08;动态规划&#xff0c;搜索&#xff09;5.字符排序&#xff08;逆序对&…

如何定位慢查询SQL以及优化

&#x1f468;‍&#x1f4bb;个人主页&#xff1a; 才疏学浅的木子 &#x1f647;‍♂️ 本人也在学习阶段如若发现问题&#xff0c;请告知非常感谢 &#x1f647;‍♂️ &#x1f4d2; 本文来自专栏&#xff1a; MySQL ❤️ 支持我&#xff1a;&#x1f44d;点赞 &#x1f33…