持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
前言
大家好呀,我是L同学。在上篇文章js原型知识点总结中,我们学习了js中的构造函数、原型、constructor属性、构造函数、原型、实例对象三者的关系等相关知识点。今天,在这篇文章中,我们将学习js中的原型链、继承、instanceof等相关知识点。
原型链
原型对象中的属性和方法,都可以被实例对象直接使用。
要获取某对象的属性时,会执行如下操作:
- 首先搜索这个实例对象,如果这个实例对象中有这个属性,就返回这个属性的值。
- 如果找不到,就继续搜索指针指向的原型对象,在原型对象中查找该属性。如果在原型对象中有这个属性,就返回这个属性的值。
- 如果找不到,就去原型的原型找,依次类推。
- 直到最顶层的Object.prototpye还是找不到,就返回undefined
因为原型对象也是对象,又有自己的原型,所以就形成了一条可向上追溯的链条,叫原型链。
Object是所有类的父类。原型链最顶层的原型对象就是Object的原型对象。
构造函数的prototype指向原型对象,原型对象中的constructor指向构造函数。
原型链的尽头是null。
原型链的属性屏蔽,defineProperty
- 原型链上层有,且可写,那就在原对象上创建新属性(屏蔽属性)
- 原型链上层有,但不可写,无法修改或在原对象上创建屏蔽属性,严格模式下会报错
- 原型链上层有,且是个setter,则一定会调用这个setter。不会创建屏蔽属性,也不会重新定义setter。
继承
- 通过原型链继承
// 1. 定义父类构造函数
// 父类:公共属性和方法
function Person() {
this.name = 'haha'
this.friends = []
}
// 2. 父类原型上添加内容
Person.prototype.eating = function() {
console.log(this.name + ' eating');
}
// 3. 定义子类构造函数
// 子类:特有属性和方法
function Student() {
this.sno = 111
}
// 4. 创建父类对象,并且作为子类的原型对象
let p = new Person()
Student.prototype = p
// 5. 在子类原型上添加内容
Student.prototype.studying = function() {
console.log(this.name + ' studying');
}
// name、sno
let s = new Student()
console.log(s);
s.eating()
s.studying()
打印结果:
- 借用构造函数继承
- 原型式继承
- 寄生式继承
- 寄生组合式继承
- ES6类的继承—— extends
instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car);
// expected output: true
console.log(auto instanceof Object);
// expected output: true