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

简介: 这篇文章介绍了变量的解构赋值技巧在前端开发中的常用性,包括对象解构和数组解构。文章中给出了一些代码示例,解释了可迭代对象的概念以及如何使用迭代协议来实现数组解构。此外,文章还介绍了生成器的概念并提供了代码示例。作者建议对这些概念不熟悉的读者可以查阅ES6的文档来更好地理解。

前言

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

// 对象解构
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)

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

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

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

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

可迭代对象

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

数组解构

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

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())

我们看一下打印结果:
pppnm7op5af0m5fzrcgh7g2gkoddhs4y.png

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

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) -> 复制属性,跟迭代器没关系。
对象解构就相当于下面这种写法:

const obj = {
   
    a: 1, b: 2 };
// const { a, b } = obj;
const a = obj.a;
const b = obj.b;

问题解决

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

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

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

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

最终效果是一样的。

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

相关文章
|
1月前
|
算法 编译器 C语言
【C++ 迭代器的空类类型 】深入理解C++迭代器类别与空类标签的奥秘
【C++ 迭代器的空类类型 】深入理解C++迭代器类别与空类标签的奥秘
37 0
|
4天前
|
存储 安全 Java
java泛型与迭代器的关系
java泛型与迭代器的关系
6 0
|
1月前
|
存储 索引 Python
什么是数组,什么是对象,并说出他们的区别
什么是数组,什么是对象,并说出他们的区别
17 6
|
1月前
|
JavaScript
解构赋值及其原理
解构赋值及其原理
35 1
|
10月前
|
JavaScript 前端开发 索引
JavaScript 手写代码 第六期(重写数组方法二)不改变原数组的方法
JavaScript 手写代码 第六期(重写数组方法二)不改变原数组的方法
46 0
|
10月前
|
JavaScript 前端开发 索引
JavaScript 手写代码 第五期(重写数组方法一)-可以改变原数组的方法
JavaScript 手写代码 第五期(重写数组方法一)-可以改变原数组的方法
53 0
|
11月前
|
索引 Python 容器
继续打脸水货教程:关于可变对象与不可变对象
前阵子我们聊了下Python中有关函数参数传递以及变量赋值的一些内容:Python到底是引用传递还是值传递?网上大多数教程都讲错了
歪理解?原型链中的函数和对象
最近在看高程4,原型链肯定是绕不过的,本瓜之前一直认为,只要记住这句话就可以了: 一个对象的隐式原型(__proto__)等于构造这个对象的构造函数的显式原型(prototype)
|
JSON 数据格式
🍉十分钟搞定解构赋值,你确定不来看看嘛~
🍉十分钟搞定解构赋值,你确定不来看看嘛~
96 5
🍉十分钟搞定解构赋值,你确定不来看看嘛~