美文网首页
ES6...扩展运算符的实现原理

ES6...扩展运算符的实现原理

作者: AoeKeller | 来源:发表于2021-08-29 14:36 被阅读0次

ES6...扩展运算符的实现原理-记录TypeError("Invalid attempt to spread non-iterable instance")的问题分析

最近重构的新项目上线,观察前端监控日志有类型错误

TypeError("Invalid attempt to spread non-iterable instance")

提示的报错机型是,Android5.1.1的vivoXplay5,vivo 6sPlus等vivo系列。找不到对应机型但是有Android5.1.1的OPPO,结果OPPO是正常的。只好自己爬代码分析。
该类型错误是因为使用了ES6的扩展运算符展开MapIterator对象报错。但查阅了canisue网站,Map.values等是支持5.1.1系统的。怀疑代码报错的地方是

[...MapObje.values()]

转义后的代码如下

k = Object(o["a"])(u["a"].values())

Object(o["a"])的最终调用如下的d(t)函数

"75fc": function(t, e, n) {
  "use strict";
  var r = n("a745")
    , i = n.n(r);
  function o(t) {
    if (i()(t)) {
      for (var e = 0, n = new Array(t.length); e < t.length; e++)
        n[e] = t[e];
      return n
    }
  }
  ......
  function l(t) {
    if (u()(Object(t)) || "[object Arguments]" === Object.prototype.toString.call(t))
      return s()(t)
  }
  function f() {
    throw new TypeError("Invalid attempt to spread non-iterable instance")
  }
  function d(t) {
    return o(t) || l(t) || f()
  }
  n.d(e, "a", (function () {
    return d
  }
  ))
},

进入d(t)的o(t)中,o(t)的实现就是判断入参是否是数组,也就是Array.isArray(),判断t如果是数组的话直接生成一个新数组,拷贝t中的属性。

function o(t) {
    if (i()(t)) {
      for (var e = 0, n = new Array(t.length); e < t.length; e++)
        n[e] = t[e];
      return n
    }
  }

如果o(t)不满足的话,进入l(t)中,l(t)的u()(Object(t)主要是判断是否实现了Symbol.iterator迭代器接口

t.exports = n("584a").isIterable = function(t) {
            var e = Object(t);
            return void 0 !== e[i] || "@@iterator"in e || o.hasOwnProperty(r(e))
        }

其中 e[i]是指的对象是否有实现Symbol.iterator,否则的话判断是否有@@iterator,或者o.hasOwnProperty(r(e)),

截屏2021-08-29 上午9.34.16.png

其中r函数也很简单,是一个类型检测功能

void 0 === t ? "Undefined" : null === t ? "Null" : "string" == typeof (n = a(e = Object(t), i)) ? n : o ? r(e) : "Object" == (s = r(e)) && "function" == typeof e.callee ? "Arguments" : s

基于以上,猜测目前是因为Android5.1.1的vivo系统可能对Map的Iterator接口实现有问题,但是目前找不到该手机,只能是猜测,后面找到真机后在调试定位。
总结扩展运算符的实现原理:

  1. 是否是数组,数组直接浅拷贝属性
  2. 是否实现Iterator接口,检测方式包括是否有实现Symbol.iterator、@@Iterator、是否是其他可迭代对象等(叫可迭代也不合适好像)、或者对象本身是否是Arguments
  3. 都不满足的话抛出类型错误。

相关文章

  • ES6...扩展运算符的实现原理

    ES6...扩展运算符的实现原理-记录TypeError("Invalid attempt to spread n...

  • js数组去重利用set

    简述 原理:Set对象 + Array.from + 扩展运算符 具体实现: const nums = [1,2,...

  • LiveData

    LiveDataBus实现原理#用法详解#LiveData扩展 LiveDataBus实现原理#用法详解#Live...

  • 数组的扩展

    数组的扩展 扩展运算符...Array类似 ...restrest参数的逆运算,所有实现iterator接口的类数...

  • [转载]扩展运算符...

    原文:JavaScript 扩展运算符 扩展运算符格式 扩展运算符格式很简单,就是三个点(...) 扩展运算符作用...

  • es6之扩展运算符 三个点(...)

    es6之扩展运算符 三个点(...)对象的扩展运算符数组的扩展运算符总结es6之扩展运算符 三个点(…)对象的扩展...

  • 内置对象扩展(Array)

    Array 的扩展方法 扩展运算符(展开语法) 扩展运算符可以将数组或者对象转为用逗号分隔的参数序列 扩展运算符可...

  • ES6学习笔记(五):轻松了解ES6的内置扩展对象

    Array的扩展方法 扩展运算符(展开语法) 扩展运算符可以将数组或者对象转换为用逗号分隔的参数序列 扩展运算符可...

  • ES6之解构赋值/剩余运算符/箭头函数

    扩展运算符(对象) 扩展运算符(数组) 扩展运算符和Object.assign对对象进行合并的行为,是属于浅拷贝 ...

  • ES6学习之- 数组的扩展

    Part3 数组的扩展 3.1 扩展运算符和数组的解构赋值 (1)扩展运算符是三个点 ...,扩展运算符主要用于函...

网友评论

      本文标题:ES6...扩展运算符的实现原理

      本文链接:https://www.haomeiwen.com/subject/wvnwiltx.html