【Uncaught(in promise)TypeError:0bject.hasOwn is not a function 报错解决、polyfill 支持Object.hasOwn 低版本浏览器】

一、前言

在项目开发完成后,进行版本测试过程中,更换了浏览器,遇到Uncaught(in promise)TypeError:0bject.hasOwn is not a function 报错

控制台:

在这里插入图片描述
报错定位:

在这里插入图片描述

二、原因

报错由该项目中使用的react-markdown插件导致,hasOwn是es2022新语法,旧浏览器不支持。

三、解决

提案方法 Object.hasOwnObject.prototype.hasOwnProperty.call(object, property) 具有相同的行为。

方案一:

直接修改react-markdown插件中的源码,相当于去修改了node_modules模块,你下次再npm i时还是会被重新覆盖的,当然也可以去搜索如何优雅的修改node_modules中的代码而不被覆盖。但此方案,治标不治本。

方案二:

polyfill 支持

在不支持的浏览器中,我们需要使用一些回退方式。我们利用 Object.hasOwnObject.prototype.hasOwnProperty.call(object, property) 的相同行为实现支持方案:

if (!Object.hasOwn) {
  Object.defineProperty(Object, 'hasOwn', {
    value: function (object, property) {
      if (object == null) {
        throw new TypeError('Cannot convert undefined or null to object');
      }
      return Object.prototype.hasOwnProperty.call(Object(object), property);
    },
    configurable: true,
    enumerable: false,
    writable: true,
  });
}

将此js文件放在项目入口文件index.js中,项目初始化时执行一次,就全局修改了。

这里附上代码解读:

这段代码是为了在运行环境中添加 Object.hasOwn 方法。Object.hasOwn 是一个用于检查对象是否具有指定属性的方法,它类似于 Object.prototype.hasOwnProperty,但不同的是它直接在对象上调用,而不是通过原型链。

在一些老旧的 JavaScript 环境中,Object.hasOwn 方法可能不存在,因此这段代码的作用是在运行时检测如果 Object.hasOwn 不存在,则定义这个方法。这样可以确保在任何环境中都可以使用 Object.hasOwn 方法来检查对象的属性。

代码中的实现使用了 Object.defineProperty 来定义一个新的属性 hasOwn,该属性是一个函数,它接受两个参数:object 和 property。这个函数会检查 object 是否为 null 或 undefined,如果是,则抛出一个类型错误。否则,它会调用 Object.prototype.hasOwnProperty.call 来检查 object 是否具有指定的 property

最后,Object.defineProperty 的参数设置了这个新属性的特性:

  • configurable: true 表示这个属性可以被删除或重新定义。
  • enumerable: false 表示这个属性不会出现在对象的枚举属性中。
  • writable: true 表示这个属性的值可以被修改。

这样定义的 Object.hasOwn 方法可以在任何 JavaScript 环境中使用,包括老旧的环境,从而提高代码的兼容性。

四、原理

Object.prototype.hasOwnPropertyObject.hasOwn 是 JavaScript 中用于检查对象属性的两种方法。

  1. Object.prototype.hasOwnProperty:

    • 作用: 这是一个用于检测对象自身是否有某个属性的方法。它会返回一个布尔值,指示对象是否拥有指定的属性,而不是从原型链上继承来的属性。
    • 用法: 你可以通过 obj.hasOwnProperty('propertyName') 来使用它。
    • 缺点: 如果对象上覆盖了 hasOwnProperty 方法(比如通过对象的原型链或直接在对象上定义),可能会导致调用该方法时出现问题。
  2. Object.hasOwn:

    • 作用: 这是一个在 ES2022 中引入的新方法,用于检查对象是否有某个属性。它作为 Object 对象上的静态方法存在,不依赖于对象实例,因此不会受到实例上重写 hasOwnProperty 方法的影响。
    • 用法: 你可以通过 Object.hasOwn(obj, 'propertyName') 来使用它。
    • 优点: 因为它是静态方法,所以不受对象实例的影响,避免了由于对象上覆盖了 hasOwnProperty 而导致的问题。此外,它提供了更清晰的语法和更高的可读性。

举个栗子:

const obj = {
  hasOwnProperty: function () {
    return false;
  },
  ab: 'own property',
};

对象obj重新定义的 hasOwnProperty 方法,该方法直接覆盖了从 Object.prototype 继承的方法 hasOwnProperty,此时你再调用hasOwnProperty 方法去判断ab是否是obj对象上的属性时,只会返回false。原因:JavaScript 普通对象的原型可以被覆盖。所以有了Object.hasOwn 提案,提案方法 Object.hasOwnObject.prototype.hasOwnProperty.call(object, property) 具有相同的行为。

总的来说,Object.hasOwn 作为一种静态方法,提供了比 Object.prototype.hasOwnProperty 更可靠和一致的方式来检查对象自身的属性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值