探索如何赋予对象迭代魔法,轻松实现非传统解构赋值的艺术

前言

今天下午在网上冲浪过程中看到这样一个问题
面试题:如何让 var [a, b] = {a: 1, b: 2} 解构赋值成功?
据说是某大厂面试题,于是我学习了一下这个问题,写下这篇文章记录一下。

学习过程

要想解决这个问题首先要知道什么是解构赋值。
解构赋值是ES6中一种将数组或对象的属性/元素值赋给变量的语法。

运行一下题目的代码得到下面的情况
在这里插入图片描述

原因是对象的解构赋值需要使用对应的属性名来匹配,而不是数组的形式。
比如var {a, b} = {a: 1, b: 2} 就可以成功实现结构赋值。
但是这么高贵的问题,你10秒就回答完了,回去等通知吧。

两个普通想法

  1. 将对象属性解构到数组变量中
    首先使用Object.keys获取对象的所有键,然后使用map方法根据这些键从对象中提取对应的值,最后将这些值解构到一个数组变量中。
        var arr = [a, b];var obj = { a: 1, b: 2 }// 获取对象的键数组var keys = Object.keys(obj)// 根据键获取对应的值var values = keys.map(key => obj[key])//数组解构赋值var [a, b] = values;console.log([a, b])

在这里插入图片描述

  1. 将数组元素解构到对象变量中
    创建了一个空对象obj,然后使用数组解构赋值直接将数组的元素赋值给对象的属性。
        var arr = [1, 2];var obj = {};[obj.a, obj.b] = arr; // 数组解构赋值到对象属性console.log(obj); // 输出: {a: 1, b: 2}

在这里插入图片描述

高级解法

在JavaScript中数据是具有迭代器属性的一种数据结构,而对象是不具有迭代器的一种数据结构。
最直白淳朴的想法,解构赋值成功只需要把右边也变成可以迭代的对象就可以了。
在 JavaScript 中,可迭代对象是指具有 Symbol.iterator 方法的对象。这个方法返回一个迭代器(Iterator)对象,它通过 next() 方法提供对可迭代对象中的每个元素的访问。
JavaScript中数组,Set,Map,字符串都是可以迭代的对象,任何有iterator接口的对象都是可迭代的,我们可以自定义一个有iterator接口的对象。
网友做法

Object.prototype[Symbol.iterator] = function(){// 使用 Object.values(this) 方法获取对象的所有值,并返回这些值的迭代器对象return Object.values(this)[Symbol.iterator]()
}

这段代码是将 Object.prototype 上的 [Symbol.iterator] 方法重新定义为一个新的函数。新的函数通过调用 Object.values(this) 方法获取对象的所有值,并返回这些值的迭代器对象。

        Object.prototype[Symbol.iterator] = function () {return Object.values(this)[Symbol.iterator]()}var [a, b] = { a: 1, b: 2 }console.log([a, b])

给Object对象原型添加迭代器属性之后成功实现var [a, b] = { a: 1, b: 2 }解构赋值
在这里插入图片描述

题目拓展

上面通过给Object对象原型添加迭代器属性返回对象的值实现var [a, b] = { a: 1, b: 2 }解构赋值,但是若题目改为var [a, b] = { b: 1, z: 4 },会出现key不对应导致的问题。
运行下面的代码

Object.prototype[Symbol.iterator] = function () {return Object.values(this)[Symbol.iterator]()}var [a, b] = { b: 1, z: 4 };console.log([a, b])

运行结果如图
在这里插入图片描述

输出结果a应该是undefined,b:1,但是实际结果仍旧是a:1,b:4。
只是将{ b: 1, z: 4 }转成数组之后直接赋值,但是没有考虑到key的对应关系

最终优化结果

生成器函数function* () {}定义了一个迭代器生成器。当该迭代器被调用时,它会返回一个可迭代对象,并且通过yield*语句将对象的值作为迭代器的值逐个产生出来。为了在解构赋值时考虑到对象键的对应关系,我们需要修改迭代器函数,使其按照对象的键顺序来生成值。我们可以使用Object.entries方法来获取对象的键值对数组,然后按照这个顺序来生成值。

        Object.prototype[Symbol.iterator] = function* () {let entries = Object.entries(this); // 获取对象的键值对数组let arr = ['a', 'b']; // 假设这是我们关心的键的数组for (let entry of entries) {let key = entry[0]; // 获取键if (arr.includes(key)) { // 检查键是否在数组中yield entry[1]; // 如果键在数组中,则生成对应的值}}};// 使用数组解构赋值var [a, b] = { a: 1, z: 2, c: 3 }; // 这里我们只关心键 'a'console.log([a, b]);

在这里插入图片描述

首先给Object.prototype添加了一个自定义的迭代器,它使用Object.entries来获取对象的键值对数组,并按照这个数组的顺序来生成值。然后使用数组解构赋值来尝试解构一个对象,但是由于对象的键顺序是’b’, ‘z’,而我们只关心值’1’,所以变量a被赋值为’1’,而变量b因为没有对应的值而被赋值为undefined。


总结一下代码的步骤就是

  1. 添加迭代器: 通过给Object.prototype添加一个名为Symbol.iterator的方法,所有的对象都可以被迭代。
  2. 定义关心的键: 在迭代器内部定义一个数组arr其中包含迭代过程中关心的键名。
  3. 迭代对象属性: 使用Object.entries(this)获取对象的键值对数组,这里的this指的是调用迭代器的对象。
  4. 过滤属性: 在遍历键值对数组时,我们检查每个键是否在我们关心的键数组arr中。如果键存在,我们才生成对应的值。
  5. 解构赋值: 使用数组解构赋值来提取我们关心的键对应的值。由于迭代器已经过滤掉了不需要的属性,解构赋值只会得到我们想要的值。

额外的小问题:为什么上面的代码中是 let arr = [‘a’, ‘b’];不是let arr = [a, b]?

let arr = [a, b]是错误的,在声明arr数组的时候,变量a,b没有定义,没有具体的值不能用来初始化数组。
错误的运行结果是a is not defined

总结

本文解决如何让 var [a, b] = {a: 1, b: 2} 解构赋值成功的问题的最佳实践大概是通过扩展Object.prototype来为所有对象添加一个自定义的迭代器,该迭代器允许我们以一种特定的方式遍历对象的属性。具体来说,这个迭代器会过滤掉我们不关心的属性,只返回我们指定键名对应的属性值。

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

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

相关文章

概率论与数理统计_上_科学出版社

contents 前言第1章 事件与概率1.1 随机事件与样本空间1.1.1 样本空间1.1.2 随机事件1.1.3 事件之间的关系与运算 1.2 概率的三种定义及其性质1.2.1 概率的统计定义1.2.2 概率的古典定义1.2.3 概率的几何定义1.2.4 概率的性质 1.3 常用概型公式1.3.1 条件概率计算公式1.3.2 乘法…

百日筑基第十一天-看看SpringBoot

百日筑基第十一天-看看SpringBoot 创建项目 Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下: https://start.spring.io/ 打开后的界面如下: 可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导&#xff…

【数智化人物展】数势科技创始人兼CEO黎科峰:数智化时代To B软件行业面临颠覆与重塑...

黎科峰 本文由数势科技创始人兼CEO黎科峰投递并参与由数据猿联合上海大数据联盟共同推出的《2024中国数智化转型升级先锋人物》榜单/奖项评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 2020年,对我而言,是职业生涯中的一个重大转折点。在全球新…

频域信号通过逆傅里叶变换恢复成时域信号

频域信号通过逆傅里叶变换恢复成时域信号 flyfish import numpy as np import matplotlib.pyplot as plt from scipy.fftpack import fft, ifft plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False# 设置参数 t np.linspace(0, 1, 1000, en…

Simulink中示波器连续运行的方法

1.在Simulink中,经常要使用到示波器,默认示波器是定时运行的,只能观察到一小部分运行的波形;实际调试过程中,经常要连续运行,因此,需要设置示波器为连续运行模式,下面将介绍示波器连续运行的方法。 打开Simulink仿真软件,找到仿真设置按钮,点击设置: 2.将其停止时间…

音频流格式启用数据流

音频流格式启用数据流 音频流格式启用数据流使用 AudioStreamBasicDescription 结构在哪里以及如何设置流格式 音频流格式启用数据流 在单个样本帧级别处理音频数据时,就像使用音频单元一样,仅仅指定正确的数据类型来表示音频是不够的。单个音频样本值中…

HandlerMethodArgumentResolver :深入spring mvc参数解析机制

❃博主首页 &#xff1a; <码到三十五> ☠博主专栏 &#xff1a; <mysql高手> <elasticsearch高手> <源码解读> <java核心> <面试攻关> ♝博主的话 &#xff1a; 搬的每块砖&#xff0c;皆为峰峦之基&#xff1b;公众号搜索(码到三十…

编程新纪元:AI辅助工具豆包Marscode体验

自从ChatGPT带动全球AI热潮&#xff0c;AI席卷着各行各业。编程界也不例外&#xff0c;早期做过了Github Copilot、阿里的通义灵码等AI编程插件的体验 p.s.以上的下载量与评分均只是plugins.jetbrains的marketplace数据&#xff0c;仅供参考 基本AI编程工具的功能都差不多&…

自然语言处理学习(3)RNN 模型学习---NLP领域的第一个模型

一 基本定义 视频链接 1.小案例理解–语义理解 目的&#xff1a;输入一句话&#xff0c;机器需要理解这句话的语义 二. RNN模型分类 1. 按照输入输出分类 (1) N Vs N (2) N Vs 1 (3) 1 VsN (4) seq2seq 三 传统RNN模型 1. 内部结构分析 &#xff08;a) 总体外…

基于单片机的多功能电子时钟的设计

摘要&#xff1a;提出了一种基于单片机的多功能电子时钟的设计方法&#xff0c;以 AT89C52单片机作为系统的主控芯片&#xff0c;采用DS1302作为时钟控制芯片&#xff0c;实现日期时钟显示并且提供精准定时的功能。此外&#xff0c;还可经由DHT22所构成的温湿度传感电路&#x…

Kafka集群部署(手把手部署图文详细版)

1.1.1 部署zookpeer 在node02下载并解压zookeeper软件包 cd /usr/local wget https://archive.apache.org/dist/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz 或者&#xff1a;scp cat192.168.28.100:/home/cat/zookeeper-3.4.6.tar.gz /tmp&#xff08;注意目录&#xf…

vue属性绑定v-bind

属性绑定v-bind 双大括号不能在HTML attributes 中使用。想要响应式地绑定一个attribute&#xff0c;应该使用v-bind指令。 v-bind 指令指示Vue将元素id attribute 与组件的dyid属性保持一致。如果绑定值是null或者undefined&#xff0c;那么该attribute将会从渲染的元素上移…

昇思第9天

LSTMCRF序列标注 序列标注&#xff1a;对序列进行标注&#xff0c;实际上是对序列中每个Token进行标签预测&#xff0c;可以直接视作简单的多分类问题。但是序列标注不仅仅需要对单个Token进行分类预测&#xff0c;同时相邻Token直接有关联关系&#xff0c;需要引入一种能够学…

docker介绍与详细安装

1 docker 介绍 1.1 虚拟化 在计算机中&#xff0c;虚拟化&#xff08;英语&#xff1a;Virtualization&#xff09;是一种资源管理技术&#xff0c;是将计算机的各种实体资源&#xff0c;如服务器、网络、内存及存储等&#xff0c;予以抽象、转换后呈现出来&#xff0c;打破实…

【BUUCTF-PWN】12-get_started_3dsctf_2016

32位&#xff0c;开启了NX保护 执行效果&#xff1a; main函数&#xff1a; 其中gets()函数存在栈溢出&#xff0c;溢出距离为0x38&#xff0c;这里是使用的esp寻址&#xff0c;属于外平栈&#xff0c;不需要覆盖ebp的四个字节。而之前做的题一般都是ebp寻址&#xff0c;…

开发国际短剧系统的策略解析

一、明确项目目标和需求 1、功能需求&#xff1a;确定系统应具备的基本功能&#xff0c;如用户注册、登录、浏览短剧、评论、分享、个性化推荐等。 2、性能需求&#xff1a;确保系统能够承受高并发访问&#xff0c;保证视频流畅播放&#xff0c;减少卡顿和延迟。 3、跨文化传播…

MCU中如何利用串口通信,增加AT指令框架

第一步&#xff0c;通过串口与PC端建立通信第二步&#xff0c;根据PC端发来的AT指令&#xff0c;MCU执行相应代码 主要是解析PC端发来的字符串&#xff0c;也就是获取字符串、处理字符串、以及分析字符串。 1. 串口通信 用到的是DMA串口通信&#xff0c;收发字符串数据时&…

如何使用 3D 建模库在 C# 中将 3DS 转换为 USDZ?

USDZ/USD是一种 3D 文件格式&#xff0c;被广泛用于跨平台共享 3D 资产。另一方面&#xff0c;3DS是另一种以块形式存储数据的 3D 文件格式。在某些情况下&#xff0c;您需要将3DS 文件转换为 USDZ/USD文件格式。因此&#xff0c;本篇博文介绍了一个功能丰富的3D 建模库&#x…

【基于R语言群体遗传学】-6-表型计算等位基因频率、最大似然估计方法

到目前为止&#xff0c;我们主要讨论了等位基因和基因型频率&#xff0c;以及我们如何可以从一个推断出另一个。但是&#xff0c;如果我们不知道等位基因频率&#xff0c;只知道种群中存在哪些表型呢&#xff1f;如果我们足够幸运&#xff0c;知道哪些表型对应哪些基因型&#…

一键安装部署,在 Ubuntu 服务器上快速搭建基于 Ghost CMS的网站

我们在上一篇内容中讲过&#xff0c;如何使用 Helm 在 Kubernetes 集群上安装 WordPress&#xff0c;创建高可用性网站。而这次我们将基于另一个流行的内容管理系统 Ghost CMS 在 DigitalOcean 云主机进行建站。 Ghost 也是开源的内容管理系统&#xff08;CMS&#xff09;&…