我成替身了?| 浅浅谈一谈我对原型的理解

134 阅读3分钟

Function

汽车&汽车工厂&施工队

汽车是有由汽车工厂生产的,但汽车工厂不是凭空产生的,汽车工厂是由施工队建造的。

实例对象&构造函数&Function

如果说构造函数是实例对象的工厂的话,那么Function就是函数建造者,而构造函数本身也是Function的实例对象。

 //函数本身也是对象,Function是它的构造者
 function foo(){}  =>  foo=new Function() 

Function是何物?

Function是所有函数的祖先,Function本身也是函数,所有函数都是Function的实例,继承的也是Function原型的特性。

Function从何而来?

混沌消散,万物之初始之时便已存在。元老级的函数(早就写死在js的底层)

函数

所谓函数

  1. 函数是一种特殊的对象
  2. 能够用于构造其它对象
  3. 能够配合“()”符号执行
  4. 所有函数都是祖先函数Function的实例,并且继承Function的原型。

函数构造对象 => 对象构造对象

已知 函数 是 由Function构造而来的对象,那么函数构造实例的过程,其实是在用对象来构造对象。因为“工厂”本身也是一个实例,由“工厂”二字指代,只是表明了它不同的特性。函数亦是如此。

原型:只有函数存在原型

  1. 只有“函数”拥有原型
  2. 原型存在的目的:让函数构造的实例对象可以继承原型上的属性与方法,简化代码量。

什么是原型?

当我们使用 function 关键字声明一个构造函数foo时,foo会自动拥有一个prototype属性,该属性指向一个普通对象,并且该对象天生拥有一个属性“constructor”指向foo函数,这个对象我们称之为原型对象。

9c522644fd121d76511350f58916ab09.png

原型有什么作用?

实现继承机制:原型继承

将公有的属性与方法添加到原型上,由构造函数创建的实例对象的都将继承原型中的属性与方法。

未命名文件.png

优点

继承机制实现后,由构造函数创建的子对象可以直接调用原型中的方法与属性

function foo() {

}

foo.prototype.fn = () => {
    console.log("hello")
}

const f1 = new foo();
const f2 = new foo();

f1.fn()  // hello
f2.fn()  //hello


显式原型:prototype属性:函数与原型的桥梁

每一个函数,都存在名为prototype的属性。作为一个指针,指向它们的原型,是连接原型与函数的桥梁

未命名文件.png

隐式原型:__proto__属性:实例对象与原型间的桥梁

对象与原型间的桥梁

每一个对象,都存在名为__proto__的属性,它是一个指针,指向构造该对象函数的原型。__proto__是连接对象与原型之间的桥梁

函数中的__prototype__

所有函数的__prototype__都指向 祖先函数Function的原型Function.prototype.

未命名文件.png

原型中的__prototype__

  1. 所有除Object.prototype外的原型,其__proto__指向的都是Object.prototype

未命名文件.png

  1. Object.prototype的__proto__属性指向为空

我们利用new构造的实例对象中的__proto__

实例对象的__proto__属性指向其构造函数的原型 未命名文件.png

特殊的原型Object.prototype

Object.prototype的__proto__属性指向为空

未命名文件.png

原型链

什么是原型链

由对象之间通过__proto__与prototype指针彼此互相连接,所形成的巨大关系链。我们称之为原型链 d9afcd1172d340508d25c095b1103fac~tplv-k3u1fbpfcp-zoom-in-crop-mark_1512_0_0_0.webp

原型链有什么用

  1. 类型判断:函数instanceof 当我们调用x instanceof X 时,instanceof 函数沿着 x对象的隐式原型链往上查找,直到找到X的显式原型。
image.png