关于JS的六种继承

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43572937/article/details/102642673

持续更新中.....

继承一共有六种方式:
分别是:
1. 原型链继承
2. 借用构造函数继承
3. 组合继承
4. 原型式继承
5. 寄生式继承
6. 寄生组合式继承

1. 原型链继承

原型链继承是实现继承的主要方法。

  • 基本思想: 利用原型让一个引用类型继承另外一个引用类型的属性和方法。

了解一下构造函数,原型和实例的关系?

  • 每个构造函数都有一个原型对象,原型对象都包含指向构造函数的指针(prototype),而实例包含了指向原型的指针(__proto__
    实例的__proto__属性等于构造函数的prototype属性
    实例 -> 原型 -> 构造函数

原型链的基本概念?

  • 如果试图引用对象(实例instance)的某个属性,首先会从对象内部开始寻找该属性,直至找不到,然后才会到对象的原型(instance.prototype)去寻找该属性。
  • 如果原型对象指向另一个类型的实例,即constructor1.prototype = instance2

如果试图引用constructor1构造的实例instance1的某个属性p1:

  • 首先会在instance1内部找一遍
  • 接着在instance.__proto__(即constructor1.prototype)中找一遍,实际上constructor1.prototype就是instance2,也就是说在instance2找到了p1属性。
  • 如果instance2还是没有p1属性,就会持续在instance2.__proto__(即constructor2.prototype)中寻找,一直这样下去,直到找到为止。或者找到Object的原型对象上(null
  • 这样就形成路径了:instance1-->instance2-->....-->Object.prototype
  • 类似链状的结构称为“原型链
function SuperType(){
	this.property = true;
}
SuperType.prototype.getSuperValue = function(){
	return this.property;
}
function SubType(){
	this.subProperty = false;
}

// 继承了SuperType   子类型的原型等于父类型的实例。完成原型链继承
SubType.prototype = new SuperType();

// 添加新方法
SubType.prototype.getSubValue(){
	return this.subProperty;
}

// 重写父类型中的方法
SubType.prototype.getSuperValue(){
	return false;
}

let instance = new SubType();
instance.getSuperValue();   // false
  • 上述代码中。第一个方法getSubValue()被添加到了SubType中。而getSuperValue()是原型链中已经存在的一个方法,但是重写这个方法会屏蔽原来的方法。
  • 也就是说当通过SuperType的实例调用getSuperValue()时,还会继续调用原来的那个方法
    ⚠️通过原型链继承时,不能使用对象字面量创建原型方法。这样会重写原型链
    如:
function SuperType(){
	this.property = true;
}
SuperType.prototype.getSuperValue(){
	return this.property;
}

function SubType (){
	this.subProperty = false;
}
 // 继承SuperType
 SubType.prototype = new SuperType();

// 使用字面量添加新方法会导致上一条代码无效(即取代)
SubType.prototype = {
	getSubValue: function(){
		return this.subProprty;
	},
	someMethod: function(){
		return false;
	}
}

let instance = new SubType();
instance.getSuperValue();    // 报错

2. 借用构造函数继承

构造函数继承有时候又叫做“伪造对象或经典继承”

  • 基本思想: 在子类型构造函数的内部调用父类型构造函数。
  • 但是,一般函数只不过是在特定环境中执行代码的对象,因此可以通过使用applycall方法可以在新创建的对象上执行构造函数。
    示例:
function SuperType(){
	this.arr = [1,2,3];
}
// 借用构造函数继承
function SubType(){
	// 继承SuperType
	SuperType.call(this);
}

let instance1 = new SubType();
instance1.arr.push(4);
instance1.arr;  // [1,2,3,4]

let instance2 = new SubType();
instance2.arr;    // [1,2,3]
  • 在上述代码中,在子类型的内部调用了父类型的构造函数
  • 使用了call方法,实际上是在新创建的SubType实例环境下调用了SuperType构造函数
  • 这样,就会在新的SubType对象上执行SuperType()函数定义的所有对象初始化代码。结果SubType的每个实例都会具有SuperType对象中的属性或方法的副本

这让我想到了,ES6中类的继承为什么要在子类的构造函数中执行super()方法,就是这个道理。

构造函数继承相对原型链继承的一个优势?

  • 可以在子类型的构造函数中向父类型的构造函数传递参数。

示例:

function SuperType(name){
	this.name = name;
}

function SubType(){
	// 继承 SuperType,同时传递参数
	Supertype.call(this, 'Jack');

	// 实例属性 
	this.age = 24;
}

let instance = new SubType();
instance.name;   // Jack
instance.age;   // 24

3. 组合继承

组合继承有时候又叫“伪经典继承”,是将原型链继承借用构造函数继承组合到一起的继承。

  • 基本思想: 使用原型链实现对原型属性的方法的继承,通过即用构造函数来实现对实例属性的继承。这样即通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。

示例:

function SuperType(name){
	this.name = name;
	this.arr = [1,2,3];
}

SuperType.prototype.sayName = fuction(){
	alert(this.name);
}

function SubType(name , age){
	// 继承SuperType
	SuperType.call(this, name);
	this.age = age;
}

// 继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge(){
	alert(this.age);
}

let instance1 = new SubType('Jack', 24);
instance1.arr.push(4);
instance1.sayName();    // Jack
instance1.sayAge();   // 24
instance!.arr;   //  [1,2,3,4]

let instance2 = new SubType("Mary", 23);
instance2.arr;    // [1,2,3]
instance2.sayName();   // Mary
instance2.sayAge();     // 23

  • 上述代码中,SuperType构造函数指定两个属性:namearrSuperType的原型定义了sayName()方法。
  • SubType构造函数在调用SuperType构造函数时传入了name参数,紧接着定义了sayAge()方法
  • 这样就可以让两个不同的SubType实例分别拥有自己的属醒(arr,name,age
  • 也可以使用相同的方法(sayName(), sayAge())

4.原型式继承

原型式继承要求必须有一个对象作为另一个对象的基础。

  • 基本思想: 借助原型基于已有的对象创建新的对象。

给出函数:

function object(o){

}

通过Object.create()方法实现原型式继承。

  • 这方法接收两个参数
  1. 一个用作新对象的原型对象(可选)
  2. 另外一个是一个对象,为新对象添加额外的属性。

示例:

let person = {
	name: 'Jack',
	age: 24,
	friends: [1,2,3]
}

// 继承person
let otherPerson = Object.create(person,{
	name: {
		value: "Mary"
	}
})

alert(otherPerson.name);    // Mary

5.寄生式继承

  • 基本思想:创造一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象。

示例:

function createOther(obj){
	let clone = 
}

猜你喜欢

转载自blog.csdn.net/weixin_43572937/article/details/102642673