js原型链总结

83 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

前言

大家好呀,我是L同学。在上篇文章js原型知识点总结中,我们学习了js中的构造函数、原型、constructor属性、构造函数、原型、实例对象三者的关系等相关知识点。今天,在这篇文章中,我们将学习js中的原型链、继承、instanceof等相关知识点。

原型链

原型对象中的属性和方法,都可以被实例对象直接使用。

要获取某对象的属性时,会执行如下操作:

  1. 首先搜索这个实例对象,如果这个实例对象中有这个属性,就返回这个属性的值。
  2. 如果找不到,就继续搜索指针指向的原型对象,在原型对象中查找该属性。如果在原型对象中有这个属性,就返回这个属性的值。
  3. 如果找不到,就去原型的原型找,依次类推。
  4. 直到最顶层的Object.prototpye还是找不到,就返回undefined

因为原型对象也是对象,又有自己的原型,所以就形成了一条可向上追溯的链条,叫原型链

Object是所有类的父类。原型链最顶层的原型对象就是Object的原型对象

构造函数的prototype指向原型对象,原型对象中的constructor指向构造函数。

原型链的尽头是null。

原型链的属性屏蔽,defineProperty

  • 原型链上层有,且可写,那就在原对象上创建新属性(屏蔽属性)
  • 原型链上层有,但不可写,无法修改或在原对象上创建屏蔽属性,严格模式下会报错
  • 原型链上层有,且是个setter,则一定会调用这个setter。不会创建屏蔽属性,也不会重新定义setter。

继承

  1. 通过原型链继承
// 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()

打印结果:

image.png

  1. 借用构造函数继承
  2. 原型式继承
  3. 寄生式继承
  4. 寄生组合式继承
  5. 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