JS中的常用继承方式总结


JS本身是基于面向对象开发的编程语言,所以学习JS的时候基本上就是学习它有哪些类,学习这些类的实例,实例可以调用类原型提供的方法,实例还有自己私有的属性和方法。
面向对象想编程中有一个非常重要的知识点 -- 类:封装、继承、多态

  • 封装 :类也是一个函数,把实现一个功能的代码进行封装,以此实现“低耦合高内聚”
  • 多态:重载、重写
    • 重写:子类重写父类上的方法(把随着继承运行的)
    • 重载: 相同的方法,由于参数或者返回值不同,具备了不同的功能(JS不具备严格意义下的重载的),JS中的重载指同一个方法,根据传参的不同,依次判断处理,实现不同的功能。
  • 继承 = > 继承的目的:让子类的实例同时具备父类中的私有属性和公共方法

JS中的继承方法一 :原型继承

原型继承:让子类的原型等于父类的实例 => Child.prototype = new Parent;(实现继承)

特点:

  1. 父类中私有的和公有的属性和方法,最后都变为子类实例的公有的属性和方法
  2. 和其他语言不同的是,原型继承并不会把父类的属性和方法“拷贝”给子类,而是让子类实例基于__proto__(原型链)找到自己定义的属性和方法–“指向/查找”方式的。
  • c1.__proto__.xxx = xxx;修改子类原型(原有父类的实例)中的内容,内容被修改后,对子类的其他实例有影响,对父类的其他实例没有影响想
  • c1.__proto__.__proto__.xxx = xxx;直接修改的是父类的原型,这样不仅会影响其他子类的实例,也会影响其他父类的实例。

EG:

function Parent(){
	this.x = 100;
};
Parent.prototype.getX = function getX(){
	return this.x;
};
function Child(){
	this.y = 200;
};
Child.prototype = new Parent;//实现继承
Child.prototype.constructor = Child//为了保证Child原型的完整性,手动添加上constructor 
Child.prototype.getY = function getY(){
	return this.y;
};
let c1 = new Child;

图例解析
在这里插入图片描述

  1. 缺点:
    1. 原型继承并不会把父类的属性和方法“拷贝”给子类,而是让子类实例基于__proto__(原型链)找到自己定义的属性和方法
    2. 会把父类公有的和私有的属性和方法,全部变成了子类实例公有的属性和方法
  2. 期望:
    1. 让父类私有的变成子类实例私有的
    2. 让父类公有的变成子类实例公有的

JS中的继承方法二 :call继承

  • 在子类的构函数中把父类当做普通方法执行(没有父类实例,父类原型上的那些东西也就和子类没有关系了)
  • Parent.call(this)中的this.x = 100,相当于给实例c1设置一个私有的属性x,属性值是100,相当于让子类的实例继承了父类的私有属性,并且变为了子类的私有属性,这就是"拷贝式"。
  • 特点:只能继承父类私有的,不能继承继承父类公有的
function Parent(){
	this.x = 100;
};
Parent.prototype.getX = function getX(){
	return this.x;
};
function Child(){
	Parent.call(this);
	this.y = 200;
};
Child.prototype.getY = function getY(){
	return this.y;
};
let c1 = new Child;

缺点:

  • 只能继承父类中私有的
  • 不能继承父类中公有的

JS中的继承方法三:寄生组合式继承

  • 理想的继承方式:父类私有的变为子类私有的,父类公有的变为子类公有的
  • 寄生组合式继承:CAll继承+另类原型继承
    • 核心点Child.prototype.__proto__ === Parent.prototype
    • 通过call继承可以把父类私有的变为子类私有,但是无法继承父类公有的
    • 通过把子类的原型链指向父类的原型,可以继承父类的公有办法,但是IE浏览器不支持修改__proto__, 所以利用:Child.prototype= Object.create(Parent.prototype)
    • 为了保证Child原型的完整性,手动加上Child.prototype.constructor = Child

EG:

function Parent(){
	this.x = 100;
};
Parent.prototype.getX = function getX(){
	return this.x;
};
function Child(){
	Parent.call(this);//继承父类的私有属性方法
	this.y = 200;
};

//Child.prototype.__proto__ === Parent.prototype //IE浏览器不支持

Child.prototype= Object.create(Parent.prototype);//继承父类的公有属性方法
Child.prototype.constructor = Child;// 为了保证Child原型的完整性
Child.prototype.getY = function getY(){
	return this.y;
};
let c1 = new Child;

图形解释:Child.prototype.__proto__ === Parent.prototype【IE浏览器不支持】在这里插入图片描述
图形解释:Child.prototype= Object.create(Parent.prototype)
在这里插入图片描述

知识扩展:Object.create(obj)

  • 创建一个空对象,让其原型链指向obj;obj为一个类的原型。
  • Object.create(Parent.prototype):创建一个空对象,让其原型链指向Parent的原型[prototype]

ES6中类的继承(extends Parent)

  • ES6中创建的类就是类,不能被当做普通函数执行,只能new执行
    • 不加new自执行函数会报错:“Uncaught TypeError: Class constructor Child cannot be invoked without ‘new’”
  • 继承: 子类 extends 父类 (类似于寄生组合是继承)
  • 继承后子类constructor第一行必须加上super(),类似于之前的call继承,super(100,200):
    • 相当于把Parent中的constructor执行,传递了100和200
    • 不加报错:‘Must call super constructor in derived class before accessing ‘this’ or returning from derived constructor’
//ES6中类和继承
class Parent{
	constructor (){
		this.x = 100;
	};
	//等价于:Parent.prototype.getX = function...
	getX(){
		return this.x;
	}
};
class Child  extends Parent{
	constructor (){
		super();//继承后子类constructor第一行必须加上super(),否则会报错。
    at new Child 
		this.y = 200;
	};
	getY(){
		return this.y;
	}
};
new Child();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值