对象解构与迭代器的猫腻?

前言

变量的解构赋值是前端开发中经常用到的一个技巧,比如:

javascript 复制代码
// 对象解构
const obj = { a: 1, b: 2 };
const { a, b } = obj;
console.log(a, b)

数组解构
const arr = [1, 2, 3];
const [a, b] = arr;
console.log(a, b)

工作中我们最经常用的就是类似上面的对象和数组解构,好多同学就不禁问了,这个不是很简单吗。 那好,我们再来看一个:

javascript 复制代码
// 不改动下面代码,如何使等式成立
const [a, b] = { a: 1, b: 2 };
console.log(a, b)

你觉得这个打印出来什么呢?

直接报错:{(intermediate value)(intermediate value)} is not iterable 翻译过来就是值是不可迭代的,这是为什么呢?因为右边的值是不可迭代对象

可迭代对象

什么是可迭代对象? 可迭代对象就是满足 可迭代协议 的对象。

可迭代协议 中必须有这么一个属性:Symbol.iterator,一个无参数的函数,其返回值为一个符合 可迭代协议 的对象,即迭代器

数组解构

数组可以解构,因为数组是一个可迭代对象。

javascript 复制代码
const arr = [1, 2, 3];
const iter = arr[Symbol.iterator]();
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())
console.log(iter.next())

我们看一下打印结果:

value 代表的是这次迭代的值,done 代表迭代是否完成。 这就是 可迭代协议 的规则。 数组解构就相当于下面这种写法:

javascript 复制代码
const arr = [1, 2, 3];
// const [a,b] = arr;
const iter = arr[Symbol.iterator]();
const a = iter.next().value;
const b = iter.next().value;
console.log(a, b)

对象解构

那么问题来了,对象身上没有 Symbol.iterator,为什么还能解构?

因为对象的解构过程是这样的:创建对象 -> 枚举属性(OwnPropertyKeys) -> 复制属性,跟迭代器没关系。

问题解决

我们捋清楚问题的起因,问题就好解决了,我们只需要在对象的原型上也添加一个 Symbol.iterator 属性就可以了:

javascript 复制代码
Object.prototype[Symbol.iterator] = function () {
  return Object.values(this)[Symbol.iterator]();
}
const [a, b] = { a: 1, b: 2 };
console.log(a, b)

这样就能使等式成立,而且如果你的 ES6 功底足够的扎实,还知道什么叫 生成器Generator,那你还可以这样写:

javascript 复制代码
Object.prototype[Symbol.iterator] = function* () {
  yield* Object.values(this);
}
const [a, b] = { a: 1, b: 2 };
console.log(a, b)

最终效果是一样的。

如果你对这些还不是很熟悉,建议你看一下 ES6 的文档:ECMAScript 6 入门教程

相关推荐
雪芽蓝域zzs1 小时前
第十六节:递归组件实现无限层级折叠侧边栏菜单
开发语言·javascript·ecmascript
BillKu2 小时前
vue3 字符串排序 localeCompare,确保排序为 “B01“, “B10“, “B2“
前端·javascript·vue.js
然我2 小时前
从 Service 到生命周期:Agent Runtime 的插件内核
前端·javascript·agent
用户6919026813393 小时前
Agent 记忆处理机制详解:从变量数据类型到内存模型
javascript·架构
ShineWinsu3 小时前
对于 Vue 3:开发前需要掌握的 JavaScript 核心基础:从变量、数组方法到 Promise、Async/Await 与 ES Module 的解析
javascript·vue.js·elasticsearch
晴天163 小时前
Tsup:TypeScript库打包的“零配置极速方案”
前端·javascript·typescript
雪芽蓝域zzs4 小时前
第十七节:面包屑导航组件(适配多级嵌套路由)
前端·javascript·vue.js
smileNicky4 小时前
React 弹窗组件如何在新标签页打开?
javascript·react.js·ecmascript
yume_sibai4 小时前
Element Plus 其他实用组件完全指南(10个核心组件)
前端·javascript·vue.js
雪芽蓝域zzs5 小时前
第二十二节:进阶:用户管理新增、编辑弹窗 + 表单校验
前端·javascript·vue.js