原型链
定义:每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(__proto__),层层向上直到一个对象的原型对象为 null
。
prototype:(原型对象)函数独有的属性
constructor:(构造函数)每个函数都有一个原型对象,该原型对象有一个 constructor 属性,指向创建对象的函数本身。
__proto__:(原型)对象的私有属性(在 JavaScript 中一切皆对象)
原型链图解:
继承方式(es5):
方式1:基于原型链继承
弊端:当原型中存在引用类型的值时,实例能够修改这个引用类型的值(不够安全)
// 新建父类 Base
function Base() {
this.name = 'tomni'
// jobInfo为一个引用类型
this.jobInfo = {
jobName: 'job1',
price: 1000
}
}
// 在原型上添加 getName 方法
Base.prototype.getName = function() {
return this.name
}
// 创建子类
function Sub() {
this.age = 18
}
const newBase = new Base()
/**
* 原型链继承
* 1. 将 Sub 的原型对象指向 newBase
* 2. 将 Sub 原型对象的构造函数执行本身(Sub)
*/
Sub.prototype = newBase
Sub.prototype.constructor = Sub
/** *** 原型链继承的问题 *** */
const newSub = new Sub()
const newSub2 = new Sub()
// 修改实例 newSub.jobInfo 中的 jobName
newSub.jobInfo.jobName = 'job22'
// 打印 newSub2.jobInfo.jobName
// 会发现 newSub2.jobInfo 这个对象也被修改了
console.log(newSub2.jobInfo) // -> job22
方式2:更改函数 this 指向实现继承
弊端:无法继承父对象中的原型对象(prototype)中的属性和方法,每次实例化都需要执行一遍父对象,性能欠佳
// 新建父类 Base
function Base() {
this.name = 'tomni'
// jobInfo为一个引用类型
this.jobInfo = {
jobName: 'job1',
price: 1000
}
}
// 在原型上添加 getName 方法
Base.prototype.getName = function() {
return this.name
}
// 创建子类
function Sub() {
// 使用当前上下文 this 执行 Base 函数(每次对 Sub 实例化都需要执行)
Base.call(this)
this.age = 18
}
const newSub = new Sub()
// 改变this指向的方式实现继承,无法继承其原型对象(prototype)中的方法与属性
// Uncaught TypeError: newSub.getName is not a function
console.log(newSub.getName())
方式3:组合式继承
弊端:每次创建子实例,父对象原型对象中的构造函数会被执行两次
// 新建父类 Base
function Base() {
this.name = 'tomni'
// jobInfo为一个引用类型
this.jobInfo = {
jobName: 'job1',
price: 1000
}
// 会执行两次(因为创建 Sub 实例的过程中,Base.prototype.constructor 被执行了两次)
console.log('constructor')
}
// 在原型上添加 getName 方法
Base.prototype.getName = function() {
return this.name
}
// 创建子类
function Sub() {
// 修改 this 指向实现继承
Base.call(this)
this.age = 18
}
// 原型链继承
Sub.prototype = new Base()
Sub.prototype.constructor = Sub
const newSub = new Sub()
const newSub2 = new Sub()
// 父对象中 引用类型 被影响的问题得以解决
newSub.jobInfo.jobName = '1111'
console.log(newSub2.jobInfo.jobName)
// 无法继承 父对象原型对象中的属性和方法 问题得以解决
console.log(newSub.getName()) // -> tomni
手机扫一扫
移动阅读更方便
你可能感兴趣的文章