2022-03-03
阅读:29
ECMA-262把原型链定义为ECMAScript的主要继承方式。其基本思想就是通过原型继承多个引用类型的属性和方法,
每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型,如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另外一个原型,相应的另一个原型也有一个指针指向另一个构造函数,这样在实例和原型之间构造了一条原型链,这就是原型链的基本思想。
function Person(){}
Person.prototype.name = '张三'
Person.prototype.age = 20
Person.prototype.getName = function(){
return this.name
}
function Student(){}
//继承Person
Student.prototype = new Person()
Student.prototype.grade = '三年级'
let stu = new Student()
console.log(stu.getName())//张三
上面例子实现继承的关键是 Student
没有使用默认的原型,而是将其替换成了一个新的对象,这个对象恰好是Person
的实例,这样一来,Student
的实例不仅能从Person
的实例中继承属性和方法,而且与Student
的原型挂钩。于是stu
通过内部的[[prototype]]
(__proto__
)指向Student.prototype
而Student.prototype
又通过内部的[[prototype]]
(__proto__
)指向Person.prototype
在读取实例属性时,首先会在实例上搜索这个属性,如果没找到,则会继续搜索实例原型。在通过原型链实现继承之后,搜索就可以继续向上搜索原型的原型。
默认情况下,所有引用类型都继承自
Object
,这也是通过原型链实现的,任何函数的默认原型都是一个Object
的实例,这意味着这个实例有一个内部指针指向Object.prototype
。这也是为什么自定义类型能够使用包括toString()
、valueOf
在内的所有默认方法
instanceof
console.log(stu instanceof Person)// true;
console.log(stu instanceof Student) // true;
console.log(stu instanceof Object) // true;
从技术上将,stu是 Student、Person、和Object的实例,因为stu的原型链中包含这些构造函数的原型,结果就是 instanceof 对所有这些构造函数都返回 true
isPrototypeOf
console.log(Object.prototype.isPrototypeOf(stu))// true;
console.log(Person.prototype.isPrototypeOf(stu)) // true;
console.log(Student.prototype.isPrototypeOf(stu)) // true;
只要原型链上包含这个原型、这个方法就会返回 true
子类有时候需要覆盖父类的方法,或者增加父类中没有的方法。为此,这些方法必须在原型赋值之后再添加到原型上
function Person(){}
Person.prototype.name = '张三'
Person.prototype.age = 20
Person.prototype.getName = function(){
return this.name
}
function Student(){}
//继承Person
Student.prototype = new Person()
Student.prototype.grade = '三年级'
//新方法
Student.prototype.getGrade = function(){
return this.grade
}
//覆盖已有方法
Student.prototype.getName = function(){
return `${this.name}--${this.grade}`
}
let stu = new Student()
console.log(stu.getName())
以对象字面量的方式创建原型方法会破坏之前的原型链,因为这相当于重写了原型
function Person(){}
Person.prototype.name = '张三'
Person.prototype.age = 20
Person.prototype.getName = function(){
return this.name
}
function Student(){}
//继承Person
Student.prototype = new Person()
//以对象字面量的形式添加方法,会导致上一行代码无效
Student.prototype = {
grade:'三年级',
getGrade(){
return this.grade
}
}
let stu = new Student()
console.log(stu.getName())
页面报错,找不到getName
方法
![]()