5.变量的解构赋值 - JS
什么是解构赋值
- 通过类似(或相同)的构型,将已知数据的元素/属性解构并提取出来,再赋值到相应变量,可以是新建的变量,也可以是已存在的变量/属性等;
- 最常见的是数组和对象的解构赋值,基本语法如下。
/* 绑定模式:变量同用一个声明let/const */
/* 数组 */
const [a, b] = array;
let [a, , b] = array;
const [a = aDefault, b] = array;
let [a, b, ...rest] = array;
const [a, , b, ...rest] = array;
let [a, b, ...{ pop, push }] = array;
const [a, b, ...[c, d]] = array;
/* 对象 */
const { a, b } = obj;
let { a: a1, b: b1 } = obj;
const { a: a1 = aDefault, b = bDefault } = obj;
let { a, b, ...rest } = obj;
const { a: a1, b: b1, ...rest } = obj;
let { [key]: a } = obj;/* 赋值模式:变量的声明各自独立 */
let a, b, a1, b1, c, d, rest;
let pop, push;
[a, b] = array;
[a, , b] = array;
[a = aDefault, b] = array;
[a, b, ...rest] = array;
[a, , b, ...rest] = array;
[a, b, ...{ pop, push }] = array;
[a, b, ...[c, d]] = array;({ a, b } = obj); // 必须加上 ()
({ a: a1, b: b1 } = obj);
({ a: a1 = aDefault, b = bDefault } = obj);
({ a, b, ...rest } = obj);
({ a: a1, b: b1, ...rest } = obj);
- 可以看到,声明和解构赋值在同一语句的是绑定模式;先声明再赋值的是赋值模式;
- 下面根据不同数据类型,进行语法总结。
数组的解构赋值
将可迭代对象解构,赋值给数组模式里对应位置上的变量。
基本语法
- 完全的模式匹配,构型完全一致;
let [a, b] = [1, 2];
let [a, [b, c], [d], e] = [1, [2, 3], [4], 5];
- 数据更多,只赋值指定位置;
let [a, b] = [1, 2, 3] // a=1,b=2
let [a, , b] = [1, 2, 3, 4] // a=1,b=3,跳过第二个位置
- 数据更少,多余的变量赋值为
undefined;
let [a, b, c] = [1, 2] // c=undefined
let [a, [b, c], d] = [1, [2]] // c=d=undefined
- 结合剩余参数,将剩余的数据作为数组赋值给最后一个变量;
let [a, ...rest] = [1, 2, 3, 4] // rest = [2, 3, 4]
let [a, , ...rest] = [1, 2, 3, 4] // rest = [3, 4]
let [a, [b, ...rest], c] = [1, [2, ], 3, 4] // rest = []
- 带默认值的解构赋值;
let [a=1] = [] // a=1
let [a=1] = [undefined] // a=1
let [a=1] = [null] // a=null
- *将前面变量用作后面变量的默认值。
let [x, y=x, z=2*x] = [1] // y=1,z=2
let [x, y=x] = [1, 10] // y=10
let [x=y, y] = [1, 10] // 这种写法易错、且没有太多意义,因为匹配是从左到右的
扩展部分
- 一个数据交换的便捷语法
[b, a] = [a, b]; - 一般的可迭代对象(
Map、Set、String等)都可以通过数组模式进行解构赋值; - *在函数参数列表中,起提取相应参数的作用,只有被提取的参数,后续会被传入函数。
let [a, b] = new Map([[1, 2], // a=[1,2][3, 4], // b=[3,4]
]);function* gen() {yield* [1, 2, 3]
}
let [x, y, z] = gen() // x=1,y=2,z=3function firstPlusThird([first, ,third]) { return first + third; }
firstPlusThird([1, 2, 10, 20]) // 11
注意事项
- 可以嵌套;
- 剩余参数必须在最后一个位置;
- 只有在没有匹配成功的时候,才会执行默认值的表达式;
- 数组模式的右端的期待值是可迭代对象;
- 不要将可能匹配失败的变量,作为默认值。
let [a, ...rest, b] = [1, 2, 3, 4] // 报错,剩余参数rest不能在中间
let [a=console.log(1)] = [1] // a=1且不会执行console.log(1)
let [a=console.log(1)] = [] // a=undefined且执行console.log(1)
let [x=y,y] = [] // 报错,y没有匹配到就赋值给x,x、y都没有声明成功
let [x, y] = 1 // 报错
let [x] = null // 报错
对象的解构赋值
解构对象的属性,给相同属性名的变量进行赋值;和数组模式不同的是属性没有次序,要根据属性名赋值。
基本语法
- 同名的属性(匹配成功->属性值赋值给对应变量) / 没有同名的属性(匹配失败->
undefined);
const employee = {id: 42,isAdmin: true,salary: '1.8w',
};
let { id, isAdmin } = employee; // id=42,isAdmin=true
let { isAdmin, id } = employee; // id=42,isAdmin=true
let { wage } = employee; // wage=undefined
- 将匹配到的属性赋值给其他名称的变量;
/*
* : 后的才是变量名
* : 前的是要匹配的属性名
*/
let { id:ID } = employee; // ID=42,没有id这个变量
let { salary:wage } = employee; // wage='1.8w'
- 带有默认值;
const employee2 = { }
let { id=1 } = employee; // id=42,匹配成功了
let { id=1 } = employee2; // id=1,匹配失败了
let { id:ID=1 } = employee; // ID=42,匹配成功了
let { id:ID=1 } = employee2; // ID=1,匹配失败了
- 嵌套;
const o = {done: false,materials: [ ['copper',], { obsidian: '3kg', granite: '10t' } ],rate: '0%',plus() { this.rate = 1 + +this.rate.slice(0, -1) + '%' }
}
let { materials: m } = o; // m=[ ['copper',], { obsidian: '3kg', granite: '10t' } ]
let { materials: [a, b] } = o; // a=['copper'],b={ obsidian: '3kg', granite: '10t' }
let { materials: [, { obsidian }] } // obsidian='3kg'
- 带有计算属性。
let employee3 = { id: 12,isAdmin: true
};
let x = 'id'
let { [x]: theId } = employee3 // theId=12
扩展部分
- 数组/字符串等基本数据类型是特殊的对象,有自己的属性(
length、0/1/…等索引),甚至原型链上的方法都可以赋值(尽管不能正常使用); - 还有一些内置对象,
Math、Date等一些好用的方法,可以独立使用的方法,都可以通过解构赋值的语法赋值给变量,使得调用更方便; - *在函数参数列表中,起提取相应参数的作用,只有被提取的参数,后续会被传入函数;
- 当解构一个对象时,如果属性本身没有被访问,它将沿着原型链继续查找,如上面第1点。
let { 0:firstPos, 1:secondPos, length:len, at } = [1, 2, 3, 4]
firstPos // 1
secondPos // 2
len // 4
at(0) // 报错,因为没有指向的对象,脱离了数组let { max, sin, PI:pi } = Math
max(1, 4, 2)// 4
sin(pi/2) // 1let user = { id: 32,name: 'Li Ming' }, user2 = {};
function getUserId({ id }) {return id;
}
getUserId(user) // 32
getUserId(user2) // undefined
注意事项
- 将属性赋值给其他名字的变量时,
:前的是属性名,不是建立的变量,也不会建立; {}可以没有变量;null、undefined不能解构的数据类型;- 先声明再赋值的情况,需要用
()包围。先声明后赋值模式的语句 +()。
let { x:y } = { x: 1 } // 将属性x 的值赋值给y,创建了变量y,没有创建变量x
let { a: 1 } = null // 报错
let { } = null // 报错
let { a: 1 } = undefined // 报错
let { } = undefined // 报错
let m;
{ m } = { m: 'M' } // 报错
({ m } = { m: 'M' }) // m=1
({} = { a: 1, b: 2 }) // 这样是允许的,尽管很怪
字符串的解构赋值
字符串既可以作为类数组,进行数组模式的解构赋值;也可以作为对象,进行对象的解构赋值。
let str = 'Hello';
let strArr;
/* 作为数组被解构 */
let [a, b, , ,c] = str; // a='H',b='e',c='o'
/* 作为对象被解构 */
let { length:n, 0:firstChar } // n=5,firstChar='H'
({ 0:strArr[0], [str.length-1]:strArr[1] } = str)
strArr // ['H', 'o']
函数参数的解构赋值
上面数组和对象的解构赋值,扩展部分提到过。在参数列表中做解构的类型一般就是数组和对象模式:
- 数组模式,根据位置上匹配数据,提取出来并进行指定传参;
- 对象模式,根据属性名匹配到属性值,提取出来并进行指定传参;
- 匹配失败,传
undefined。
let arr = [1, 2, 10, 20], obj = { value: 100 };
function getM([a, ,b], { value }) {return a + b > value ? a + b: value; // 取大
}getM(arr, obj) // 100
应用
- 简单地,交换变量的值;
- 从函数返回多个值;
- 函数的解构参数;
- 提取 JSON 数据;
- 等等等等。
function f() { return [1, 2, 3] }let [a, b, c] = f(); // a=1,b=2,c=3
相关文章:
5.变量的解构赋值 - JS
什么是解构赋值 通过类似(或相同)的构型,将已知数据的元素/属性解构并提取出来,再赋值到相应变量,可以是新建的变量,也可以是已存在的变量/属性等;最常见的是数组和对象的解构赋值,…...
tableau添加形状
目录 1.效果:1.自带的形状:2.添加形状:小结: 1.效果: 1.自带的形状: 2.添加形状: 找到tableau的安装目录,点入 默认->形状 的文件夹: 新建一个文件夹: …...
(2)(2.10) LTM telemetry
文章目录 前言 1 协议概述 2 配置 3 带FPV视频发射器的使用示例 4 使用TCM3105的FSK调制解调器示例 前言 轻量级 TeleMetry 协议 (LTM) 是一种单向通信协议(从飞行器下行的数据链路),可让你以低带宽/低波特率(通常为 2400 波…...
工具推荐系列-极客编辑器(实时在线编写md文件同步GitHub)
工具项目地址:https://github.com/geekeditor/geekeditor-desktop-releases/tree/main 工具基础配置方法:https://www.geekeditor.com/workspace1.x.html 详细同步代码仓的方法可以用下面: 如何创建GitHub仓库 及生成获取AccessToken…...
3d gaussian splatting介绍整理
3D 高斯分布是用于实时辐射场渲染的 3D 高斯分布中描述的一种光栅化技术,它允许实时渲染从小图像样本中学习到的逼真场景。 paper github 本文翻译整理自: blog: Introduction to 3D Gaussian Splatting DDPMs - Part 2 给出一些2D图片,用…...
[C#]de4dot常用命令
命令:de4dot.exe "D:\xxx.exe" 解释:运行后文件在程序集的目录下生成一个带-cleaned的新程序集。 命令:de4dot.exe file1 -f "D:\xxx.exe" -o "D:\output\xxx_cleaned.exe" 解释:-f : 指定.NET 程序…...
林浩然的“生命体验”大冒险
林浩然的“生命体验”大冒险 Lin Haoran’s “Life Experience” Grand Adventure 在一个阳光明媚的日子,林浩然——我们这位幽默风趣、充满生活智慧的大男孩,正坐在自家后院的老槐树下,手捧一本哲学书,皱着眉头深思:“…...
设计模式——职责链模式(Chain of Responsibility Pattern)
概述 职责链模式(Chain of Responsibility Pattern):避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接成一条链,并且沿着这条链传递请求,直到有对象处理它为止。职责链模式是一种对象行为…...
C++引用详解
顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、引用的概念 引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间…...
fMRI数据处理(随时更新)
要开始学习处理fMRI的数据了。 fMRI的数据一般有 dcm 格式和 nii 格式。 Nifti(Neuroimaging Informatics Technology Initiative,神经影像信息学技术倡议)文件格式,是目前各大神经影像分析工具普遍兼容的体素水平的数据格式&am…...
【Linux C | 网络编程】getsockname 和 getpeername函数详解及C语言例子
😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…...
研发日记,Matlab/Simulink避坑指南(六)——字节分割Bug
文章目录 前言 背景介绍 问题描述 分析排查 解决方案 总结归纳 前言 见《研发日记,Matlab/Simulink避坑指南(一)——Data Store Memory模块执行时序Bug》 见《研发日记,Matlab/Simulink避坑指南(二)——非对称数据溢出Bug》…...
(M)unity受伤反弹以及死亡动画
受伤反弹 1.在人物控制脚本中添加受伤后速度将为0,并添加一个反弹的力 在刷新移动时,需要在没有受伤的状态 public bool isHurt; public float hurtForce; private void FixedUpdate() {if(!isHurt)Move(); }public void GetHurt(Transform attacker) …...
【Java】Springboot入门
学习目标 基于SpringBoot框架的程序开发步骤 熟练使用SpringBoot配置信息修改服务器配置 基于SpringBoot的完成SSM整合项目开发 一、SpringBoot简介 1. 入门案例 问题导入 SpringMVC的HelloWord程序大家还记得吗? SpringBoot是由Pivotal团队提供的全新框架&…...
专业138总分420+中国科学技术大学843信号与系统考研经验中科大电子信息通信
**今年中科大专业课843信号与系统138分,总分420顺利上岸,梦圆中科大,也是报了高考失利的遗憾,总结一下自己的复习经历,希望可以给大家提供参考。**首先,中科大843包括信号与系统,和数字信号处理…...
携程开源 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX
携程开源 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX 官网文档 基于真实请求与数据的流量回放测试平台、自动化接口测试平台AREX 目前已跑通,通过冒烟测试,这篇文章稍稍水一下,主要讲下部署过程里踩的坑,因为…...
Android中C++层fstream用法详解
fstream用于读写文件内容 ifstream用于读文件内容 ofstream用于写内容到文件 读本文章前,请读一下C 文件和流 | 菜鸟教程 目录 1. 打开文件open 2. 返回当前指针位置tellg, tellp 3. 设置文件读位置指针seekg 4. 设置文件写位置指针seekp 5. 如何在文件…...
git clone常见问题一览及解决方法
在使用Ubuntu下,终端运行git clone命令时会遇见许多问题,本文主要针对一些常见的问题进行整理。关于换源问题,推荐使用小鱼的一键换源。 1.git clone 速度过慢 1.1 魔法 这个方法不做过多赘述,ubuntu下个人使用发现体验良好&am…...
ArcGIS Pro 如何批量删除字段
在某些时候,我们得到的图层属性表内可能会有很多不需要的字段,如果挨个去删除会十分的麻烦,对于这种情况,我们可以使用工具箱内的字段删除工具批量删除,这里为大家介绍一下使用方法,希望能对你有所帮助。 …...
OG Trade在ZKX揭幕:一家基于Starknet的游戏化永续合约交易所
ZKX的 OG Trade通过内置游戏化和30分钟交易竞赛,为所有交易者创造机会,革新了永续合约交易模式。 2024年1月30日 — ZKX宣布推出OG Trade,这是一家基于Starknet的游戏化永续合约交易所,旨在满足短期交易者、高水平交易者和波段交易…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
