温故而知新 XD
关于原型的几个知识要点:
- 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。
- 每当代码读取某个对象的某个属性时,都会进行一次搜索,目标是具有给定名字的属性。搜索从对象实例本身开始。如果在实例中找到了该属性,则返回该属性的值;如果没有找到,则搜索内部指针指向的原型对象,若找到,则返回属性值;若没找到,继续搜索原型的原型...
实现
给出父类 Animal,实现子类Cat:
function Animal (name) {
this.name = name
this.brother = 'Tony'
}
Animal.prototype.eat = function (thing) {
console.log(this.name + ' eat ' + thing);
}
组合继承(结合原型链和借用构造函数,不太完美)
function Cat (name) {
Animal.call(this,name) // 借用构造函数,继承父类属性
this.sister = 'May'
}
Cat.prototype = new Animal() // 原型链,继承父类方法
/* 在prototype继承了父类实例的全部属性,存在冗余。属性的继承已经在构造函数内通过调用父类构造函数实现。
实际上,子类的prototype需要的只是父类实例中指向父类原型的内部指针。*/
console.log(Cat.prototype)
// {name: undefined(冗余), brother: "Tony"(冗余), constructor: ƒ}
Cat.prototype.constructor = Cat // 指定构造函数
var tom = new Cat('Tom')
寄生组合继承(完美)
function Cat (name) {
Animal.call(this,name)
this.sister = 'May'
}
function getPrototype (_class) {
function F () {}
F.prototype = _class.prototype
return new F() /* 返回一个实例,该实例没有继承_class的属性,
解决了组合继承中的问题 */
}
Cat.prototype = getPrototype(Animal)
console.log(Cat.prototype)
// {constructor: ƒ}
Cat.prototype.constructor = Cat