你真的弄懂了原型和原型链是什么了吗?

325 阅读5分钟

前言

讲原型和原型链之前首先得先了解四个概念:
(1)实例对象:通过 new 关键字构造出的对象 或者 简单来说是花括号包裹的对象。
(2)原型对象:在创建对象的同时,此对象中默认有一个 prototype 属性指向了该对象,而这个 prototype 对象就是原型对象。而且所有的原型对象都是被 Object 函数对象创建出来的。
(3)显式原型:每个对象都有一个 prototype ,这个就是显式原型。
(4)隐式原型:每个实例对象都有一个 __proto__ ,这个就是隐式原型。

原型

概念

  1. 每个对象都有 prototype 属性称之为原型,也称为原型对象。
  • 原型可以放一些属性和方法,共享给实例对象使用。
  • 原型可以做继承。
  1. 每个实例对象的隐式原型(__proto__)指向构造函数(对象)的显示原型(prototype)。

举例讲解

class Student{
    constructor(name, score){
        this.name = name;
        this.score = score;
    }
    
    introduce(){
        console.log("my name is " + this.name + ". my score is " + this.score);
    }
}

let student = new Student('zs',90);

  1. Student 就是一个类对象,然后 Student.prototypeStudent 的显示原型对象。

image.png

  1. student 就是通过 new 关键字创建的类对象 Student 的实例化对象,然后 student.__proto__Student 的隐式原型对象。

image.png

  1. 每个实例对象的隐式原型(__proto__)指向构造函数(对象)的显示原型(prototype):也就是说 student 的 __proto__ 实际上是指向 Student 的原型对象(prototype)。

image.png

image.png

原型链

概念

  1. 定义:每个对象都有 __proto__ 属性,这个属性指向它的原型对象,原型对象也是对象也有__proto__ 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链。

  2. 联系原型理解原型链

  • 当我们创建一个 JavaScript 对象时,每个对象都有一个特殊的内部属性称为原型(prototype)。原型是一个指向另一个对象的引用,这个对象被称为原型对象。通过原型,对象可以继承另一个对象的属性和方法。
  • 原型链是一种通过原型对象的引用来实现对象之间继承关系的机制。 当我们访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(即 Object.prototype),最顶端找不到则返回null。。

举例讲解

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  sayHello() {
    console.log("Hello, my name is " + this.name);
  }
}

class Student extends Person {
  constructor(name, age, score) {
    super(name, age);
    this.score = score;
  }
}

let student = new Student("zs", 18, 90);

// 访问 student 对象的属性和方法
console.log(student.name);  // zs
console.log(student.age);   // 18
console.log(student.score); //90
student.sayHello();         // Hello, my name is zs
  1.  Person 对象有 name 和 age 属性,以及一个 sayHello 方法。然后Student 对象有 score属性并继承 Person 对象。这样 Student 对象就可以 通过原型链继承 Person 对象的属性和方法。

image.png

  1. Student 原型对象也是对象, 也有 __proto__ 属性,固 Student隐式原型对象(__proto__) 指向 Student原型对象(Student.prototype) 的原型对象,因为 Student 对象 通过原型链继承 Person 对象的属性和方法,也就是说 Student 的原型对象的原型对象是 Person原型对象(Person.prototype),所以 Student.prototype.__proto__ === Person.prototypetrue

image.png

  1. student 就是通过 new 关键字创建的类对象 Student 的实例化对象。原型链的概念体现在当我们访问 student 对象的属性或方法时,如果 student 对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(即 Object.prototype)为止。在这个示例中,student 对象没有定义 name, age 属性以及 sayHello 方法,但它可以通过原型链找到 Person 对象的 name,age 属性以及 sayHello 方法并进行调用。所以 student 可以通过 student.name 和 student.age 访问继承的属性,通过 student.sayHello() 调用继承的方法。

image.png

小知识点

prototype 、__proto__ 、constructor三者之间的关系

  1. prototype(原型) :每个函数对象都有一个 prototype 属性,该属性指向一个普通的对象。这个对象被称为该函数的原型对象。原型对象可以包含属性和方法,这些属性和方法可以被该函数的实例共享和访问。
  2. __proto__ :每个对象都有一个隐式的属性 __proto__ ,它指向该对象的原型对象。也就是说,对象的 __proto__ 指向了创建该对象的构造函数的原型对象。
  3. constructor :原型对象上有一个 constructor 属性,它指向创建该原型对象的构造函数。也就是说,通过原型对象的 constructor 属性,可以找到该对象的构造函数。

所以,可以总结如下关系:

  • 每个对象都有一个 prototype 属性,它指向该对象的原型对象。
  • 每个对象都有一个 __proto__ 属性,它指向创建该对象的构造函数的原型对象。
  • 原型对象上有一个 constructor 属性,它指向创建该原型对象的构造函数。

构造函数 以及 new 干了什么

  1. 构造函数
    构造函数是一种特殊的函数,用于创建和初始化对象。它们通常用于创建具有相同属性和方法的多个对象。使用构造函数创建的对象被称为实例。

  2. new 干了什么
    在JavaScript中,使用关键字 new 来调用构造函数并创建新的对象。当使用 new 关键字时,它会执行以下操作:
    (1) 创建一个空对象。
    (2) 将这个新对象的 __proto__ 属性指向构造函数的 prototype 属性。
    (3) 将构造函数的作用域赋给实例化对象(即将 this 关键字指向实例化对象)。
    (4) 执行构造函数内部的代码,将属性和方法添加到实例化对象上。
    (5) 返回实例化对象作为构造函数的结果。

tips:在使用 new 关键字调用构造函数时,首先会创建一个空对象。这个空对象是未经初始化的,并且没有任何属性或方法。创建一个空对象的目的是为了将构造函数中定义的属性和方法添加到这个对象上。

以上是我整理的有关原型和原型链的相关知识点,如有错漏,还请指正! ( OvO )