一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何利用Object.getOwnPropertyNames获取实例自有键名并过滤掉内置原型干扰

时间:2026-06-13 09:46:52 编辑:袖梨 来源:一聚教程网

Object.getOwnPropertyNames只返回对象自身的所有自有属性键名(含不可枚举),不包含原型链上的任何属性。它天然绕过__proto__和原型链,无需过滤内置原型方法;真正需过滤的是实例自身可能存在的length、constructor等内置自有属性。

直接用 Object.getOwnPropertyNames 只能拿到实例自身的**所有**自有属性键名(包括不可枚举的),但它**不包含原型链上的属性**,所以本身就不会返回内置原型(如 Object.prototypeArray.prototype 等)的方法或属性。所谓“过滤掉内置原型干扰”,其实是对这个 API 的常见误解——它根本不会获取原型上的东西。

明确:getOwnPropertyNames 本来就不查原型

Object.getOwnPropertyNames(obj) 的作用范围严格限定在 obj 自身,即 obj.hasOwnProperty(key) === true 的那些键。它完全绕过 __proto__ 和整个原型链。例如:

(数组实例)

const arr = [1, 2];<br>console.log(Object.getOwnPropertyNames(arr)); // ['0', '1', 'length']<br>// 没有 push、map、toString 等 —— 它们在 Array.prototype 上,这里根本不会出现

真正需要过滤的,是构造函数/内置对象自动添加的自有属性

某些内置对象(如 new Date()new RegExp()、或使用 Object.defineProperty 显式定义的不可枚举属性)会在实例上**自身拥有**一些非业务属性。这时才需按需过滤。常见策略:

  • 排除 length、prototype、constructor 等典型静态键(尤其在处理类数组或自定义构造函数时)
  • 跳过 Symbol 键getOwnPropertyNames 不返回 Symbol,若需统一处理请改用 Reflect.ownKeys
  • 结合 hasOwnProperty + typeof 判断,比如只保留字符串键且值为普通数据类型

实用过滤示例:只留用户显式设置的字符串键

假设你有一个实例 user,想提取它“真正由代码赋值产生的自有键”(排除内置自动属性):

function getUserOwnDataKeys(obj) {<br>  return Object.getOwnPropertyNames(obj)<br>    .filter(key => {<br>      // 排除 length、__*、constructor、prototype 等常见内置自有属性<br>      if (key === 'length' || key === 'prototype' || key === 'constructor') return false;<br>      if (key.startsWith('__')) return false;<br>      // 可选:只保留值为 string/number/boolean/null 的键(排除函数、对象等)<br>      const val = obj[key];<br>      return ['string', 'number', 'boolean', 'undefined'].includes(typeof val) || val === null;<br>    });<br>}<br><br>const user = { name: 'Alice', age: 30 };<br>Object.defineProperty(user, 'id', { value: 101, enumerable: false });<br>console.log(getUserOwnDataKeys(user)); // ['name', 'age', 'id']

注意:和 for...in、Object.keys 的关键区别

  • Object.keys(obj):只返回**可枚举**的自有属性键
  • for...in:遍历**可枚举**的自有 + 原型属性键(含 Object.prototype
  • Object.getOwnPropertyNames(obj):返回**所有**自有属性键(无论是否可枚举),但**绝对不含原型链任何键**

因此,如果你看到结果里出现了 toStringhasOwnProperty,那说明该属性被手动定义在了实例自身(非常规操作),而不是“没过滤干净”。

热门栏目