彻底搞懂JavaScript中的原型(__proto__)、原型对象(prototype)及原型链

2024-03-26 08:20:56

一. 原型(__proto__)

任何对象(除了null以外)上都会有一个内部属性__proto__。这个属性就是对象的原型,你可以在控制台中通过obj.__proto__打印(obj是定义的一个对象)。

object

但是需要注意的是,这个属性是一个内部属性,在平时开发代码中是不能直接使用这个属性,你可以通过getPrototypeOf(获取)、setPrototypeOf(设置)等。

那__proto__指向什么呢?你可以理解为构造该对象的构造函数的prototype。比如我们通过 new 一个构造函数,创建一个对象:

function A() {}
const a = new A();

那它(a)的__proto__指向的就是构造它的构造函数(A)的prototype,即:

a.__proto__ === A.prototype

二. 原型对象(prototype)

原型对象是针对函数的,在函数中,我们可以定义一些原型方法和原型属性,之后通过函数new的实例对象上都可以访问这些原型方法和属性,减少了内存占用。

function Person() {}
Person.prototype.getName = function() {
    return “我是原型方法”;
}
const person1 = new Person();
const person2 = new Person();
person1.getName(); // 我是原型方法
person2.getName(); // 我是原型方法

需要注意的是:函数也是一种对象,因此函数不仅有prototype,也有__proto__属性。

上面定义的Person构造函数的__proto__:

Person.__proto__ === Function.prototype

三. 原型链

原型链是一种查找规则。

当查找一个对象上的属性或者方法时,首先从自身属性开始查找,如果没有,则去该对象的原型上查找(__proto__),如果没有,再去对象的原型的原型上去查找,直至null(Object.prototype.__proto__ === null)结束,这种链式查找,被称为原型链。

下面我会详细介绍该如何毫无压力的写成任何对象的原型链。

比如我们创建一个构造函数,之后new一个对象,我们以这个对象为例:

function A() {}
const a = new A();
a对象的原型链:
  1. 构造a对象的构造函数是A,那么a.__proto__:

    a.__proto__ === A.prototype

  2. A.prototype.__proto__呢?可能会有人回答是Function.prototype,A的构造函数不是Function嘛,那可以明确告诉你,A.prototype.__proto__不是指向Function.prototype,而是指向Object.prototype,为啥呢,因为A.prototype,而不是A,A的构造函数是Function,但是A.prototype可不是,它是一个对象,那它的构造函数是Object,所以:

    A.prototype.__proto__=== Object.prototype

  3. Object.prototype.__proto__呢?很显然指向null

    Object.prototype.__proto__ === null

为什么是null呢,你可以理解为有始有终,也可以理解为原型链必须要结束,不可能限循环下去。

A的原型链:

__proto__存在于每个对象中,而prototype只能存在于函数里,函数呢,又是特殊的对象,那么函数也是有__proto__的。那现在我们在以A这个构造函数,来了解其原型链,经过上面的分析,那A的原型链应该很简单了。

A.__proto__ === Function.prototype

Function.prototype.__proto__ === Object.prototype

Object.prototype.__proto__ === null

A的原型链写完了,那接着写Function的原型链:

Function的原型链:

Function.__proto__ === Function.prototype

Function.prototype.__proto__ === Object.prototype

Object.prototype.__proto__ === null

注意:Function的__proto__有点特别,因为它是指向Function.prototype,因为Function的构造函数就是Function。

如果我们将a的__proto__指向另一个对象b(let b = {}),而不是A.prototype了,那这个原型链该如何显示呢?如下所示:

a.__proto__ === b

b.__proto__ === Object.prototype

Object.prototype.__proto__ === null

目录

相关推荐
深入理解对象原型__proto__深入理解constructor对象的isPrototypeOf和静态方法Object.getPrototypeOf深入理解原型链JavaScript--原型链图解Object对象中的静态方法setPrototypeOf