API | 原型链属性 | 不可枚举属性 | Symbol
属性名属性 | 总结
—————————————-|———-|————|——————|-
判断:
in
| ✅ | ✅ | ✅ | 最宽松,原型链、不可枚举、Symbol
属性都返回true
Object.property.hasOwnProperty
| | ✅ | ✅ | 只有原型链属性会返回false
,自身的不可枚举、Symbol
属性都返回true
Object.property.propertyIsEnumerable
| | | | 最严格,不可枚举、原型链、Symbol
属性都返回false
,只有可枚举的自身非Symbol
属性会返回true
遍历:(全都不返回Symbol
属性名的属性)
for...in
| ✅ | | | 可枚举非Symbol
属性都会返回,不论是自身属性还是原型链属性
Object.keys()
| | | | 最严格,只返回可枚举的自身非Symbol
属性,不可枚举、原型链、Symbol
属性都不返回
Object.getOwnPropertyNames()
| | ✅ | | 自身的非Symbol
属性都会返回,不论是否可枚举
例:
// 声明父类
function parent() {
// 父类实例属性
this.parentProp = 'Parent property value';
}
// 父类实例方法
parent.prototype.parentMethod = function() {
console.log('Parent method called');
};
// 声明子类
function child() {
// 子类实例方法
this.childMethod = function() {
console.log('Child method called');
};
}
// 设置子类原型
child.prototype = new parent();
// 设置子类构造函数
child.prototype.constructor = child;
let chi = new child();
// 子类实例属性
chi.childProp = 'Child property value';
// 子类实例不可遍历属性
Object.defineProperty(chi, 'notEnumerable', {
value: 'notEnumerable',
enumerable: false
})
// 子类实例Symbol属性名属性
let symbol = Symbol('SymbolNameProp');
chi[symbol] = 'Symbol name property value'
// 判断测试
console.log({
parentIn: 'parentProp' in chi,
notEnumerableIn: 'notEnumerable' in chi,
SymbolIn: symbol in chi
}); // { parentIn: true, notEnumerableIn: true, SymbolIn: true }
console.log({
parentHasOwnProperty: Object.prototype.hasOwnProperty.call(chi, 'parentProp'),
notEnumerableHasOwnProperty: Object.prototype.hasOwnProperty.call(chi, 'notEnumerable'),
SymbolHasOwnProperty: Object.prototype.hasOwnProperty.call(chi, symbol)
}); // { parentHasOwnProperty: false, notEnumerableHasOwnProperty: true, SymbolHasOwnProperty: true }
console.log({
parentPropertyIsEnumerable: Object.propertyIsEnumerable(chi, 'parentProp'),
notEnumerableIsEnumerable: Object.propertyIsEnumerable(chi, 'notEnumerable'),
SymbolIsEnumerable: Object.propertyIsEnumerable(chi, symbol)
}); // { parentPropertyIsEnumerable: false, notEnumerableIsEnumerable: false, SymbolIsEnumerable: false }
// 遍历测试
let forInProps = [];
for (prop in chi) { forInProps.push(prop); }
console.log({
forInProps,
ObjectDotKeysProps: Object.keys(chi),
getOwnPropertyNames: Object.getOwnPropertyNames(chi)
}); // { ObjectDotKeysProps: [ "childMethod", "childProp" ], forInProps: [ "childMethod", "childProp", "parentProp", "constructor", "parentMethod" ], getOwnPropertyNames: [ 'childMethod', 'childProp', 'notEnumerable' ] }
属性的可枚举性和所有权 - 内置的判断、访问和迭代方法
整理自https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Enumerability_and_ownership_of_properties
作用 | 自身对象 | 自身对象及其原型链 | 仅原型链 | ||||
---|---|---|---|---|---|---|---|
判断 | 可枚举属性 | 不可枚举属性 | 可枚举属性及不可枚举属性 | 可枚举属性 | 不可枚举属性 | 可枚举属性及不可枚举属性 | 需要额外代码实现 |
propertyIsEnumerable
hasOwnProperty
|
hasOwnProperty
获取属性后使用
propertyIsEnumerable
过滤可枚举属性
|
hasOwnProperty
|
需要额外代码实现 | 需要额外代码实现 | in |
||
访问 | 可枚举属性 | 不可枚举属性 | 可枚举属性及不可枚举属性 | 需要额外代码实现 | 需要额外代码实现 | ||
Object.keys getOwnPropertyNames getOwnPropertySymbols
|
getOwnPropertyNames 、getOwnPropertySymbols 获取属性后使用
propertyIsEnumerable
过滤可枚举属性
|
getOwnPropertyNames getOwnPropertySymbols
|
|||||
迭代 | 可枚举属性 | 不可枚举属性 | 可枚举属性及不可枚举属性 | 可枚举属性 | 不可枚举属性 | 可枚举属性及不可枚举属性 | 需要额外代码实现 |
Object.keys getOwnPropertyNames getOwnPropertySymbols
|
getOwnPropertyNames 、getOwnPropertySymbols
获取属性后使用 propertyIsEnumerable
过滤可枚举属性
|
getOwnPropertyNames getOwnPropertySymbols
|
for..in (同时会排除 Symbol) |
需要额外代码实现 | 需要额外代码实现 |