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

news2024/10/6 6:18:13

前言

今天下午在网上冲浪过程中看到这样一个问题
面试题:如何让 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.coloradmin.cn/o/1895629.html

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

相关文章

nginx安装升级修复HTTP头信息泄露Nginx版本信息漏洞(并保持https配置)

文章目录 1. 准备工作2. 修改web服务器所使用的nginx的名称和版本信息2.1 修改以下三个文件:(1) src/core目录下的nginx.h文件(2) src/http目录下的ngx_http_header_filter_module.c文件(3) src/http目录下的ngx_http_special_response.c文件 2.2 重新编译nginx2.3 …

Spring框架的学习前言

1.注意事项 1.在接下来的学习中我们会将jdk的版本升级到17。 2.引入maven仓库用来存储依赖 3.在后面的javaSpring框架中要第一个项目的创建要选javaweb和lombook这两个依赖 2.Maven的主要功能 (1)maven的主要功能是引入依赖和管理依赖,在…

第7章:Electron文件系统操作(2)

7.2 文件对话框 Electron 提供了 dialog 模块用于显示文件打开和保存对话框。 7.2.1 显示文件打开对话框 主进程代码: const { app, BrowserWindow, ipcMain, dialog } require(electron); const path require(path);let mainWindow;const createMainWindow …

【Ubuntu】详细说说Parallels DeskTop安装和使用Ubuntu系统

希望文章能给到你启发和灵感~ 如果觉得文章对你有帮助的话,点赞 + 关注+ 收藏 支持一下博主吧~ 阅读指南 开篇说明一、基础环境说明1.1 硬件环境1.2 软件环境二、Ubuntu系统的使用2.1 系统的下载2.2 系统的安装2.3 安装桌面版(可选)2.3.1 安装/更新apt2.3.2 安装桌面版2.3…

4.通过制作trackbar控件了解3原色在opencv的应用-cnblog

通过制作trackbar控件了解3原色在opencv的应用 什么是3原色 一张彩色图片通常是由三种基本颜色,即红色、绿色和蓝色(通常称为RGB)的混合组成的。这三种颜色以不同的比例混合可以产生几乎所有其他颜色。在数字图像中,每个像素通常…

找不到msvcr110.dll是怎么回事?彻底解决msvcr110.dll丢失的方法

当您的电脑提示遇到msvcr110.dll丢失时,您知道如何解决此问题吗?事实上,解决此类dll文件丢失的问题相对较为简单。只要我们深入了解msvcr110.dll丢失的具体情况,便可轻松解决此问题。以下为您介绍msvcr110.dll修复方法。 一&#…

算法库应用-顺序串(串比较)

学习贺利坚老师博客 数据结构例程——串的顺序存储应用_使用顺序串存储身份证号-CSDN博客 本人详细解析博客 串的顺序存储结构应用_(1)假设串采用顺序串存储,设计一个算法程序,按顺序比较两个串s和t的大小。请-CSDN博客 版本日志 V1.0: 利用顺序串, 进行简单的判断比较, 也算是…

某DingTalk企典 - Token

⚠️前言⚠️ 本文仅用于学术交流。 学习探讨逆向知识,欢迎私信共享学习心得。 如有侵权,联系博主删除。 请勿商用,否则后果自负。 网址 aHR0cHM6Ly9kaW5ndGFsay5jb20vcWlkaWFuLw 浅聊一下 没毛病,就这字段,有效期…

【前端CSS3】CSS显示模式(黑马程序员)

文章目录 一、前言🚀🚀🚀二、CSS元素显示模式:☀️☀️☀️2.1 什么是元素显示模式2.2 块元素2.3 行内元素2.4 行块元素2.5 元素显示模式的转换 三、总结🚀🚀🚀 一、前言🚀&#x1f…

小程序 npm 支持

使用 npm 包 目前小程序已经支持使用 npm 安装第三方包,因为 node_modules 目录中的包不会参与小程序项目的编译、 上传和打包,因此在小程序 项目中要使用的 npm 包,必须走一遍构建 npm 的过程。在构建成功以后,默认 会在小程序目…

015-GeoGebra基础篇-定点旋转物体、动态显示数值并显示运动轨迹

这可能是我能想到的最大概率可以被你搜索到的标题了,容我先喘口气~ 目录 一、成品展示二、涉及内容三、做图步骤(1)绘制三角形t(2)建立定点D(3)制作角度滑动条(4)图形绕点…

如何利用AI撰写短文案获客?分享6大平台和3大步骤!

从去年开始,很多大厂都在裁员,原因就是因为AI的火爆,替代了很多机械式的劳动力。以前很多人可以通过机械式的工作来摸鱼,现在AI完成的效率比人工的要高很多倍。 国内好用的AI平台非常多,有时候也可以使用几个AI平台结合…

线程(基础概念)

文章目录 一、线程和进程?二、线程初识2.1 线程属性2.2 线程的调度策略2.3 线程的优先级2.3 线程实验 一、线程和进程? 我们经常描述进程(process)和线程(thread): 进程是资源管理的最小单位&a…

每天五分钟深度学习框架pytorch:tensor向量的统计函数的运算

本文重点 给定一个向量,我们如何才能获取到这个向量中重要的那部分呢?比如均值,最大值等等,我们可以使用pytorch中已经封装好的方法来完成这些任务。 常用的统计方法 L1范式 L1范式就是将向量中所有元素的绝对值相加求和,以上是对a、b、c三个向量求L1范式,都是8 L2范数…

GEE计算遥感生态指数RSEI

目录 RESI湿度绿度热度干度源代码归一化函数代码解释整体的代码功能解释:导出RSEI计算结果参考文献RESI RSEI = f (Greenness,Wetness,Heat,Dryness)其遥感定义为: RSEI = f (VI,Wet,LST,SI)式中:Greenness 为绿度;Wetness 为湿度;Thermal为热度;Dryness 为干度;VI 为植被指数…

QT5.12环境搭建与源码编译

一、概述 QT版本:QT5.12.10 Qt网址:http://download.qt.io/archive/qt/ 编译平台 ubuntu18.04 二、安装交叉编译工具链 1、获取交叉编译工具链 一般如果是编译系统如果有对应的gcc 就是用这个就可以了 比如rk3128 lin…

校园失物招领系统带万字文档java项目失物招领管理系统java课程设计java毕业设计springboot vue

文章目录 校园失物招领系统一、项目演示二、项目介绍三、万字字项目文档四、部分功能截图五、部分代码展示六、底部获取项目源码带万字文档(9.9¥带走) 校园失物招领系统 一、项目演示 校园失物招领系统 二、项目介绍 语言: Java 数据库&…

【WebRTC实现点对点视频通话】

介绍 WebRTC (Web Real-Time Communications) 是一个实时通讯技术,也是实时音视频技术的标准和框架。简单来说WebRTC是一个集大成的实时音视频技术集,包含了各种客户端api、音视频编/解码lib、流媒体传输协议、回声消除、安全传输等。对于开发者来说可以…

【matlab】智能优化算法——求解目标函数

智能优化算法在求解目标函数方面发挥着重要作用,它通过迭代、筛选等方法来寻找目标函数的最优值(极值)。以下是关于智能优化算法求解目标函数的详细介绍: 一、智能优化算法概述 智能优化算法是一种搜索算法,旨在通过…