前言
讲原型和原型链之前首先得先了解四个概念:
(1)实例对象:通过 new 关键字构造出的对象 或者 简单来说是花括号包裹的对象。
(2)原型对象:在创建对象的同时,此对象中默认有一个 prototype 属性指向了该对象,而这个 prototype 对象就是原型对象。而且所有的原型对象都是被 Object 函数对象创建出来的。
(3)显式原型:每个对象都有一个 prototype ,这个就是显式原型。
(4)隐式原型:每个实例对象都有一个 __proto__ ,这个就是隐式原型。
原型
概念
- 每个对象都有 prototype 属性称之为原型,也称为原型对象。
- 原型可以放一些属性和方法,共享给实例对象使用。
- 原型可以做继承。
- 每个实例对象的隐式原型(__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);
Student
就是一个类对象,然后 Student.prototype 是Student
的显示原型对象。
student
就是通过new
关键字创建的类对象Student
的实例化对象,然后 student.__proto__ 是Student
的隐式原型对象。
- 每个实例对象的隐式原型(__proto__)指向构造函数(对象)的显示原型(prototype):也就是说
student
的 __proto__ 实际上是指向Student
的原型对象(prototype)。
原型链
概念
-
定义:每个对象都有 __proto__ 属性,这个属性指向它的原型对象,原型对象也是对象也有__proto__ 属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链。
-
联系原型理解原型链:
- 当我们创建一个 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
-
Person
对象有name
和age
属性,以及一个sayHello
方法。然后Student
对象有score
属性并继承Person
对象。这样Student
对象就可以 通过原型链继承Person
对象的属性和方法。
Student
原型对象也是对象, 也有 __proto__ 属性,固Student
的 隐式原型对象(__proto__) 指向Student
的 原型对象(Student.prototype) 的原型对象,因为Student
对象 通过原型链继承Person
对象的属性和方法,也就是说Student
的原型对象的原型对象是Person
的 原型对象(Person.prototype),所以Student.prototype.__proto__ === Person.prototype
是true
。
student
就是通过new
关键字创建的类对象Student
的实例化对象。原型链的概念体现在当我们访问student
对象的属性或方法时,如果student
对象本身没有这个属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法或者到达原型链的顶端(即Object.prototype
)为止。在这个示例中,student
对象没有定义name
,age
属性以及sayHello
方法,但它可以通过原型链找到Person
对象的name
,age
属性以及sayHello
方法并进行调用。所以student
可以通过student.name
和student.age
访问继承的属性,通过student.sayHello()
调用继承的方法。
小知识点
prototype 、__proto__ 、constructor三者之间的关系
- prototype(原型) :每个函数对象都有一个 prototype 属性,该属性指向一个普通的对象。这个对象被称为该函数的原型对象。原型对象可以包含属性和方法,这些属性和方法可以被该函数的实例共享和访问。
- __proto__ :每个对象都有一个隐式的属性 __proto__ ,它指向该对象的原型对象。也就是说,对象的 __proto__ 指向了创建该对象的构造函数的原型对象。
- constructor :原型对象上有一个 constructor 属性,它指向创建该原型对象的构造函数。也就是说,通过原型对象的 constructor 属性,可以找到该对象的构造函数。
所以,可以总结如下关系:
- 每个对象都有一个 prototype 属性,它指向该对象的原型对象。
- 每个对象都有一个 __proto__ 属性,它指向创建该对象的构造函数的原型对象。
- 原型对象上有一个 constructor 属性,它指向创建该原型对象的构造函数。
构造函数 以及 new 干了什么
-
构造函数 :
构造函数是一种特殊的函数,用于创建和初始化对象。它们通常用于创建具有相同属性和方法的多个对象。使用构造函数创建的对象被称为实例。 -
new 干了什么 :
在JavaScript中,使用关键字new
来调用构造函数并创建新的对象。当使用new
关键字时,它会执行以下操作:
(1) 创建一个空对象。
(2) 将这个新对象的 __proto__ 属性指向构造函数的 prototype 属性。
(3) 将构造函数的作用域赋给实例化对象(即将this
关键字指向实例化对象)。
(4) 执行构造函数内部的代码,将属性和方法添加到实例化对象上。
(5) 返回实例化对象作为构造函数的结果。
tips:在使用
new
关键字调用构造函数时,首先会创建一个空对象。这个空对象是未经初始化的,并且没有任何属性或方法。创建一个空对象的目的是为了将构造函数中定义的属性和方法添加到这个对象上。
以上是我整理的有关原型和原型链的相关知识点,如有错漏,还请指正! ( OvO )