JavaScript中如何扩展无合适构造函数的基类(满足多项约束)
解决JavaScript基类构造函数必须传参时的继承问题
你的问题出在Artist.prototype = new Person();这一行——因为Person的构造函数要求必须传入有效的字符串名字,无参数调用时直接触发了错误抛出,导致代码失败。我们需要一种方式来建立原型链,同时不调用基类的构造函数,还要满足你列出的所有要求。
正确的实现方案
function Person(name) { // 不可变基类 if (typeof name != "string" || name == "") { throw new Error("A person must have a valid name."); } this.getName = function() { return name; } } function Artist(name) { // 我的扩展类 Person.call(this, name); // 正确调用父类构造函数,传递必要参数 } // 关键:用Object.create创建以Person.prototype为原型的对象,不会触发Person构造函数 Artist.prototype = Object.create(Person.prototype); // 修正constructor指向,否则Artist的constructor会指向Person Artist.prototype.constructor = Artist; var tom = new Artist("Tom"); console.info(tom instanceof Person); // 输出true console.info(tom.getName()); // 输出Tom
原理说明
Object.create(Person.prototype)创建了一个空对象,这个对象的原型直接指向Person.prototype,完全跳过了Person构造函数的调用,避免了参数校验的异常。Person.call(this, name)确保了父类构造函数被正确调用,初始化了实例上的getName方法(因为你的Person把方法定义在了实例上,而非原型上)。- 修正
Artist.prototype.constructor = Artist是为了保证原型链的完整性,否则tom.constructor会指向Person,不符合语义。
封装辅助函数(可选)
如果需要多次实现这种继承,可以封装一个辅助函数来简化操作:
function extend(Child, Parent) { Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; // 额外添加属性指向父构造函数,方便后续调用父类方法 Child.__super__ = Parent; } // 使用方式 extend(Artist, Person);
这样你就不用每次都写重复的原型链代码了,而且完全符合你提出的所有要求:通过instanceof测试、不修改现有构造函数、调用父类构造函数、无中间类、不依赖第三方库。
内容的提问来源于stack exchange,提问作者ferisj
相关产品推荐
相关产品推荐

