let命令

news2024/11/16 18:42:21
  • let 命令
    • let 与 var
      • 二者区别:
        • 作用域不同
        • 变量提升(Hoisting)
        • 临时性死区
        • 重复声明
      • 联系:
      • 举例说明:
    • 块级作用域
      • 块级作用域的关键字
      • 使用 var(无块级作用域)
      • 使用 let(块级作用域)
      • 使用 const(块级作用域且常量)
    • 块级作用域与函数声明

1. let 命令

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

{
  let a = 10;
  var b = 1;
}
a // ReferenceError: a is not defined.
b // 1

上面代码在代码块之中,分别用 let 和 var 声明了两个变量。然后在
代码块之外调用这两个变量,结果 let 声明的变量报错, var 声明的
变量返回了正确的值。

这表明, let 声明的变量只在它所在的代码块有效。

1.1. let 与 var

letvar 都是用来在 JavaScript 中声明变量的关键字,但它们之间存在一些关键区别:

1.1.1. 二者区别:
1.1.1.1. 作用域不同
  • var 声明的变量具有函数作用域全局作用域

如果在函数内部声明,它只在该函数内部可见;如果在函数外部声明,则在整个脚本中都可见,成为全局变量(在浏览器环境下,全局变量会成为 window 对象的属性)。

  • let 声明的变量具有块级作用域

这意味着变量只在它声明的那个代码块(例如,if 语句、for 循环或者一对大括号 {} 内)内有效。

1.1.1.2. 变量提升(Hoisting)
  • var 声明的变量会存在变量提升现象,即使声明在代码执行之后,变量也会被提升至作用域顶部,但在赋值前其值为 undefined

  • let 不会发生变量提升,如果在声明前访问 let 变量,会导致引用错误(ReferenceError)。

1.1.1.3. 临时性死区

当使用 letconst 声明变量时,在声明之前访问这些变量会触发错误,这个区域被称为临时死区。

这是为了防止变量在声明前的不确定状态,提高代码的可预测性。

if (true) {
  console.log(temp); // 报错,temp在TDZ中
  let temp = "ES6";
}

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

var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}

上面代码中,存在全局变量 tmp ,但是块级作用域内 let 又声明了一
个局部变量 tmp ,导致后者绑定这个块级作用域,所以在 let 声明变
量前,对 tmp 赋值会报错。

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

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

if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

上面代码中,在 let 命令声明变量 tmp 之前,都属于变量 tmp 的“死
区”。

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

1.1.1.4. 重复声明
  • 使用 var 可以在同一作用域内重复声明同一个变量,后面的声明会覆盖前面的声明。

  • let 不允许在同一作用域内重复声明同一个变量,尝试这样做会导致语法错误。

1.1.2. 联系:
  • 它们都是用于变量声明的关键词。
  • 在基本的变量赋值和访问操作上,两者的行为是类似的,一旦声明并赋值后,都可以用来存储数据。
1.1.3. 举例说明:
// var 示例
function varExample() {
  var x = 1;
  if (true) {
    var x = 2; // 这里改变了外层函数的x
    console.log(x); // 输出2
  }
  console.log(x); // 输出2,因为var变量提升了且被覆盖
}

// let 示例
function letExample() {
  let y = 1;
  if (true) {
    let y = 2; // 这里创建了一个新的块级作用域变量y
    console.log(y); // 输出2
  }
  console.log(y); // 输出1,因为let有块级作用域
}

varExample(); // 调用函数演示var行为
letExample(); // 调用函数演示let行为

在这个例子中,varExample 函数展示了使用 var 时变量提升以及在相同作用域内重复声明导致的变量覆盖现象。

letExample 函数则展示了 let 如何在块级作用域内创建独立的变量,避免了变量覆盖的问题。

ES6 规定暂时性死区和 let 、 const 语句不出现变量提升,主要是为
减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料
之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免
此类错误就很容易了。

1.2. 块级作用域

ES5 只有全局作用域和函数作用域,没有块级作用域。

ES6(ECMAScript 2015)引入了块级作用域,这是一种新的变量作用域规则,它允许变量在代码块(通常是一对大括号 {} 内)内声明和使用,超出这个块之后,这些变量就会被销毁或不再可见。

这与ES5中的作用域规则不同,ES5中只有全局作用域和函数作用域,没有块级作用域的概念。

实例一

var tmp = new Date();
function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}
f(); // undefined

实例二

var tmp = new Date();
function f() {
  console.log(tmp); 
}
f(); // Mon May 06 2024 09:44:26 GMT+0800 (中国标准时间)

实例一代码的原意是, if 代码块的外部使用外层的 tmp 变量,内部使
用内层的 tmp 变量。但是,函数 f 执行后,输出结果为 undefined

原因在于变量提升,导致内层的 tmp 变量覆盖了外层的 tmp 变量。

1.2.1. 块级作用域的关键字
  • let: 用于声明一个块级作用域的变量,它可以重复声明,但在同一作用域内不能重复初始化。
  • const: 用于声明一个块级作用域的常量,一旦赋值不能改变,也不能重新声明。
1.2.2. 使用 var(无块级作用域)

在ES5中,即使变量在某个代码块内声明,它也会被提升到包含它的函数作用域或全局作用域中。

var x = 1;
if (true) {
  var x = 2; // 这里的x会覆盖外层的x
}
console.log(x); // 输出2
1.2.3. 使用 let(块级作用域)

使用 let 声明的变量只在声明它的块内有效。

let y = 1;
if (true) {
  let y = 2; // 这个y只在这个if块内有效
}
console.log(y); // 输出1,外层的y不受影响
1.2.4. 使用 const(块级作用域且常量)

const 声明的变量同样遵循块级作用域,而且声明后其值不能被重新赋值。

if (true) {
  const z = 3; // z是一个常量,只能在此if块内访问
  // z = 4; // 这里会报错,尝试修改常量值
}
// console.log(z); // 这里也会报错,z在块外不可见

1.3. 块级作用域与函数声明

函数能不能在块级作用域之中声明?这是一个相当令人混淆的问题。

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

// 情况一
if (true) {
  function f() {}
}
// 情况二
try {
  function f() {}
} catch(e) {
// ...
}

上面两种函数声明,根据 ES5 的规定都是非法的。

在ES6(ECMAScript 2015)之前,JavaScript只有全局作用域和函数作用域。这意味着在函数外部声明的变量是全局变量,在函数内部声明的变量则是局部变量,仅在该函数内部可见。然而,对于if语句、for循环等代码块内部,并没有自己的作用域。

ES6引入了块级作用域,主要通过letconst关键字实现,这使得开发者可以在任何块(例如if语句、for循环的花括号内)内声明变量,这些变量的作用域仅限于该块。

关于函数声明在块级作用域中的行为,ES6规范试图明确函数声明应当具有块级作用域特性,即在块内声明的函数只应在该块内可访问。

理论上,这样的函数声明应该类似于使用let声明的变量,只在声明它们的块中可见。例如:

{
  function sayHello() {
    console.log("Hello");
  }
  sayHello(); // 此处可以调用
}
// sayHello(); // 理论上此处应该报错,因为sayHello只在上面的块内可见

但实际上,由于历史遗留原因和浏览器兼容性问题,早期的ES6实现中,函数声明在块级作用域的行为并不统一。

一些环境(特别是某些浏览器)可能仍然会将块级函数声明提升到包含块的顶部,或者有其他非标准行为。

因此,在实际开发中,为了避免潜在的问题,推荐在块级作用域内使用函数表达式而非函数声明:

{
  const sayHello = function() {
    console.log("Hello");
  };
  sayHello(); // 正确使用函数表达式
}
// sayHello(); // 这里依然会报错,因为sayHello是块级作用域内的函数表达式

总结来说,虽然ES6旨在让函数声明遵循块级作用域规则,但由于兼容性问题,最好在块级作用域中使用函数表达式以确保代码的可预测性和兼容性。

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

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

相关文章

C++中的std::bind深入剖析

目录 1.概要 2.原理 3.源码分析 3.1._Binder分析 3.2._CALL_BINDER的实现 4.总结 1.概要 std::bind是C11 中的一个函数模板,用于创建一个可调用对象(函数对象或者函数指针)的绑定副本,其中一部分参数被固定为指定值&#xf…

​​​​【收录 Hello 算法】4.4 内存与缓存

目录 4.4 内存与缓存 4.4.1 计算机存储设备 4.4.2 数据结构的内存效率 4.4.3 数据结构的缓存效率 4.4 内存与缓存 在本章的前两节中,我们探讨了数组和链表这两种基础且重要的数据结构,它们分别代表了“连续存储”和“分散存储”两种物理…

Qt常用基础控件总结

一、按钮部件 按钮部件共同特性 Qt 用于描述按钮部件的类、继承关系、各按钮的名称和样式,如下图: 助记符:使用字符"&“可在为按钮指定文本标签时设置快捷键,在&之后的字符将作为快捷键。比如 “A&BC” 则 Alt+B 将成为该按钮的快捷键,使用”&&qu…

铁山靠之数学建模 - Matlab入门

Matlab基础 1. Matlab界面与基本操作1.1 matlab帮助系统1.2 matlab命令1.3 matlab功能符号1.4 matlab的数据类型1.5 函数计算1.6 matlab向量1.7 matlab多项式1.8 M文件1.9 函数文件1.10 matlab的程序结构1.11 echo、warning和error函数1.12 交互输入1.13 程序调试1.14 设置断点…

游戏陪玩平台app小程序H5源码交付游戏陪玩接单软件游戏陪玩源码 陪玩小程序陪玩工作室运营模式陪玩管理系统游戏陪玩工作室怎么做

提供陪玩平台源码,陪玩系统源码,陪玩app源码,团队各部门配备齐全,分工明确,及时对接开发进度,保证开发效率 一、陪玩平台源码的功能介绍 1、派单大厅:陪玩系统源码的派单大厅内支持用户通过语音连麦的方式…

idea已配置的git仓库地址 更换新的Git仓库地址 教程

文章目录 目录 文章目录 更改流程 小结 概要更改流程技术细节小结 概要 先在idea控制台走一下流程 先将本地的git仓库删除 1. 查看当前远程仓库地址: 在终端或命令行中,导航到你的项目目录,并运行以下命令查看当前的远程仓库地址&#xff…

QT+MYSQL数据库处理

1、打印Qt支持的数据库驱动&#xff0c;看是否有MYSQL数据库驱动 qDebug() << QSqlDatabase::drivers(); 有打印结果可知&#xff0c;没有MYSQL数据库的驱动 2、下载MYSQL数据库驱动&#xff0c;查看下面的文章配置&#xff0c;亲测&#xff0c;可以成功 Qt6 配置MySQL…

智能BI(后端)-- 系统异步化

文章目录 系统问题分析什么是异步化&#xff1f;业务流程分析标准异步化的业务流程系统业务流程 线程池为什么需要线程池&#xff1f;线程池两种实现方式线程池的参数线程池的开发 项目异步化改造 系统问题分析 问题场景&#xff1a;调用的服务能力有限&#xff0c;或者接口的…

phpstudy(MySQL启动又立马停止)问题的解决办法

方法一&#xff1a;查看本地安装的MySQL有没有启动 1.鼠标右击开始按钮选择计算机管理 2.点击服务和应用程序 3.找到服务双击 4.找到MySQL服务 5.双击查看是否启动&#xff0c;如启动则停止他&#xff0c;然后确定&#xff0c;重新打开phpstudy,启动Mysql. 方法二&#xff…

OpenHarmony 实战开发——3.1 Release + Linux 原厂内核Launcher起不来问题分析报告

1、关键字 Launcher 无法启动&#xff1b;原厂内核&#xff1b;Access Token ID&#xff1b; 2、问题描述 芯片&#xff1a;rk3566&#xff1b;rk3399 内核版本&#xff1a;Linux 4.19&#xff0c;是 RK 芯片原厂发布的 rk356x 4.19 稳定版内核 OH 版本&#xff1a;OpenHa…

net7部署经历

1、linux安装dotnet命令&#xff1a; sudo yum install dotnet-sdk-7.0 或者直接在商店里安装 2、配置反向代理 127.0.0.1:5000》localhost 访问后报错 原因&#xff1a;数据表驼峰名&#xff0c; 在windows的数据表不区分大小写&#xff0c;但是在linux里面是默认区分的&…

xiuno(修罗)知乎模板二开优化魔板仿网盘资源社–模板加全套插件

使用说明 以服务器为例搭建教程 ①先安装 PHP7.1 版本 再安装数据库 Mysql ②解压文件&#xff1a;xiunobbs_4.0.4&#xff08;解压到根目录&#xff09;.zip ③解压②完成后找到【plugin】文件夹再解压&#xff1a;plugin(解压到 plugin 文件夹).zip 设置伪静态代码在上面&am…

记录如何查询域名txt解析是否生效

要查询域名的TXT记录&#xff0c;可以使用nslookup命令。具体步骤如下&#xff1a;12 打开命令行终端。输入命令 nslookup -qttxt 域名&#xff0c;将"域名"替换为你要查询的实际域名。执行命令后&#xff0c;nslookup会返回域名的TXT记录值。 如何查询域名txt解析是…

【C++后端项目】负载均衡OJ服务器

文章目录 一、演示项目二、所用技术与开发环境所用技术开发环境 三、项目宏观结构I. 风格&#xff1a;仿leetcodeII. 结构&#xff1a;Browser-Server模式III. 编写思路&#xff1a;编译服务 -> OJ服务 -> 前端设计 四、关于Git分支管理✨4.1 Git 分支结构4.2 Git 分支命…

【linux】主分区,扩展分区,逻辑分区,动态分区,引导分区,标准分区

目录 主分区&#xff0c;扩展分区&#xff0c;逻辑分区 主分区和引导分区 主分区&#xff0c;扩展分区&#xff0c;逻辑分区&#xff08;标准分区&#xff09; 硬盘一般划分为一个“主分区”和“扩展分区”&#xff0c;然后在扩展分区上再分成数个逻辑分区。 磁盘主分区扩展…

调用 gradio 创建聊天网页报错(使用远程服务器)

文章目录 写在前面1、使用默认IP地址&#xff08;失败&#xff09;2、使用本地IP地址&#xff08;失败&#xff09;3、使用远程服务器IP地址&#xff08;成功&#xff09; 写在前面 我复现了github上的 llama-chinese 的工作 使用的是 llama2&#xff0c;环境配置是在远程服务…

如何使用 ArcGIS Pro 计算容积率

容积率是指地上建筑物的总面积与用地面积的比率&#xff0c;数值越小越舒适&#xff0c;这里为大家介绍一下如何使用ArcGIS Pro 计算容积率&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的建筑和小区数据&#xff0c;除了建筑和小区数据&am…

智能合约是什么?搭建与解析

智能合约是一种基于区块链技术的自动化执行合约&#xff0c;它通过编程语言编写&#xff0c;并在区块链网络上部署运行。智能合约是区块链技术的重要组成部分&#xff0c;它使得去中心化应用&#xff08;DApp&#xff09;的开发变得更加便捷和高效。本文将从智能合约的搭建、原…

如何解决 NPM依赖下载超时问题 :npm ERR! network timeout at: https://registry.npmjs.org/猫头虎

如何解决 NPM依赖下载超时问题 &#xff1a;npm ERR! network timeout at: https://registry.npmjs.org/猫头虎 博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试…

正交频分复用回顾(通俗易懂)

OFDM我们知道&#xff0c;叫做正交频分复用&#xff0c;它是4G的一个关键技术&#xff0c;4G的多址技术叫做OFDMA&#xff0c;也就是说4G是通过OFDM来作用户区分的&#xff0c;具体是什么意思呢&#xff1f;继续往下看。 图1 在2G和3G时代&#xff0c; 单用户都是用的一个载波…