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

原型链中`new person()`与`person.prototype`的区别及继承方式疑问

关于原型继承两种方式的区别与可行性分析

好问题!先直接给你答案:person1.prototype = person.prototype确实能让子类实例访问到父类原型的方法,但这是一种非常不推荐的做法,副作用极大。接下来我详细拆解这两种方式的核心区别,帮你彻底搞懂原型链在这里的运作逻辑:

1. 使用 person1.prototype = new person() 的原型链逻辑

这种方式是早期JS实现继承的常见写法,它的运作方式是:

  • 创建一个父类person的实例对象,将这个实例赋值给子类person1的原型。
  • 此时原型链的结构是:person1Inst(子类实例) → person1.prototype(父类实例) → person.prototype(父类原型) → Object.prototype → null。
  • 好处是:子类原型和父类原型是两个独立的对象,你给子类原型添加方法(比如tellMyAge)时,只会影响子类及其实例,不会污染父类的原型。
  • 小缺陷:如果父类构造函数包含副作用(比如初始化了一些实例属性、执行了其他逻辑),这些会被带到子类原型上。比如如果父类构造函数是function(name) { this.myName = name; this.log = () => console.log('hi') },那么new person()创建的实例会带有myName(值为undefined)和log方法,这些会变成子类所有实例共享的属性(不过在你的例子里这个问题不明显)。

2. 使用 person1.prototype = person.prototype 的问题

这种写法看似能让子类继承父类原型方法,但本质是让子类原型和父类原型指向同一个引用对象,带来的问题非常严重:

  • 当你给person1.prototype添加新方法(比如tellMyAge)时,这个方法会直接被加到person.prototype上,导致所有父类的实例也能访问到这个方法。比如你创建var p = new person("Bob"),p.tellMyAge()居然能执行,这完全破坏了子类和父类的边界。
  • 你无法区分原型上的方法是父类原生的还是子类添加的,因为它们都在同一个对象上,后期维护会变得一团糟。
  • 原型链结构变成:person1Inst → person.prototype(父类原型) → Object.prototype → null,相当于子类没有自己独立的原型空间,完全和父类共享,这根本不是真正的继承,而是“共享原型”。

更规范的替代方案

为了避免上述两种方式的缺陷,更推荐使用Object.create()来实现原型继承:

// 创建一个以父类原型为原型的空对象,作为子类原型
person1.prototype = Object.create(person.prototype);
// 手动修正constructor指向(因为Object.create会丢失子类的constructor引用)
person1.prototype.constructor = person1;

// 之后再添加子类自己的方法
person1.prototype.tellMyAge = function () { console.log(this.age); }

这种方式既保证了正确的原型链(子类实例 → 子类原型 → 父类原型),又避免了父类构造函数的副作用,同时不会污染父类原型,是ES6之前实现继承的标准写法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:57:15