原型继承的正确方式及Student.prototype两种赋值写法的差异
构造函数原型继承的两种写法差异解析
先明确:在你给出的构造函数场景中,Student.prototype = Object.create(Person.prototype)是实现原型继承的正确方式,而直接赋值Student.prototype = Person.prototype会破坏子类与父类的原型隔离,引发逻辑问题。两者核心差异如下:
一、直接赋值 Student.prototype = Person.prototype 的问题
这种写法让Student.prototype直接指向Person.prototype的同一个内存引用,相当于子类和父类共用同一份原型对象,带来两个关键问题:
- 子类方法污染父类原型
当你给Student.prototype添加子类专属方法时,这个方法会被直接添加到Person.prototype上,导致所有Person实例也能调用该方法,完全违背子类方法的专属特性:Student.prototype = Person.prototype; Student.prototype.study = function() { console.log('Studying'); }; const p = new Person('Alice', 1990); p.study(); // 输出"Studying",不符合预期 - 实例类型判断混乱
由于Student.prototype和Person.prototype是同一个对象,instanceof的类型判断会失效:父类的实例会被误判为子类实例,完全打乱了类的层级关系:const p = new Person('Alice', 1990); p instanceof Student; // 返回true,逻辑错误
二、Student.prototype = Object.create(Person.prototype) 的正确逻辑
Object.create(Person.prototype)会创建一个全新的空对象,这个新对象的原型(__proto__)指向Person.prototype,再将这个新对象赋值给Student.prototype,完美解决了上述问题:
- 原型隔离,子类方法不污染父类
Student.prototype是独立的对象,给它添加子类专属方法时,只会作用于子类实例,不会影响父类:Student.prototype = Object.create(Person.prototype); Student.prototype.study = function() { console.log('Studying'); }; const p = new Person('Alice', 1990); p.study(); // 报错:p.study is not a function,符合预期 - 原型链层级清晰,类型判断正常
子类实例的原型链为:Student实例 -> Student.prototype -> Person.prototype -> Object.prototype,既能继承父类原型的方法(比如sayHi),又能拥有自己的专属方法,同时instanceof判断完全准确:const s = new Student('Bob', 2000, 'Computer Science'); s instanceof Student; // true s instanceof Person; // true const p = new Person('Alice', 1990); p instanceof Student; // false,正确区分父子类实例 - 补充:修正构造函数指向
用这种写法后,Student.prototype.constructor会默认指向Person(因为新对象的原型是Person.prototype),需要手动修正,让子类实例的构造函数指向自身:Student.prototype.constructor = Student;
内容的提问来源于stack exchange,提问作者Vsevolod IV
相关产品推荐
相关产品推荐

