var [a,b] = {a:1,b:2}怎么才能成立

前言

var [a,b] = {a:1,b:2}这道题看起来得到结果a=1,b=2。看起来好像有些荒唐,我们都知道数组的解构赋值需要后面也是数组即var [a,b]=[1,2]才能成功。这个题目就是一种错误的写法。怎么让错误的写法成立呢?这不纯纯的瞎写吗?考这个一点意义都没有,想到这你就要走了,等等先别走!搞明白这个题会让你对es6解构赋值的理解更加深刻,顺便了解一下迭代器的概念,心动了吧!赶紧往下看吧!!!

迭代协议

题目问怎么能让var [a,b] = {a:1,b:2} 成立,那么我们首先要运行一下,看看它是怎么个不成立法。

css 复制代码
const obj = {
    a:'1',
    b:'2',
}

const [a,b] = obj

运行之后打开控制台可以发现报错信息,它告诉我们obj这个对象是不可迭代的,那么我们想办法把obj变成可迭代的是不是就能解决这个问题,这要怎么做呢?想要搞明白这点我们需要先了解一下可迭代协议。

可迭代协议的概念( MDN

可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of 结构中,哪些值可以被遍历到。一些内置类型同时是内置的可迭代对象,并且有默认的迭代行为,比如 Array 或者 Map,而其他内置类型则不是(比如 Object)。

要成为可迭代对象,该对象必须实现 @@iterator 方法,这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性:

[Symbol.iterator]

一个无参数的函数,其返回值为一个符合迭代器协议的对象。

当一个对象需要被迭代的时候(比如被置入一个 for...of 循环时),首先,会不带参数调用它的 @@iterator 方法,然后使用此方法返回的迭代器获得要迭代的值。

说人话就是,要想让obj成为一个可迭代的对象,就需要它实现 @@iterator 方法,具体表现为对象身上要有一个名为[Symbol.iterator] 的方法。而数组和Map则是一开始就有这个方法,所以它们是可迭代的。而对象身上则没有这个默认行为,所以不可迭代。真的是这样吗?我们创建一个数组,看看数组身上到底有没有[Symbol.iterator] 方法。

c 复制代码
const array = [1,2,3]
console.log(array)

点开原型查看

发现真的有一个Symbol.iterator()方法,该方法会返回一个迭代器对象。我们来调用一下

vbnet 复制代码
const array = [1,2,3]
const iterator = array[Symbol.iterator]()
console.log(iterator)
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())

打印iterator对象后发现在它的原型上有一个next()方法,调用next()方法,会得到一个对象value就是当前迭代的值,done则代表当前迭代器是否已经迭代完成。

数组 解构 的本质

ini 复制代码
const array = [1,2,3]
var [a,b,c] = array
// 本质上是
const iterator = array[Symbol.iterator]()
var a = iterator.next().value
var b = iterator.next().value
var c = iterator.next().value

解决方法

到此为止我们可知,要想满足迭代协议需要对象身上有一个名为[Symbol.iterator]的方法。再使用for..of或者解构赋值的时候会隐式的调用这个方法,得到一个迭代对象,通过迭代对象的next方法判断当前是否完成迭代和具体迭代的值。

也就是说我们要在obj上添加[Symbol.iterator]方法并且完成next方法的逻辑

最终代码如下

javascript 复制代码
 const obj = {
    a: '1',
    b: '2',
    [Symbol.iterator]() {
        let index = 0
        const keys = Object.keys(this)
        return {
            next() {
                if (index < keys.length) {
                    return {
                        done: false,
                        value: obj[keys[index++]]
                    }
                }
                return {done:true,value:undefined}
            }
        }
    }
}

const [a, b] = obj

当然,我们也可以用for...of去循环遍历这个对象,我看谁再说for...of不能遍历对象(doge)

scss 复制代码
for(let i of obj){
    console.log(i)
}
// 1
// 2

结尾

我通过这个无厘头的题目中,学习了迭代器,明白了数组解构的本质。

希望大家看完这篇文章也能有所收获!

相关推荐
RickeyBoy3 小时前
SwiftUI 如何实现 Infinite Scroll?
ios·面试
跟着珅聪学java6 小时前
js编写中文转unicode 教程
前端·javascript·数据库
英俊潇洒美少年6 小时前
Vue3 深入响应式系统
前端·javascript·vue.js
颜酱6 小时前
回溯算法实战练习(3)
javascript·后端·算法
前端摸鱼匠6 小时前
【AI大模型春招面试题12】Scaling Laws揭示了模型性能、数据量、计算量之间的什么关系?
人工智能·ai·语言模型·面试·大模型
我命由我123457 小时前
React Router 6 - 概述、基础路由、重定向、NavLink、路由表
前端·javascript·react.js·前端框架·ecmascript·html5·js
yaaakaaang8 小时前
(四)前端,如此简单!---Promise
前端·javascript
aini_lovee8 小时前
C# 实现邮件发送源码(支持附件)
开发语言·javascript·c#
英俊潇洒美少年9 小时前
js 进程与线程的讲解
javascript
敲代码的嘎仔9 小时前
Java后端开发——真实面试汇总(持续更新)
java·开发语言·程序人生·面试·职场和发展·八股