You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

超类构造方法继承疑问:子类为何继承超类新增原型方法?

问题解答

你的理解完全正确

  • 创建User构造函数,并在其原型上添加info()方法
  • 通过User.call(this, name)实现构造函数继承,让UserAdmin实例拥有User的实例属性
  • 使用Object.create(User.prototype, {...})让UserAdmin.prototype继承User.prototype的方法,同时修正constructor指向以保持一致性

为什么someFunc会被UserAdmin实例继承?

因为Object.create(User.prototype)创建的新对象,其内部原型(__proto__)直接指向原User.prototype对象,而非复制一份快照。这意味着当后续给User.prototype新增someFunc时,UserAdmin的实例依然能通过原型链找到这个方法——毕竟它的原型链最终还是连着User.prototype本身。

如何避免继承超类原型后续新增的函数?

核心思路是复制User.prototype的当前属性到独立对象,切断和原User.prototype的原型链关联,这样后续User.prototype的修改就不会影响UserAdmin的原型。

方法1:用Object.assign快速复制

function User(name) {
  this.name = name;
}
User.prototype.info = function () {
  return this.name;
};

function UserAdmin(name, privileges) {
  User.call(this, name);
  this.privileges = privileges;
}
// 复制User.prototype当前的所有属性到新对象,同时设置constructor
UserAdmin.prototype = Object.assign({}, User.prototype, {
  constructor: {
    value: UserAdmin,
    enumerable: false,
    configurable: true,
    writable: true,
  }
});

// 后续给User原型新增方法
User.prototype.someFunc = function() {
    console.log("I am created in User prototype")
}

let meAdmin = new UserAdmin("meAdmin", "edit");
meAdmin.someFunc()  // 报错:meAdmin.someFunc is not a function

方法2:手动遍历复制(兼容旧环境)

如果环境不支持Object.assign,可以手动遍历User.prototype的可枚举属性:

function User(name) {
  this.name = name;
}
User.prototype.info = function () {
  return this.name;
};

function UserAdmin(name, privileges) {
  User.call(this, name);
  this.privileges = privileges;
}

// 创建一个空原型的对象,避免继承Object.prototype的冗余属性
UserAdmin.prototype = Object.create(null);
// 复制User.prototype的可枚举属性
for (let key in User.prototype) {
  if (User.prototype.hasOwnProperty(key)) {
    UserAdmin.prototype[key] = User.prototype[key];
  }
}
// 修正constructor属性
Object.defineProperty(UserAdmin.prototype, 'constructor', {
  value: UserAdmin,
  enumerable: false,
  configurable: true,
  writable: true,
});

User.prototype.someFunc = function() {
    console.log("I am created in User prototype")
}

let meAdmin = new UserAdmin("meAdmin", "edit");
meAdmin.someFunc()  // 报错:meAdmin.someFunc is not a function

注意点

  • 这种方式是静态复制,如果后续User.prototype上的原有方法被修改,UserAdmin.prototype里的对应方法不会同步更新——因为是独立的副本。
  • 如果你需要保持原原型方法的同步更新,那还是得用原型链继承;但如果要彻底隔离后续新增方法,复制属性的方式就是最优解。

内容的提问来源于stack exchange,提问作者Boris Borais

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 16:52:40