面试题答案
一键面试属性特性在原型链上的传播和表现
- 传播:在JavaScript的原型继承体系中,当访问对象的属性时,如果对象本身没有该属性,JavaScript会沿着原型链向上查找,直到找到该属性或者到达原型链顶端(
null
)。例如,若child
对象继承自parent
对象,child
对象本身没有prop
属性,那么就会在parent
对象的原型上查找prop
属性。 - 表现:属性特性(可配置性
configurable
、可枚举性enumerable
、可写性writable
)也会随着原型链继承。默认情况下,通过字面量或构造函数创建对象的属性,这些特性值分别为true
、true
、true
。但如果通过Object.defineProperty
定义属性,可以精确控制这些特性。
利用属性特性设计继承模式实现特定需求
下面通过代码实现一个继承模式,使得父类的某些属性在子类中具有不同的可配置性、可枚举性或可写性。
// 定义父类
function Parent() {
this.sharedProp = 'parent value';
}
// 子类通过原型链继承父类
function Child() {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
// 在子类上重新定义sharedProp属性,修改其特性
Object.defineProperty(Child.prototype,'sharedProp', {
configurable: false,
enumerable: false,
writable: true,
value: 'child value'
});
// 测试
const childInstance = new Child();
console.log(childInstance.sharedProp); // 输出 'child value'
// 尝试重新配置属性
try {
Object.defineProperty(childInstance,'sharedProp', { value: 'new value' });
} catch (error) {
console.log('不能重新配置属性:', error.message);
}
// 检查属性是否可枚举
const keys = Object.keys(childInstance);
console.log('可枚举属性:', keys);
代码解释
- 定义父类和子类:首先定义了
Parent
构造函数和Child
构造函数,通过Parent.call(this)
在子类构造函数中调用父类构造函数,实现属性的继承。然后通过Object.create
创建子类原型,使其继承父类原型,并修正子类的constructor
属性。 - 修改子类属性特性:使用
Object.defineProperty
在子类原型上重新定义sharedProp
属性,将其configurable
设置为false
,意味着不能再使用Object.defineProperty
修改该属性的特性;enumerable
设置为false
,表示该属性不会出现在for...in
循环或Object.keys
等操作中;writable
设置为true
,说明该属性的值可以被修改。 - 测试:创建
Child
类的实例childInstance
,首先输出属性值验证可写性。然后尝试重新配置属性,由于configurable
为false
,会抛出错误。最后通过Object.keys
检查属性是否可枚举,验证enumerable
为false
的设置。