js 继承(一)之原型链、借用构造函数、组合继承
前言 …
Just we
原型链
基本思想利用原型让一个引用类型继承另一个引用类型的属性和方法
function Father() {
this.last_name = '张'
}
Father.prototype.sayLast_Name = function () {
console.log('我的姓:' + this.last_name)
}
function Son() {
this.first_name = '三'
}
Son.prototype = new Father()
Son.prototype.sayFirst_Name = function () {
console.log('我的名字:'+ this.first_name)
}
var son = new Son()
son.sayLast_Name()
son.sayFirst_Name()
以上代码定义了两个类型:Father 和 Son 。每个类型有一个属性和一个方法。Son 继承了 Father,该继承是通过创建 Father 实例,将该实例赋给 Son.prototype 实现。实现的本质是重写 Son 原型对象,代之以 Father 的实例
这个例子中的实例以及构造函数和原型之间的关系如下图
原型链的问题
function Father() {
this.hobbies = ['吃饭', '睡觉', '打豆豆']
}
function Son() {
}
Son.prototype = new Father()
var son_1 = new Son()
son_1.hobbies.push('学习')
console.log(son_1.hobbies) // ["吃饭", "睡觉", "打豆豆", "学习"]
var son_2 = new Son()
console.log(son_2.hobbies) // ["吃饭", "睡觉", "打豆豆", "学习"]
- 在原型对象上定义的属性,会被所有实例共享
- 在创建子类型 Son 的实例时,不能向超类型 Father 的构造函数中传递参数
借用构造函数
借用子类型构造函数的内部调用超类型的构造函数
function Father(last_name) {
this.last_name = last_name
this.hobbies = ['吃饭', '睡觉', '打豆豆']
}
function Son(last_name, first_name) {
Father.call(this, last_name)
this.first_name = first_name
}
var son_1 = new Son('张', '三')
son_1.hobbies.push('学习')
console.log(son_1.hobbies) // ["吃饭", "睡觉", "打豆豆", "学习"]
var son_2 = new Son('张', '五')
console.log(son_2.hobbies) // ["吃饭", "睡觉", "打豆豆"]
通过调用 call 方法,在创建的 Son 的实例环境下调用了 Father 的构造函数,这样一来,我们在创建 Son 的实例对象就可以执行 Father 的定义的所有对象的初始化代码。Son 的每个实例对象就会拥有自己的 hobbies 属性,以上代码也可以看出创建子类型 Son 的实例时,可以向超类型 Father 的构造函数中传递参数。
借用构造函数问题
function Father() {
}
Father.prototype.sayHello = function () {
console.log('Hello JavaScript')
}
function Son() {
Father.call(this)
}
var son = new Son()
son.sayHello() //error
方法和函数都在构造函数中定义,所用类型只能使用构造函数模式,没有函数复用
组合继承
组合继承结合上述原型链和借用构造函数的优点,避免他们的缺陷
直接上代码
function Father(last_name) {
this.last_name = last_name
this.hobbies = ['吃饭', '睡觉', '打豆豆']
}
Father.prototype.sayName = function () {
console.log(this.last_name + this.first_name)
}
function Son(last_name, first_name) {
Father.call(this, last_name)
this.first_name = first_name
}
Son.prototype = new Father()
var son_1 = new Son('张', '三')
son_1.hobbies.push('学习')
console.log(son_1.hobbies) // ["吃饭", "睡觉", "打豆豆", "学习"]
var son_2 = new Son('张', '五')
console.log(son_2.hobbies) // ["吃饭", "睡觉", "打豆豆"]
son_1.sayName() // 张三