ES6中的let、const

news/2024/7/10 23:56:21 标签: es6, javascript, 前端

let

ES6中新增了let命令,用来声明变量,和var类似但是也有一定的区别

1. 块级作用域

只能在当前作用域内使用,各个作用域不能互相使用,否则会报错。

{
    let a = 1;
    var b = 1;
}
console.log(a); // 会报错
console.log(b); // 1
为什么会有块级作用域
  • 内层变量会覆盖外层变量

比如说一个函数外声明了一个变量count,在一个函数体内进行修改,然后在if语句中声明了一个相同的变量count。本意是修改外部count,内部使用新定义的count,但是会自动提升,就会发生变化。


var count = 1;
function f1 () {
    console.log(count)
    if (true) {
        var count = 3;
    }
}
f1();

代码执行时会转为

var count = 1;
function f1 () {
    var count;
    console.log(count);
    if (true) {
        var count = 3;
    }
}
f1(); // undefined
  • 循环遍历时会泄露全局变量

当使用for进行循环时,定义变量i会在全局中也能获取到。

各个作用域可以任意嵌套

外层作用域不会读取内部作用域的变量,各个作用域之间也能定义相同的变量名

块级作用域和函数声明

在ES5中函数声明只能存在顶级作用域和函数中。但是在ES6中支持在块级作用域内声明,本作用域外不能引用。

对于声明函数来说浏览器可以使用以下规则

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

如果确实需要在块级作用域内使用函数,可以使用函数表达式的形式,而不是函数声明语句。

2. 变量不会自动提升

使用var声明的变量会自动提升,会提升到函数、全局作用域的头部。意思就是说先使用后声明不会报错,变量值为undefined。

function f1 () {
    console.log(num);
    var num = 1;
}

// 当执行时代码会转化成

function f1 () {
    var num;
    console.log(num);
    num = 1;
}

这样会导致打印出的结果为undefined,而使用let声明的变量没声明前使用会直接报错。

3. 暂时性死区

也就是因为变量不会自动提升,只要在当前作用域内使用let声明某个变量,就会在当前区域进行绑定,在该变量声明之前的区域称之为死区,不能使用,若使用会报错。

function f1 () {
    console.log(num);
    // 声明以上全部为死区
    let num = 1;
}

4. 相同作用域不能有相同的变量名

否则会报错

5. do表达式

块级作用域就是以一个花括号中的语句,将多个操作封装起来,但是没有返回值。

因为在块级作用域中,外层作用域是不能使用内部变量,可以使用do表达式返回一个结果

let x = do {
    let t = 1;
}

这样变量x就能获取作用域变量t的值为1;

const

const声明的变量是只读一个常量,一旦声明就不能改变。因为不能改变也就得在声明的时候必须进行赋值,否则会报错。

具有的特点和let类似

  • 块级作用域,只能在当前作用域内使用
  • 变量不会自动提升
  • 具有暂时性死区
  • 在同一区域不能声明相同的变量名

const本质

const声明的变量并不是值不能改变,而是变量指向的那个内存地址是不能改变的,对于基本数据类型来说,内存地址存的是真实的值,所以对于基本数据来说声明后就不能更改。但是对于复杂数据类型来说内存地址保存的是一个指针,而指针指向的是真实的数据结构,所以只要指针不变,数据内容不管怎么变都行。

其实对于一个使用const声明的变量,假如想修改数组对象赋值成一个新对象时,按正常情况会报错,但是如果还是想赋值的话,可以使用Object.freeze()方法将对象冻结,只是冻结的是对象,如果要新增修改属性需要进一步将属性也冻结。

const foo = {};
// 冻结重新赋值为空对象
const foo = Object.freeze({});
// 常规模式下,不起作用
// 严格模式下,会报错
// 需要将对象的属性也冻结才能正常
foo.prop = 123;

将整个对象以及对象属性冻结

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

顶层对象的属性

在浏览器中的顶层对象指定是window对象,node中的顶层对象是global对象。

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

var a = 1;
console.log(window.a); // 1

但是window对象其实是指的是浏览器窗口对象,所以为了区别开,在ES6中规定,使用let、const声明的全局变量不等于顶层对象的属性,但是使用var声明的属性不变。


http://www.niftyadmin.cn/n/5066608.html

相关文章

Spring Boot 开发16个实用的技巧

当涉及到使用Spring Boot开发应用程序时,以下是16个实用的技巧: 1. **使用Spring Initializr**:Spring Initializr是一个快速创建Spring Boot项目的工具,可以帮助您选择项目依赖和生成项目骨架。 2. **自动配置**:Sp…

【Linux】Linux常用命令—文件管理(上)

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; &#x1f525;c系列专栏&#xff1a;C/C零基础到精通 &#x1f525; 给大…

Python 编程基础 | 第三章-数据类型 | 3.6、元组

一、元组 Python 的元组与列表类似&#xff0c;不同之处在于元组的元素不能修改。元组使用小括号&#xff0c;列表使用方括号。 1、创建元组 元组创建很简单&#xff0c;只需要在括号中添加元素&#xff0c;并使用逗号隔开即可&#xff0c;例如&#xff1a; tup1 (physics, ch…

微服务网关:Spring Cloud Zuul 升级 Spring Cloud Gateway 的核心要点

1. 服务路由 1.1. Zuul 接收请求&#xff1a; 在routes路由规则中&#xff0c;根据path去匹配&#xff0c;如果匹配中&#xff0c;就使用对应的路由规则进行请求转发如果无法从routes中匹配&#xff0c;则根据path用“/”去截取第一段作为服务名进行请求转发&#xff0c;转发…

maven 初学

1. maven 安装 配置安装 路径 maven 下载位置: D:\software\apache-maven-3.8.6 默认仓库位置: C:\Users\star-dream\.m2\repository 【已更改】 本地仓库设置为&#xff1a;D:\software\apache-maven-3.8.6\.m2\repository 镜像已更改为阿里云中央镜像仓库 <mirrors>…

【再识C进阶4】详细介绍自定义类型——结构体、枚举和联合

学习目标&#xff1a; 在上一篇博客中&#xff0c;我们已经详细地学习了字符分类函数、字符转换函数和内存函数。那这一篇博客和上一篇博客的关系不是那么相连。 这一篇博客主要介绍一下自定义类型&#xff0c;因为在解决实际问题时&#xff0c;由于世界上的因素有很多&#xf…

Postgresql 主从复制+主从切换(流复制)

pgsql有多种主从复制方式&#xff0c;推荐的是流复制 一、前置条件 1.至少两个pgsql数据库&#xff08;可以是一台设备上的两个&#xff09; 可以参考下面的教程 pgsql编译安装&#xff1a;pgsql 编译安装&#xff08;linux&#xff09; pgsql单机多开&#xff1a;pgsql 单机…