1、原型链继承
原型链继承基本思想就是让一个原型对象指向另一个类型的实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function SuperType() {
this.property = true
}
SuperType.prototype.getSuperValue = function () {
return this.property
}
function SubType() {
this.subproperty = false
}
SubType.prototype = new SuperType()
SubType.prototype.getSubValue = function () {
return this.subproperty
}
var instance = new SubType()
alert(instance.getSuperValue())
</script>
</head>
<body>
</body>
</html>
2、借用构造函数继承
此方法为了解决原型中包含引用类型值所带来的问题。
这种方法的思想就是在子类构造函数的内部调用父类构造函数,可以借助apply()和call()方法来改变对象的执行上下文
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function SuperType() {
this.colors = ['red', 'blue', 'green']
}
function SubType() {
// 继承SuperType
SuperType.call(this)
}
var instance1 = new SubType()
var instance2 = new SubType()
instance1.colors.push('black')
alert(instance1.colors)
alert(instance2.colors)
</script>
</head>
<body>
</body>
</html>
3、组合继承(原型+借用构造)
组合继承是将原型链继承和构造函数结合起来,从而发挥二者之长的一种模式。
思路就是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function SuperType(name) {
this.name = name
this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType(name, job) {
// 继承属性
SuperType.call(this, name)
this.job = job
}
// 继承方法
SubType.prototype = new SuperType()
SubType.prototype.constructor = SuperType
SubType.prototype.sayJob = function() {
alert(this.job)
}
var instance1 = new SubType('Jiang', 'student')
instance1.colors.push('black')
alert(instance1.colors) //["red", "blue", "green", "black"]
instance1.sayName() // 'Jiang'
instance1.sayJob() // 'student'
var instance2 = new SubType('J', 'doctor')
alert(instance2.colors) // //["red", "blue", "green"]
instance2.sayName() // 'J'
instance2.sayJob() // 'doctor'
</script>
</head>
<body>
</body>
</html>
这种模式避免了原型链和构造函数继承的缺陷,融合了他们的优点,是最常用的一种继承模式。
4、原型式继承
借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function object(o) {
function F() {}
F.prototype = o
return new F()
}
var person = {
name: 'Jiang',
friends: ['Shelby', 'Court']
}
var anotherPerson = object(person)
alert(anotherPerson.friends)
</script>
</head>
<body>
</body>
</html>
5、寄生式继承
寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script>
function createAnother(o) {
var clone = Object.create(o) // 创建一个新对象
clone.sayHi = function() { // 添加方法
alert('hi')
}
return clone // 返回这个对象
}
var person = {
name: 'Jiang'
}
var anotherPeson = createAnother(person)
anotherPeson.sayHi()
</script>
</head>
<body>
</body>
</html>
6、寄生组合式继承
在前面说的组合模式(原型链+构造函数)中,继承的时候需要调用两次父类构造函数。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script>
function SuperType(name) {
this.name = name
this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType(name, job) {
// 继承属性
SuperType.call(this, name)
this.job = job
}
// 继承
SubType.prototype = Object.create(SuperType.prototype)
// 修复constructor
SubType.prototype.constructor = SubType
var instance = new SubType('Jiang', 'student')
instance.sayName()
//ES6新增了一个方法,Object.setPrototypeOf,可以直接创建关联,而且不用手动添加constructor属性。
// 继承
Object.setPrototypeOf(SubType.prototype, SuperType.prototype)
alert(SubType.prototype.constructor === SubType)
</script>
</head>
<body>
</body>
</html>