解决错误:Do not access Object.prototype method ‘hasOwnProperty‘ from target object no-prototype-builtins

367 阅读2分钟

解决错误:Do not access Object.prototype method ‘hasOwnProperty‘ from target object no-prototype-builtins

目录

[TOC]

在 JavaScript 开发中,如果你使用 ESLint 进行代码检查,可能会遇到以下错误提示:
Do not access Object.prototype method 'hasOwnProperty' from target object no-prototype-builtins

这一错误通常源于直接通过对象实例调用 hasOwnProperty 方法(例如 obj.hasOwnProperty('key') ),而 ESLint 的 no-prototype-builtins 规则会将其标记为潜在的安全风险。本文将详细解释这一错误的原因,并提供多种解决方案。


错误原因
  1. 原型链污染风险
    JavaScript 中几乎所有对象都继承自 Object.prototype ,因此可以调用 hasOwnProperty 方法。但如果一个对象自身定义了名为 hasOwnProperty 的属性(例如 obj.hasOwnProperty = 123 ),直接调用 obj.hasOwnProperty('key') 时,实际调用的是对象自身的属性而非原型链上的方法,这会导致意外的行为或错误。

  2. 无原型对象的兼容性问题
    使用 Object.create(null) 创建的对象没有原型链,因此无法调用 hasOwnProperty 方法。此时直接调用 obj.hasOwnProperty 会抛出 TypeError

  3. ESLint 规则限制
    ESLint 的 no-prototype-builtins 规则强制开发者避免直接调用 Object.prototype 的方法(如 hasOwnProperty , toString 等),以规避上述风险。


解决方案
方法 1:使用 Object.prototype.hasOwnProperty.call()

通过显式调用 Object.prototype.hasOwnProperty 并指定上下文( this ),可以绕过原型链的干扰,确保调用的是原始方法。

const obj = { key: 'value' };
 
// 安全用法
if (Object.prototype.hasOwnProperty.call(obj, 'key')) {
  console.log('key exists');
}
简化写法(推荐)

可以提取工具函数减少重复代码:

function hasOwn(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key);
}
 
// 使用示例
if (hasOwn(obj, 'key')) {
  // ...
}
方法 2:使用 Object.hasOwn()(ES2022+)

ES2022 引入了 Object.hasOwn() 方法,作为更简洁、安全的替代方案。它直接检查对象自身属性,无需处理原型链问题。

const obj = { key: 'value' };
 
// 现代浏览器和 Node.js 16.9.0+ 支持
if (Object.hasOwn(obj, 'key')) {
  console.log('key exists');
}
兼容性处理

对于旧环境,可以通过 Polyfill 实现:

if (!Object.hasOwn) {
  Object.hasOwn = function(obj, key) {
    return Object.prototype.hasOwnProperty.call(obj, key);
  };
}
方法 3:配置 ESLint 规则(不推荐)

虽然不推荐,但如果你确定代码环境安全,可以暂时禁用此规则:

单行禁用

// eslint-disable-next-line no-prototype-builtins
if (obj.hasOwnProperty('key')) { /* ... */ }

全局禁用
.eslintrc 配置文件中关闭规则:

{
  "rules": {
    "no-prototype-builtins": "off"
  }
}
为什么推荐显式调用或 Object.hasOwn()?
场景obj.hasOwnPropertyObject.prototype.hasOwnProperty.callObject.hasOwn
对象有自定义 hasOwnProperty❌ 失败✅ 安全✅ 安全
无原型对象( Object.create(null)❌ 抛出 TypeError✅ 安全✅ 安全
代码简洁性✅ 简单❌ 冗长✅ 简洁
浏览器兼容性所有环境所有环境ES2022+

总结
  1. 优先使用 Object.hasOwn()
    现代项目(支持 ES2022+)应直接使用 Object.hasOwn() ,它简洁且安全。

  2. 旧项目使用显式原型调用
    通过 Object.prototype.hasOwnProperty.call() 确保兼容性。

  3. 避免直接调用 obj.hasOwnProperty
    除非你完全控制对象结构且无原型链风险。

遵循 ESLint 的 no-prototype-builtins 规则,不仅能避免潜在错误,还能提升代码的健壮性和可维护性。