js:实现继承的几种方法(包括es6)

js的继承方式有很多,比如

一、借用构造函数继承(call,apply,bind)

1.介绍

利用call,apply,bind借用父类的构造函数

2.实现
function Animal (name) {
	this.name = name
	this.showName = function () {
		alert(this.name)
	}
}
function Cat () {
	// apply用法:传参传一个数组
	Animal.apply(this, [name])
}
var cat = new Cat('飞翔的哔哔鸡')
cat.showName()
 // call用法:传参传一个字符串
Animal.call(this, name)
 // bind用法:先调用再传参
Animal.bind(this)(name)
3.优缺点
1)优点

简单明了

2)缺点

无法继承原型链上的属性和方法

二、原型链继承

1.介绍

利用原型链来实现继承,父类的一个实例作为子类的原型,也就是 子构造函数.prototype = new 父构造函数()

2.实现
function Animal (name) {
	this.name = name
	this.friends = ['小狗','小猫']
	this.showName = function () {
		alert(this.name)
	}
}
function Cat () {
}
Cat.prototype = new Animal()
// 注意这里new Animal()生成的父类对象并没有constructor属性,故需添加上
Cat.prototype.constructor = Cat
3.优缺点
1)优点

容易实现

2)缺点
//当父类中包含引用类型属性值时,其中一个子类的多个实例中,只要其中一个实例引用属性只发生修改一个修改,其他实例的引用类型属性值也会立即发生改变
//原因是父类的属性变成子类的原型属性
var cat1 = new Cat()
var cat2 = new Cat()
cat1.friends.push('小猪')
console.log(cat1.friends) //['小狗','小猫','小猪']
console.log(cat2.friends) //['小狗','小猫','小猪']

三、组合式继承(原型链继承+借用构造函数继承)

1.介绍

实际开发比较常用(当然不考虑兼容性的话我更喜欢es6的extend)

2.实现
function Animal (name) {
	this.name = name
	this.showName = function () {
		alert(this.name)
	}
}
function Cat () {
	// apply用法:传参传一个数组
	Animal.apply(this, [name]) //第二次调用
}
Cat.prototype = new Animal() //第一次调用
var cat = new Cat('飞翔的哔哔鸡')
cat.showName()
3.优缺点
1)优点

解决了构造继承和原型链继承的两个问题

2)缺点

父类的构造函数被调用两次,实际上子类上会拥有超类的两份属性,只是子类的属性覆盖了超类的属性

四、es6的extends

1.介绍

实际开发比较常用,写法更加面向对象,原理还是原型链

2.实现
class Animal {
	constructor (name) {
		this.name = name
	}
	showName () {
		alert(this.name)
	}
}
class Cat extends Animal {
	constructor (name) {
		super(name)
		this.type = '宠物'
	}
}
var cat = new Cat('飞翔的哔哔鸡')
cat.showName()
3.super关键字

super这个关键字,既可以当作函数使用,也可以当作对象使用。当作函数使用时,super代表父类的构造函数,并在子类中执行Parent.apply(this),从而将父类实例对象的属性和方法,添加到子类的this上面。以下三点需要特别注意:

1)子类必须在constructor方法中调用super方法,如果子类没有定义constructor方法,constructor方法以及其内部的super方法会被默认添加。
2)在子类的constructor方法中,只有调用super之后,才可以使用this关键字,否则会报错。
3)super作为对象时,在子类中指向父类的原型对象。即super=Parent.prototype。

例子:

class Animal {
	constructor (name) {
		this.name = name
	}
	showName () {
		alert(this.name)
	}
}
class Cat extends Animal {
	constructor (name) {
		super(name)
	}
	sayMy () {
		super.showName()
	}
}
var cat = new Cat('飞翔的哔哔鸡')
cat.sayMy() //飞翔的哔哔鸡
4.static关键字

在一个方法前加上关键字static,就表示该方法不会被实例继承,但是父类的静态方法,会被子类继承。

class Animal {
	static showWhat (name) {
		alert(name)
	}
	showName (name) {
		showWhat(name)
	}
}
class Cat extends Animal {}
Cat.showWhat('小猪') //小猪

var an = new Animal()
an.showWhat('小狗') //Uncaught TypeError: an.showWhat is not a function
  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lvan的前端笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值