JavaScript继承
· 2 min read
每个函数都会创建一个 prototype 属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。
默认情况下,所有原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数。
#
原型链const Fn = function () {};Fn.prototype.name = "Lex";Fn.prototype.hobbies = ["Coding", "JavaScript", "Eating"];Fn.prototype.sayHi = function () { console.log("Hello,World");};
const o = new Fn();o.hobbies.push("Gaming");const obj = new Fn();console.log(obj.hobbies); // [ 'Coding', 'JavaScript', 'Eating', 'Gaming' ]
#
盗用数据结构包含引用值的原型链继承导致 👆 问题,而且不能在实例化时给父类构造函数传参。
const Father = function (name) { this.name = name; this.sayHi = function () { console.log(`Hello ${this.name}`); };};Father.prototype.sayHey = function () { console.log(`Hey Lex`);};
const Son = function () { Father.call(this, "Alex");};
const s1 = new Son();console.log(s1.name); // Alexconsole.log(s1.sayHi()); // undefinedconsole.log(s1.sayHey()); // TypeError not a function
原理就是在实例化时调用父类构造函数,形成独立的子函数 context,因此函数在执行时不能复用(每个 instance 都要重新声明 methods)。
#
组合思路是通过盗用构造函数继承实例属性,使用原型链继承原型上的属性和方法。
warning
// 继承方法Son.prototype = new Father();
#
原型式继承利用 Object.create()
API
function object(o) { function F() {} F.prototype = o; return new F();}
Object.create()
本质是原型式继承的规范封装。
const person = { name: "Lex", hobbies: ["sleeping", "eating", "coding"],};
const anotherPerson = Object.create(person);anotherPerson.name = "bb";anotherPerson.hobbies.push("film");console.log(anotherPerson.hobbies);
属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的。
#
寄生式继承function createAnother(original) { let clone = object(original); // 通过调用函数创建一个新对象 clone.sayHi = function () { // 以某种方式增强这个对象 console.log("hi"); }; return clone; // 返回这个对象}
显然,增强的 methods 依然无法复用。
#
寄生式组合最佳实践
function inheritPrototype(subType, superType) { let prototype = object(superType.prototype); // 创建对象 prototype.constructor = subType; // 增强对象 subType.prototype = prototype; // 赋值对象}
function SuperType(name) { this.name = name; this.colors = ["red", "blue", "green"];}SuperType.prototype.sayName = function () { console.log(this.name);};function SubType(name, age) { SuperType.call(this, name); this.age = age;}inheritPrototype(SubType, SuperType);SubType.prototype.sayAge = function () { console.log(this.age);};