网站LOGO
白雾茫茫丶
页面加载中
3月5日
网站LOGO 白雾茫茫丶
记录学习、生活和有趣的事
菜单
  • 热评
    用户的头像
    首次访问
    上次留言
    累计留言
    我的等级
    我的角色
    打赏二维码
    打赏博主
    对象解构与迭代器的猫腻?
    点击复制本页信息
    微信扫一扫
    文章二维码
    文章图片 文章标题
    创建时间
  • 一 言
    确认删除此评论么? 确认
  • 本弹窗介绍内容来自,本网站不对其中内容负责。
    按住ctrl可打开默认菜单

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

    谢明伟 · 原创 ·
    前端开发 · JavaScript
    共 2819 字 · 约 2 分钟 · 290

    前言

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

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

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

    问题解决

    我们捋清楚问题的起因,问题就好解决了,我们只需要在对象的原型上也添加一个 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 入门教程

    声明:本文由 谢明伟(博主)原创,依据 CC-BY-NC-SA 4.0 许可协议 授权,转载请注明出处。

    还没有人喜爱这篇文章呢

    现在已有

    1

    条评论
    发一条!
    1. · · 广西
      • 等级:Lv.2
      • 角色:好友
      • 分组:志同道合
      • 在线:三月内
      头像
      沙发

      原来如此,之前写了个段代码;
      .then(res => new Uint8Array(res))
      .then(array => btoa(String.fromCharCode(...array)))
      .then(b64 =>
      // 在内存小的机器上可能会堆栈溢出,可能就是迭代器yield的时候用了某种递归 Σ(っ °Д °;)っ

      评论
    博客logo 白雾茫茫丶 记录学习、生活和有趣的事 51统计 百度统计
    MOEICP 萌ICP备20236860号 ICP 粤ICP备2023007649号 ICP 粤公网安备44030402006402号

    🕛

    本站已运行 2 年 63 天 13 小时 58 分

    🌳

    自豪地使用 Typecho 建站,并搭配 MyLife 主题
    白雾茫茫丶. © 2022 ~ 2024.
    网站logo

    白雾茫茫丶 记录学习、生活和有趣的事
     
     
     
     
    壁纸