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

结尾

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

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

相关推荐
diygwcom4 分钟前
electron-updater实现electron全量版本更新
前端·javascript·electron
volodyan8 分钟前
electron react离线使用monaco-editor
javascript·react.js·electron
^^为欢几何^^16 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
Hello-Mr.Wang21 分钟前
vue3中开发引导页的方法
开发语言·前端·javascript
WG_1725 分钟前
C++多态
开发语言·c++·面试
鱼跃鹰飞1 小时前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
程序员凡尘1 小时前
完美解决 Array 方法 (map/filter/reduce) 不按预期工作 的正确解决方法,亲测有效!!!
前端·javascript·vue.js
北岛寒沫5 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
everyStudy5 小时前
JavaScript如何判断输入的是空格
开发语言·javascript·ecmascript
无心使然云中漫步7 小时前
GIS OGC之WMTS地图服务,通过Capabilities XML描述文档,获取matrixIds,origin,计算resolutions
前端·javascript