原型,原型链理解/Object和Function特殊性

496 阅读2分钟

什么是原型,原型链

它们对应的名称应该是:

prototype:原型

_proto_:原型链

它们的从属关系,和实质应该是:

prototype: 它是函数的一个属性,并且是一个对象

_proto_: 它是对象的一个属性,并且是一个对象

对象的_proto_里面保存的是该对象的构造函数的protype

由此得到一个关系图:

7.png

下面来看一段代码:

function Test() {}
console.log(Test.prototype)
const test = new Test()
console.log(test.__proto__)

输出结果:

5.png

然后验证一下(对象的_proto_里面保存的是该对象的构造函数的protype)这句话: console.log(test.__proto__ === Test.prototype) // true

很明显,test.__proto__Test.prototype这两个对象里面是同一个东西

那么我们再思考一下, Test.prototype也是一个对象,那么它是否也有__proto__ 呢?

观察一下输出结果:

console.log(Test.prototype.__proto__)

3.png 很显然,Test.prototype.__proto__是存在的,并且里面保存的是Object.prototype

那么,Object.prototype里面还有没有__proto__?

我们再输出打印一下:

console.log(Object.prototype.__proto__) // null

由此可知: Object是原型链最顶端的东西的了。

我们可以得到一个关系图:

Snipaste_2021-08-16_20-20-53.png

原型继承,原型链继承

再来看一段代码:

function Test() {
     this.a = 1
}
Test.prototype.b = 2
const test = new Test()
console.log(test)

输出结果:

39.png

当我在Test.prototype上面加了一个b 之后,test仍能访问到,并且是在test__proto__中访问到的。

我执行下面这一行代码:

Object.prototype.c = 3

再次输出:

28-33.png

可以看到,即使是原型链末端的Object上面的东西,test也仍然可以访问到。

那么可以得到如下关系:

Snipaste_2021-08-16_20-20-53.png

那么我再在上面的代码做一些修改:

function Test() {
    this.a = 1
}
Test.prototype.b = 2
Test.prototype.c = 1
const test = new Test()
Object.prototype.c = 3
console.log(test)
console.log(test.a)
console.log(test.b)
console.log(test.c)

得到了下面结果:

Snipaste_2021-08-16_19-36-07.png

Snipaste_2021-08-16_19-36-07.png

我在Test.prototype加了c属性,并且值与 Object.prototype不同,输出的结果值是Test.prototype.c的值。并且,test全部都能访问到,与是否是构造这个对象的构造函数无关

那么我们可以得出一个结论:

以一个对象为开头,以__proto__为节点, 以Object.__proto__ 为重点连接成的一条链。 查找数据时,得到的值,是沿着原型链查找到的最早的值,查找到后就不再往后查找了,如果没有,就继续往后找,一直找到 Object.prototype为止

这就是原型继承,原型链继承

Object和Function特殊性

上面我们知道了Test.prototypetest.__proto__其实是同一个东西。 那么我们再来看看,Test.__proto__是什么?

看下面一段代码:

console.log(Test.__proto__)   //  ƒ () { [native code] }

说明Test是由Function构造而来的。

那么Object.__proto__呢?

console.log(Object.__proto__)   //  ƒ () { [native code] }

说明Object是由Function构造而来的。

再看看Function的原型和原型链

console.log(Function.__proto__)
console.log(Function.prototype)
console.log(Function.__proto__===Function.prototype)

输出结果如下:

Snipaste_2021-08-16_19-36-07.png

由此再试一下:

console.log(typeof Object)
console.log(Object.__proto__ === Function.prototype)
console.log(Object.__proto__ === Function.__proto__)

Snipaste_2021-08-16_19-36-07.png

得出一个结论:

Object是一个函数,

Object是由Function构造出来的,

Function是由自己构造出来的。

Object.__proto__,Function.prototype,Function.__proto__是同一个东西