ES6中变量解构赋值

数组的解构赋值

ES6规定以一定模式从数组、对象中提取值,然后给变量赋值叫做解构。

本质上就是一种匹配模式,等号两边模式相同,左边的变量就能对应的值。

假如解构不成功会赋值为undefined。

不需要匹配的位置可以置空

let [ a, b, c] = [1, 2, 3];
// a = 1
// b = 2
// c = 3let [, , d] = [1, 2, 3];
// d = 3

1. 不完全解构

指的是左侧只能匹配右侧一部分模式,这种情况叫做不完全解构。

let [x, y] = [1, 2, 3];
// x = 1; y = 2

2. 等号右侧不是数组

如果等于右侧不是数组会报错

let [foo] = 1; // 报错
let [foo] = true; // 报错

在执行时会先转化,其实只要数据结构具有Iterator接口,都能解构。

3. 嵌套解构

4. 默认值

解构时可以设置一个默认值,假如解构不成功时可以使用默认值,否则会报错。

只有解构时值为undefined,才会使用默认值。

let [ x = 1] = [];
// x = 1

这里结构变量x时,不存在但是给定默认值为1。

let [x, y = 1] = ['a'];
// x = 'a' y = 1let [x = 1] = [undefined];
// x = 1let [x = 1] = [null];
// x = 1

默认值也可以是表达式、其他变量

如果是表达式,只有使用时才会进行计算求值,否则不会主动计算。

function foo() {return 2;   
}
let [x = foo()] = [1]; // 1
let [x = foo()] = [undefined]; // 2

第一个解构时不会执行foo函数,因为解构能成功,第二个解构的值为undefined,所以会执行foo函数。

对于其他变量,必须保证变量是已经存在的。

let [x = 1, y = x] = []; // x = 1; y = 1
let [x = 1, y = x] = [2]; // x = 2; y = 2
let [x = 1, y = x] = [2, 3]; // x = 2; y = 3
let [x = y, y = 1] = []; // 报错

最后一个会报错是因为,y还没有声明呢,就直接使用了。

对象的解构赋值

对象的解构不必像数组那样按顺序排列,只要变量与属性名一致就能获取到值,对于取不到值的会被赋值为undefined。

let { foo, bar } = { foo: 'a', bar: 'b'};
// foo = 'a'; bar = 'b'let { baz } =  { foo: 'a', bar: 'b'};
// baz = undefined 不存在

对于属性名不一致可以使用冒号连接,冒号左边表示匹配的模式,这个模式要与解构的对象的属性名一致,冒号有侧就是自定义的变量名。

对象的解构本质就是通过冒号,左侧进行查找,右侧被真正赋值,只不过平时左侧、右侧名称一致,简写了而已。

let { foo: baz } = { foo: 'a', bar: 'b'};
// baz = 'a'

1. 嵌套解构

let obj = {p: ['hello', { y: 'world'}]
}
let { p: [x, {y}]} = obj;
// x = 'hello'
// y = 'world'

这里的p是匹配模式,并不是变量

2. 默认值

只有对象的属性值为undefined时,默认值才能生效。

let { x = 3 } = {};
// x = 3

对象的解构赋值可以很方便地将现有对象的方法赋值给某个变量。

let { log, sin, cos } = Math; 

数组是特殊的对象,可以对数组进行对象属性结构,以数组的index。

let arr = [1, 2, 3];
let { 0: first, [arr.length - 1 ]:last } = arr;
// first = 1; last = 3

字符串的解构赋值

字符串也能解构,也解构成一个类似数组的对象。

不需要匹配的位置可以置空

let [a, b] = 'world';
// a = 'w'; b = 'o'let [a, , b] = 'world';
// a = 'w'; b = 'r'

类似数组的对象都有一个length属性,所以可以对length属性进行解构

let { length: len } = 'hello';
// len = 5

数值和布尔类型解构

解构赋值时,等号右侧只要不是对象或者数组,就会先转为对象

let { toString: s } = 123;
s === Number.prototype.toString // true

函数参数的解构

函数的参数也能进行解构,也能使用默认值。

function add ({x, y}) {return x + y;
}
add(1, 2); // 3function boo({x = 1, y = 2}) {return x + y;
}
add()

括号问题

正常解构是声明变量并且赋值,假如说变量已经声明成功,直接赋值,这时需要有所注意。

解构赋值虽然很方便,但是解析起来不容易。对于编译器来说,一个式子到底是模式还是表达式,没有办法从一开始就知道,必须解析到(或者解析不到)等号才知道,所以ES6规定,为了不导致歧义,不要使用圆括号。

let x;
{x} = {x:1};
// 报错

因为js会把{x}当做一个代码块,而不是变量,从而发生语法错误。

1. 不能使用圆括号的情况

  • 变量声明语句

会导致全部报错


let [ (a) ] = [1];
let { x: (c) } = {};
let ({ x: c }) = {};
let { (x: c) } = {};
let { (x): c } = {};let { o: ({ p:p }) } = { o: { p: 2 } };
  • 函数参数

函数的参数属于变量声明,不能使用圆括号

function f([(z)]) {return z;
}
  • 赋值语句的模式
({ p:a }) = { p: 42 };
([a]) = [5];
[({ p: a }), {x: c }] = [{}, {}];

不管是一部分模式还是全部模式都放在括号里面,都会报错。

2. 可以使用圆括号

赋值语句的非模式部分可以使用圆括号

[(b)] = [3];
({ p: (d) } = {});
[(parseInt.prop)] = [3];

用途

交换变量的值

let x = 1;
let y = 2;
[x, y] = [y, x];
// x = 2; y = 1

从函数返回多个值

函数只能返回一个值,如果真要返回多个只能放在数组和对象中,但是使用解构赋值就很方便。


function example() {return [1, 2, 3];
}
let [a, b, c] = example();

函数参数的定义

解构赋值可以方便地将一组参数与变量名对应起来。

// 参数是一组有次序的值
function f([x, y, z]) {}
f([1, 2, 3]);
// 参数是一组无次序的值
function f([x, y, z]) {}
f([z: 1, y: 2, x: 3]);

提取JSON数据

函数参数的默认值

在之前函数要是有默认值时,需要加判断,很不方便。

之前的

function foo(x) {var y;if(x != undefined) {y = '默认值';}y = x;
}
foo();

现在直接使用解构赋值,添加默认值就可以

function foo(x = '默认值') {}
foo();

变量Map解构

任何部署了Iterator接口的对象都可以使用for…of循环遍历,Map结构原生支持Iterator接口,因此配合变量的解构赋值获取键名和键值很方便。

var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {console.log(`${key} is ${value}`);
}
// first is helllo
// second is world

获取键名

for(let [key] of map) {// ...
}

获取键值

for (let [, value] of map) {// ...
}

输入模块的指定方法

加载模块时,汪汪需要指定输入的方法,则使用解构赋值使输入语句清晰

// 现在
const { SourceMapConsumer, SourceNode } = require('source-map');// 之前
const sourceMap = require('source-map');
const SourceMapConsumer = sourceMap.SourceMapConsumer();
const SourceNode = sourceMap.SourceNode();

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

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

相关文章

Nginx高级 第一部分:扩容

Nginx高级 第一部分:扩容 通过扩容提升整体吞吐量 1.单机垂直扩容:硬件资源增加 云服务资源增加 整机:IBM、浪潮、DELL、HP等 CPU/主板:更新到主流 网卡:10G/40G网卡 磁盘:SAS(SCSI) HDD(机械…

十天学完基础数据结构-第二天(数据结构简介)

什么是数据结构? 在计算机科学中,数据结构是一种组织和存储数据的方式。它定义了数据的布局,以及对这些数据执行的操作。你可以把数据结构看作是计算机内存中的特定组织方式,就像图书馆中书籍的排列一样。 数据结构可以是各种形…

python获取时间戳

使用 datetime 库获取时间。 获取当前时间: import datetime print(datetime.datetime.now()) . 后面的是微秒,也是一个时间单位,1秒1000000微秒。 转为时间戳: import datetimedate datetime.datetime.now() timestamp date…

【数据结构】堆的应用-----TopK问题

目录 一、前言 二、Top-k问题 💦解法一:暴力排序 💦解法二:建立N个数的堆 💦解法三:建立K个数的堆(最优解) 三、完整代码和视图 四、共勉 一、前言 在之前的文章中&#xff…

Springboot场景开发多面手

LinkedBear ,资深 Java 高级工程师,底层技术研究者与分享者,倾心研究 Spring 技术体系多年,对 Spring、Spring Boot 、SpringCloud 等框架有独到的见解,拥有丰富的框架体系实践经验和架构封装经验。善于总结、输出&…

CharacterEncodingFilter的用法

CharacterEncoding是SpringMVC提供的一个一个过滤器,用于设置请求和响应的字符编码,解决乱码问题,他本身是一个过滤器 那么在SpringBoot中,CharacterEncoding就有一个很好的秒用 setEncoding("UTF-8")设置编码 setForceEncoding(true) 设置请求和响应编码 还需要在配…

leetcode做题笔记160. 相交链表

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节点 c1 开始相交: 题目数据 保证 整个链式结构中不存在环。 注意,函数返回结果后&…

计算机视觉——飞桨深度学习实战-深度学习网络模型

深度学习网络模型的整体架构主要数据集、模型组网以及学习优化过程三部分,本章主要围绕着深度学习网络模型的算法架构、常见模型展开了详细介绍,从经典的深度学习网络模型以CNN、RNN为代表,到为了解决显存不足、实时性不够等问题的轻量化网络…

Day-05 CentOS7.5 安装docker

参考 : Install Docker Engine on CentOS | Docker DocsLearn how to install Docker Engine on CentOS. These instructions cover the different installation methods, how to uninstall, and next steps.https://docs.docker.com/engine/install/centos/ Doc…

计算机网络 第二章物理层

计算机网络第二章知识点速刷 其中重要的是信源和信宿,以及调制解调器在通信模型当中起到的作用。 单工、半双工和全双工。

【Java 进阶篇】JDBC 数据库连接池详解

数据库连接池是数据库连接的管理和复用工具,它可以有效地降低数据库连接和断开连接的开销,提高了数据库访问的性能和效率。在 Java 中,JDBC 数据库连接池是一个常见的实现方式,本文将详细介绍 JDBC 数据库连接池的使用和原理。 1…

计组——I/O方式

一、程序查询方式 CPU不断轮询检查I/O控制器中“状态寄存器”,检测到状态为“已完成”之后,再从数据寄存器取出输入数据。 过程: 1.CPU执行初始化程序,并预置传送参数;设置计数器、设置数据首地址。 2. 向I/O接口发…

腾讯云服务器选购指南:如何选择一台合适的云服务器配置?

腾讯云服务器配置如何选择?CPU内存、带宽和系统盘怎么选择合适?个人用户可以选择轻量应用服务器,企业用户可以选择云服务器CVM,2核2G3M带宽轻量服务器95元一年、2核4G5M服务器168元一年,企业用户可以选择标准型S5云服务…

1300*C. Rumor(并查集贪心)

解析&#xff1a; 并查集&#xff0c;求每个集合的最小费用。 每次合并集合的时候&#xff0c;根节点保存当前集合最小的费用。 #include<bits/stdc.h> using namespace std; #define int long long const int N1e55; int n,m,a[N],p[N],cnt[N]; int find(int x){retur…

分布式锁:四种方案解决商品超卖的方案

一 分布式锁 1.1 分布式锁的作用 在多线程高并发场景下&#xff0c;为了保证资源的线程安全问题&#xff0c;jdk为我们提供了synchronized关键字和ReentrantLock可重入锁&#xff0c;但是它们只能保证一个工程内的线程安全。在分布式集群、微服务、云原生横行的当下&#xff…

深度学习笔记_4、CNN卷积神经网络+全连接神经网络解决MNIST数据

1、首先&#xff0c;导入所需的库和模块&#xff0c;包括NumPy、PyTorch、MNIST数据集、数据处理工具、模型层、优化器、损失函数、混淆矩阵、绘图工具以及数据处理工具。 import numpy as np import torch from torchvision.datasets import mnist import torchvision.transf…

uniapp 实现下拉筛选框 二次开发定制

前言 最近又收到了一个需求&#xff0c;需要在uniapp 小程序上做一个下拉筛选框&#xff0c;然后找了一下插件市场&#xff0c;确实有找到&#xff0c;但不过他不支持搜索&#xff0c;于是乎&#xff0c;我就自动动手&#xff0c;进行了二开定制&#xff0c;站在巨人的肩膀上&…

归并排序及其非递归实现

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 目录 归并排序递归实现 归并排序非递归实现 归并排序递归实现 图示&#xff1a; 代码&#xff1a; 先分再归并&#xff0c;像是后序一般。 //归并排序 void MergeSort(int* arr, int left, int right) {int* temp (int…

tcp滑动窗口原理

18.1 滑动窗口 我们再来看这个比喻&#xff1a; 网络仅仅是保证了整个网络的连通性&#xff0c;我们我们基于整个网络去传输&#xff0c;那么是不是我想发送多少数据就发送多少数据呢&#xff1f;如果是这样的话&#xff0c;是不是就会像我们的从一个池塘抽水去灌到另外一个…

速看:免费领取4台阿里云服务器_申请入口及领取流程

注册阿里云账号&#xff0c;免费领云服务器&#xff0c;最高领取4台云服务器&#xff0c;每月750小时&#xff0c;3个月免费试用时长&#xff0c;可快速搭建网站/小程序&#xff0c;部署开发环境&#xff0c;开发多种企业应用。阿里云服务器网分享阿里云服务器免费领取入口、免…