如何判断一个js对象是否拥有某个属性(区分自身属性和原型链上的属性)?
在 JavaScript 中,判断对象是否拥有某个属性(区分自身属性和原型链属性)可以使用以下方法:
1. 判断属性是否存在(不区分自身或原型链)
使用 in
操作符,检查对象或其原型链上是否存在指定属性:
const obj = { a: 1 };
console.log("a" in obj); // true(自身属性)
console.log("toString" in obj); // true(继承自 Object.prototype)
2. 判断属性是否为自身属性
使用 Object.prototype.hasOwnProperty
,检查属性是否直接定义在对象上(不遍历原型链):
const obj = { a: 1 };
console.log(obj.hasOwnProperty("a")); // true(自身属性)
console.log(obj.hasOwnProperty("toString")); // false(原型链属性)
处理边缘情况
若对象可能覆盖或未继承 hasOwnProperty
方法(如 Object.create(null)
),需安全调用:
const obj = Object.create(null);
obj.a = 1;// 直接调用 obj.hasOwnProperty 会报错(obj 无该方法)
console.log(Object.prototype.hasOwnProperty.call(obj, "a")); // true
3. 综合判断属性来源
结合 in
和 hasOwnProperty
,明确属性的来源:
function checkProperty(obj, key) {if (key in obj) {if (obj.hasOwnProperty(key)) {return "自身属性";} else {return "原型链属性";}} else {return "不存在";}
}const parent = { inheritedProp: "父类属性" };
const child = Object.create(parent);
child.ownProp = "自身属性";console.log(checkProperty(child, "ownProp")); // "自身属性"
console.log(checkProperty(child, "inheritedProp")); // "原型链属性"
console.log(checkProperty(child, "nonexistent")); // "不存在"
4. 其他方法
Object.getOwnPropertyNames()
获取对象所有自身属性名(包括不可枚举属性,不包含原型链属性):
const obj = { a: 1 };
console.log(Object.getOwnPropertyNames(obj)); // ["a"]
Reflect.ownKeys()
获取对象所有自身属性名(包括 Symbol 类型和不可枚举属性):
const obj = { [Symbol("key")]: "value", a: 1 };
console.log(Reflect.ownKeys(obj)); // ["a", Symbol(key)]
总结
方法 | 作用 | 示例 |
---|---|---|
key in obj | 检查属性是否存在(自身或原型链) | "toString" in {} → true |
obj.hasOwnProperty(key) | 检查是否为自身属性 | {}.hasOwnProperty("toString") → false |
Object.getOwnPropertyNames(obj) | 获取所有自身属性名(含不可枚举) | Object.getOwnPropertyNames([]) → ["length"] |
Reflect.ownKeys(obj) | 获取所有自身属性名(含 Symbol 和不可枚举) | Reflect.ownKeys({ [Symbol()]: 1 }) → [Symbol()] |
注意事项
- 避免直接修改
__proto__
:
使用Object.getPrototypeOf(obj)
和Object.setPrototypeOf(obj, proto)
替代。 - 不可枚举属性:
for...in
和Object.keys()
会忽略不可枚举属性,而Object.getOwnPropertyNames()
和Reflect.ownKeys()
会包含它们。