1. 类式继承
首先我们从原型中来看
function Animal(){ }
let a1 = new Animal()
// 每一个对象属性,其隐式原型全部指向其父级的prototype原型
// 因为Animal是通过function构造出来的,所以其隐式原型指向Function的原型
console.log(Animal.__proto__ === Function.prototype); //true
// 根据Function原型和Object对象的原型关系,我们可以得到 这样一层关系
console.log(Animal.prototype.__proto__ === Object.prototype); // true
// 之后可以的到任何一个实例化的对象 其隐式原型(__proto__)都是指向其父级的原型(prototype)的
console.log(a1.__proto__ === Animal.prototype); //true
console.log(a1 instanceof Object); //true
console.log(a1.__proto__ === Object.protortpe) // false
// 基本结论: 任何一个实例化的对象其隐式原型(__proto__)都指向其父级的原型(protorypr)
// 为了证实一下
let temp = {}
console.lot(temp.__proto__ === Object.prototype) //true
// 原型链的产生,以及第一种方式继承的出现
console.log(a1.__proto__.__proto__ === Object.prototype); // true
复制代码
第一种继承方式 :让子对象的原型定向为一个父级的实例,这样子类的__proto__就指向了父类
function Animal (name){
this.name = 'animal'
this.say = function(){
console.log(this.name);
}
this.setName = function(name){
this.name = name
}
}
function Cat(name){ }
Cat.prototype = new Animal()
const RagaMuffin = new Cat()
RagaMuffin.say() // animal
RagaMuffin.setName('褴褛猫')
RagaMuffin.say() // 褴褛猫
console.log(RagaMuffin);
// 缺点: 父级属性共享,当修改父级属性会影响到其他实例
RagaMuffin.__proto__.name = '褴褛猫'
const Tabby = new Cat()
Tabby.say() // 褴褛猫
Tabby.setName("虎斑猫")
Tabby.say() // 虎斑猫
console.log(Tabby);
复制代码
优点:
- 直观简便的继承了父级的方法
缺点:
- 无法接收子类的动态参数
- 父级属性共享
2.构造函数继承
function Animal (name){
this.name = name
this.say = function(){
console.log(this.name);
}
}
// 对原型添加方法
Animal.prototype.eat = function(){
console.log(this.name , '吃鱼');
}
// 创建子类
function Cat(name){
Animal.call(this, name)
}
const RagaMuffin = new Cat('褴褛猫')
RagaMuffin.say() // 褴褛猫
RagaMuffin.eat() // RagaMuffin.eat is not a function
复制代码
缺点:
- 构造函数继承没能继承父级原型上的方法
3. 组合继承
结合上述两种继承方式的方法叫做组合继承
function Animal (name){
this.name = name
this.say = function(){
console.log(this.name);
}
Animal.prototype.eat = function(){
console.log(this.name , '吃鱼');
}
}
function Cat(name){
Animal.call(this, name)
}
Cat.prototype = new Animal()
const RagaMuffin = new Cat('褴褛猫')
console.loe(RageMyffin)
RagaMuffin.say() // 褴褛猫
RagaMuffin.eat() // 褴褛猫 吃鱼
复制代码
缺点:
- 子类无法传递动态参数给父类
- 父类的构造函数调用了两次
4. 原型式继承
function createObject(o) {
// 创建临时类
function f() {
}
// 修改类的原型为o, 于是f的实例都将继承o上的方法
f.prototype = o
return new f()
}
const obj = {
name: 'chang'
}
const chang = createObject(obj)
console.log(chang.name); // chang
复制代码
缺点: 共享了属性和方法,没有解决类式继承的缺点
5.寄生继承
创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象
function createAnother(original) {
var clone = Object.create(original); //通过调用函数创建一个新对象
clone.say = function () { //以某种方式来增强这个对象
console.log('Hello');
};
return clone; //返回这个对象
}
const obj = {
name: 'chang',
testArr: [1, 2, 3]
}
const newObj = createAnother(obj)
console.log(newObj.name); // chang
newObj.say() // Hello
newObj.testArr.push(4)
console.log(newObj.testArr); //(4) [1, 2, 3, 4]
复制代码
6. 寄生组合继承
function inherit(child, parent) {
// 获取父级的原型
const parent_proto = Object.create(parent.prototype)
// 子类继承父类的原型
child.prototype = parent_proto
// 父类的构造函数指向child,防止污染
parent_proto.constructor = child
}
// 父类
function Animal(name) {
this.name = name
this.say = function () {
console.log(this.name);
}
Animal.prototype.eat = function () {
console.log(this.name, '吃鱼');
}
}
// 子类
function Cat(name) {
Animal.call(this, name)
}
inherit(Cat, Animal)
const RagaMuffin = new Cat('褴褛猫')
console.log(RagaMuffin);
RagaMuffin.say() // 褴褛猫
RagaMuffin.eat()
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END