Object.getOwnPropertyNames返回对象所有自有属性名(含不可枚举属性,不含Symbol),需手动过滤_、$开头及constructor等敏感键;可封装函数统一处理前缀、精确匹配和自定义黑名单。

Object.getOwnPropertyNames 能获取对象**所有自有(非继承)的键名(包括不可枚举属性)**,但默认会包含如 constructor、toString 等内置属性。若想过滤掉敏感或内部标识(如以 _、$ 开头的私有字段,或明确排除的系统属性),需手动筛选。
明确哪些属于“敏感内部标识”
常见需过滤的键名类型包括:
- 以单下划线
_或双下划线__开头的属性(如_id、__proto__) - 以美元符
$开头的框架/库内部属性(如$el、$data) - 明确不希望暴露的系统属性,如
constructor、__proto__、prototype(虽在普通对象上通常不存在,但在某些构造函数实例中可能出现) - 自定义黑名单,如
token、password、secretKey等业务敏感字段
基础过滤写法(推荐用 Array.prototype.filter)
获取自有键名后,用 filter 排除匹配规则的项:
const obj = {
name: 'Alice',
_internal: 'hidden',
$meta: true,
age: 30,
token: 'abc123',
toString() { return 'custom'; }
};
const keys = Object.getOwnPropertyNames(obj)
.filter(key =>
!key.startsWith('_') && // 过滤 _ 开头
!key.startsWith('$') && // 过滤 $ 开头
!['constructor', 'toString', 'toJSON'].includes(key) && // 过滤特定方法名
!['token', 'password'].includes(key) // 过滤敏感业务字段
);
console.log(keys); // ['name', 'age']
封装可复用的过滤函数
便于在多处统一处理:
function getPublicKeys(obj, options = {}) {
const {
excludePrefix = ['_', '$'],
excludeExact = ['constructor', 'toString', 'toJSON', '__proto__', 'prototype'],
excludeList = [],
includeSymbols = false
} = options;
let keys = Object.getOwnPropertyNames(obj);
if (includeSymbols) {
keys = keys.concat(Object.getOwnPropertySymbols(obj).map(s => s.toString()));
}
const allExcludes = new Set([...excludeExact, ...excludeList]);
return keys.filter(key => {
if (allExcludes.has(key)) return false;
if (excludePrefix.some(prefix => key.startsWith(prefix))) return false;
return true;
});
}
// 使用示例
const data = { username: 'bob', _cache: {}, $state: 'loading', id: 123 };
console.log(getPublicKeys(data)); // ['username', 'id']
注意 Symbol 属性和不可枚举性
Object.getOwnPropertyNames **不返回 Symbol 键**。如果对象含 Symbol 属性且需一并过滤,应显式调用 Object.getOwnPropertySymbols 并合并处理(如上例中的 includeSymbols 选项)。另外,该方法本身已包含不可枚举属性,无需额外设置 enumerable: true —— 它本就是为获取“所有自有属性名”而设计的,无论是否可枚举。

















