EXIT

00:00:00

原型和原型链

首先先从一个构造函数开始:

function Person() {...} const p = new Person();

其中,Person就是一个构造函数, p就是一个实例对象.

每个函数都有一个属性 prototype,该属性指向一个对象,即调用该构造函数生成的实例对象的原型.

那么什么是原型呢?

可以这么理解,每个对象A(除了null)在创建的时候都会与之关联另一个对象B,这个对象B就是对象A的原型,对象A会从对象B中继承属性.

此处说是继承也不太恰当,因为继承是指复制属性到本体,而对象可以访问到对象的原型上的属性不是复制下来的,更像是委托访问

那么此时,我们就有了一条关系图:

image-20250917170933523

那么怎么联系实例对象p和p的原型之间的关系呢?

每一个对象(除了null)都有一个属性 __proto__,该属性会指向该对象的原型.

虽然 __proto__属性已经被各大浏览器厂商实现,但是其还不能成为一个标准规范. obj.__proto__可以看作是 Object.getPrototypeOf(obj)的语法糖.

这个时候就会有:

image-20250917171016499

既然实例对象和构造函数都有方法指向实例的原型,那么实例的原型有没有什么属性可以指向其构造函数或者实例吗?

--> 有的,每个实例的原型对象有一个属性 constructor 可以指向关联的构造函数.但是没有属性可以指向对应的实例对象,这是因为实例对象可能会有多个.

这个时候就会有:

image-20250917171103921

那么问题来了,原型也是一个对象,那么既然是对象,就可以用最原始的方法来创建它:

const p_proto = new Object()

也就是说原型对象是由构造函数 Object 实例化而来的.那么我们就可以更新原型对象的关系:

image-20250917171347765

那么p_proto的原型的原型对象是什么呢?(p的原型对象的原型对象的__proto__)

--> 其实是null,原型链已经到头了

image-20250917184543283

众所周知,其实函数也是对象,只不过是一种特殊的对象.

const fn = new Function('a','b','return a+b'); //等价于 function fn(a,b) { return a+b; }

因此,函数Person也是一个通过new Function出来的一个实例对象,它的构造函数是Function.因此有:

image-20250917184635134

同理,原型对象也会指向原型对象的原型.

既然函数也是对象,那么构造函数FunctionObject也是对象,他们也有 __proto__.

image-20250917170634950

因此最终的走向图为:

image-20250917170812775

uid:q3U7if
VOIDIS.ME
  1. no-like
  2. message
  3. Bilibili
  4. Github
  5. RSS
  6. sun