0
点赞
收藏
分享

微信扫一扫

日常学习笔记 - JS中的三种继承方式

毅会 2022-04-26 阅读 63

一、理解

对于继承最基础的理解,就是解决了一个问题:假定我们已有一个构造函数(工厂函数)A,现在想要声明一个构造函数B,而B是对A的补充,除了具备A拥有的所有属性和方法外,还具备B自身独有的一些属性和方法,此时我们可以让B直接继承A的属性和方法,再对B进行补充,就可以完美达到目的。


二、三种继承方式

1.组合继承

// 声明一个工厂函数Parent
function Parent(value){
	this.name = value;
}
// 在原型上挂载方法
Parent.prototype.getName = function(){
	console.log(this.name);
}

// 声明一个工厂函数Child
function Child(value, age){
	Parent.call(this,value); 		 // 这一步执行后继承Parent的属性
	this.age = age;					 // 添加Child独有的属性
};
Child.prototype = new Parent(); 	 // 继承Parent的原型,此时Child实例可以访问Parent原型上的属性和方法
Child.prototype.getAge = function(){ // 对Child的原型进行补充
	console.log(this.age);
};
Child.prototype.constructor = Child; // 将Child的构造器指向自己

// 创建一个Child实例
const child1 = new Child("杰克", 18);

// 打印该实例结果如下图

在这里插入图片描述

// 此时可以看到实例child1正确地继承了Parent的属性和原型,能够直接调用Child原型和Parent原型上的方法。
child1.getName();  		  // "杰克"
child1.getAge();   		  // 18
child1 instanceof Child;  // true
child1 instanceof Parent; // true
child1 instanceof Object; // true

2.寄生组合继承

第1点的末尾提到组合继承的缺点是由于继承途中调用了父类的构造函数导致的,寄生组合继承则优化了这一点。

// 声明一个工厂函数Parent
function Parent(value){
	this.name = value;
}
// 在原型上挂载方法
Parent.prototype.getName = function(){
	console.log(this.name);
}

// 声明一个工厂函数Child
function Child(value, age){
	Parent.call(this,value); 		// 这一步执行后继承Parent的属性
	this.age = age; 				// 添加Child独有的属性
};
Child.prototype = Object.create(Parent.prototype, {
	constructor:{
		value: Child,
		enumerable: false,
		writable: true,
		configurable: true
	}
})
Child.prototype.getAge = function(){ // 对Child的原型进行补充
	console.log(this.age);
};

// 创建一个Child实例
const child1 = new Child("杰克", 18);

// 打印该实例结果如下图

在这里插入图片描述

child1.getName();  		  // "杰克"
child1.getAge();   		  // 18
child1 instanceof Child;  // true
child1 instanceof Parent; // true
child1 instanceof Object; // true

3.Class继承

Class继承是ES6中被提出来的新规范,可以直接使用class关键字进行继承操作。

// 声明一个父类
class Parent{
	constructor(value){
		this.name = value;
	};
	getName(){
		console.log(this.name);
	}
}

// 声明一个子类继承父类
class Child extends Parent{
	constructor(value, age){
		super(value); 		// spuer函数在这里的作用是把Parent的构造函数中的this指向改为Child实例,传递的参数则是Parent的构造函数所需的参数
		this.age = age;
	}
	getAge(){
		console.log(this.age);
	}
}

// 创建一个Child实例
const child1 = new Child("Susan", 20);

// 打印该实例结果如下图

在这里插入图片描述

child1.getName();  		  // "Susan"
child1.getAge();   		  // 20
child1 instanceof Child;  // true
child1 instanceof Parent; // true
child1 instanceof Object; // true

三、补充

  • __proto__ 称作隐式原型,对象才有该属性,指向当前对象的原型对象(父类)。
  • prototype 称作显式原型,显式原型指向当前构造函数的原型对象(父类)。
Child.prototype;					  // Parent{}
child1.__proto__;					  // Parent{}
Child.prototype === child1.__proto__; // true
  • 原型:简单理解原型就是当前实例对象继承来源的构造函数。
  • 原型链:原型链是一个虚拟的模型,说的是当访问实例的某个属性或方法时,会依照实例本身、隐式原型(父类)、隐式原型的父类(爷类)…的顺序逐步往上查找,这个过程中访问的这些节点构成我们所说的原型链。
举报

相关推荐

0 条评论