【问题标题】:How to merge object in IE 11如何在 IE 11 中合并对象
【发布时间】:2017-06-24 19:12:48
【问题描述】:

我有以下对象数组:

Objs[0] = {Name : "ABC"};
Objs[1] = {Roll : 123}

我正在尝试使其如下:

Objs {
  Name : "ABC",
  Roll : 123
}

我尝试使用以下代码:

var Objs = [{
  Name: "ABC"
}, {
  Roll: 123
}];

console.log(
  Object.assign.apply(null, [{}].concat(Objs)) // 1
)
or 

console.log(
  Object.assign({}, ...Objs) // 2
)

问题是这在 IE 11 中不起作用。

我得到错误:

错误 1:无法获取未定义或空引用的属性“on”

错误 2:对象不支持属性或方法“分配”

关于如何在 IE 11 中合并对象有什么建议吗?

【问题讨论】:

  • 正如@Nina Scholz 所说,IE 不支持 Object.assing() 因此您可以按照她的建议编写函数或使用 polyfill 添加该功能。你也可以在全局级别使用 babel-polifill。
  • @Ram 为什么 MDN 页面会声明 IE 10 的兼容性?似乎是一个错误...

标签: javascript object internet-explorer-11


【解决方案1】:

您可以使用在 IE 11 中工作的 jQuery 方法 $.extend()

var object = {name: 'John', surname: 'Rowland'};
var newObject = $.extend({}, object);

newObject.age = '30';

console.log(object);
console.log(newObject)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

【讨论】:

  • 您也可以直接将{age: 30}作为第一个参数而不是后面添加:var newObject = $.extend({age: 30}, object};
  • @DuncanLuk 在这种情况下,是的,但如果object 中有一个age,它可能会产生不良影响。
【解决方案2】:

IE11 不支持Object.assign

您可以迭代数组和键并将值作为结果对象的新属性。

var objs = [{ Name: "ABC" }, { Roll: 123 }],
    result =  objs.reduce(function (r, o) {
        Object.keys(o).forEach(function (k) {
            r[k] = o[k];
        });
        return r;
    }, {});

console.log(result);

【讨论】:

  • 我注意到这不适用于 IE 11 中的数组属性。我添加了对数组的检查并在我的用例中使用 .concat()。 if (Object.prototype.toString.call(o[k]) === "[object Array]")) r[k] = (r[k] || []).concat(o[k]) 然后是你在 forEach 中的行。
  • @Calle,现在可以用了吗?您可以使用简单的检查和内联推送,例如 (r[k] = r[k] || []).push(o[k])
  • 我想,取决于您正在寻找的结果。 ? 我猜push会快很多,只要最后加上就是想要的结果。
【解决方案3】:

安装:

npm i -s babel-polyfill

并在入口 index.js 文件的顶部添加:

import 'babel-polyfill'

这将解决 Babel 没有解决的一些问题。 Object.assign 就是其中之一。

这意味着您可以使用新的内置插件,例如 Promise 或 WeakMap,静态 像 Array.from 或 Object.assign 这样的方法,像这样的实例方法 Array.prototype.includes 和生成器函数(前提是您使用 再生器插件)。 polyfill 也添加到全局范围 为了做到这一点,像 String 这样的原生原型。

最后,您需要决定是要使用整个 babel-polyfill(最小化大约 50kb)还是仅通过单个 polyfill 使用您需要的东西,即。 es6-promise 用于 Promises。

【讨论】:

    【解决方案4】:

    如果您在项目中使用 lodash util 库,我认为最好的办法是 lodash 的 assign 方法,该方法与所有浏览器的 Object.prototype.assign 相同,包括 IE(在至少IE11):https://lodash.com/docs/4.17.4#assign

    如果您还没有使用 lodash,请考虑一下。它有许多实用功能,可以在所有浏览器上完美运行,无论是在 JavaScript、TypeScript 和 NodeJS 中(我自己测试过,但它可能也支持其他 JS 连接技术)。就我个人而言,我将 lodash 包含在我所有的 javascript 连接项目中

    【讨论】:

    • 很好,无法击败一些 Lodash
    【解决方案5】:

    使用这样的 polyfill; Ref: MDN

     if (typeof Object.assign != 'function') {
      // Must be writable: true, enumerable: false, configurable: true
      Object.defineProperty(Object, "assign", {
        value: function assign(target, varArgs) { // .length of function is 2
          'use strict';
          if (target == null) { // TypeError if undefined or null
            throw new TypeError('Cannot convert undefined or null to object');
          }
    
          var to = Object(target);
    
          for (var index = 1; index < arguments.length; index++) {
            var nextSource = arguments[index];
    
            if (nextSource != null) { // Skip over if undefined or null
              for (var nextKey in nextSource) {
                // Avoid bugs when hasOwnProperty is shadowed
                if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                  to[nextKey] = nextSource[nextKey];
                }
              }
            }
          }
          return to;
        },
        writable: true,
        configurable: true
      });
    }
    

    【讨论】:

    • this does not support symbol property 'coz ie11 doesn't support it.
    【解决方案6】:

    如果您使用的是 TypeScript,请尝试将 Object.assign({}, ...Objs) 替换为 {...Objs};,浏览器会自动将其替换为 __assign({}, Objs);,并且此标记在 IE11 中有效。

    【讨论】:

    • 我可以确认这适用于 IE11 和 Edge。谢谢!
    【解决方案7】:

    除了@vladatr,如果您使用的是 Wepack:

    在你的 webpack.config.js 中

    const path = require("path");
    module.exports = {
      entry: ["babel-polyfill", path.resolve(__dirname, "../src/index.js")],
      .
      .
    

    在我的入口点src/index.js 文件中:

    import "babel-polyfill";
    

    【讨论】:

      【解决方案8】:

      这个只有 javascript 的解决方案适用于 IE。遍历数组,并在该循环中遍历对象中的每个键并将其添加到新对象中。新对象包含您想要的数据。

      var Objs = [];
      Objs[0] = {Name : "ABC"};
      Objs[1] = {Roll : 123};
      
      console.log(Objs);
      
      var newObject = {};
      
      for(var i=0; i<Objs.length; i++) {
      
          for(var key in Objs[i]) {
              if(! Objs[i].hasOwnProperty(key))
                  continue;
      
              newObject[key] = Objs[i][key];
          }
      }
      
      console.log(newObject);

      如果需要,可以将 newObject 分配给数组变量 Objs = newObject

      【讨论】:

        【解决方案9】:

        如果你使用 TypeScript,你可以使用

        let newObject = {
            ...existingObject
        }
        

        这会创建现有对象的浅表副本。

        【讨论】:

        • 展开运算符与 TypeScript 无关。这是一个 JavaScript 特性,从 ES6 开始可用。
        • @LiranH 正确,但如果您使用 TypeScript,即使您的目标浏览器不支持 ES6,也可以使用它。
        • 再一次,与 TypeScript 无关,是转译器(例如 Babel)负责处理。例如,您可以使用 JS ES2020 编写代码,转译器会将其转译为 ES5。
        【解决方案10】:

        即使有 babel:

        const newObj = Object.assign({}, myOtherObject)
        

        在 IE11 中摧毁了我们。

        我们将其更改为:

        const newObj = { ...myOtherObject }
        

        这与 babel 一起工作。

        【讨论】:

        • babel 本身不能使 Object.assign 在 ie11 中工作的原因是因为它不是一种可以被 transpiled down 的语言结构。它是 Object 类型中的一个函数,这意味着它需要被填充。 Babel 可以做到这一点,但它的构建和配置过程更复杂,请参阅babeljs.io/docs/en/babel-preset-env#usebuiltins
        猜你喜欢
        • 1970-01-01
        • 2015-02-08
        • 2017-09-23
        • 1970-01-01
        • 2018-06-01
        • 1970-01-01
        • 2020-08-02
        • 2015-04-12
        • 2018-11-28
        相关资源
        最近更新 更多