什么是原型,原型链
它们对应的名称应该是:
prototype
:原型
_proto_
:原型链
它们的从属关系,和实质应该是:
prototype
: 它是函数的一个属性,并且是一个对象
_proto_
: 它是对象的一个属性,并且是一个对象
对象的_proto_里面保存的是该对象的构造函数的protype
由此得到一个关系图:
下面来看一段代码:
function Test() {}
console.log(Test.prototype)
const test = new Test()
console.log(test.__proto__)
输出结果:
然后验证一下(对象的_proto_里面保存的是该对象的构造函数的protype)这句话:
console.log(test.__proto__ === Test.prototype) // true
很明显,test.__proto__
和 Test.prototype
这两个对象里面是同一个东西
那么我们再思考一下, Test.prototype
也是一个对象,那么它是否也有__proto__
呢?
观察一下输出结果:
console.log(Test.prototype.__proto__)
很显然,Test.prototype.__proto__
是存在的,并且里面保存的是Object.prototype
那么,Object.prototype
里面还有没有__proto__
?
我们再输出打印一下:
console.log(Object.prototype.__proto__) // null
由此可知: Object
是原型链最顶端的东西的了。
我们可以得到一个关系图:
原型继承,原型链继承
再来看一段代码:
function Test() {
this.a = 1
}
Test.prototype.b = 2
const test = new Test()
console.log(test)
输出结果:
当我在Test.prototype
上面加了一个b
之后,test
仍能访问到,并且是在test
的__proto__
中访问到的。
我执行下面这一行代码:
Object.prototype.c = 3
再次输出:
可以看到,即使是原型链末端的Object
上面的东西,test
也仍然可以访问到。
那么可以得到如下关系:
那么我再在上面的代码做一些修改:
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)
得到了下面结果:
我在Test.prototype
加了c
属性,并且值与 Object.prototype
不同,输出的结果值是Test.prototype.c
的值。并且,test
全部都能访问到,与是否是构造这个对象的构造函数无关
那么我们可以得出一个结论:
以一个对象为开头,以__proto__
为节点, 以Object.__proto__
为重点连接成的一条链。
查找数据时,得到的值,是沿着原型链查找到的最早的值,查找到后就不再往后查找了,如果没有,就继续往后找,一直找到 Object.prototype
为止
这就是原型继承,原型链继承
Object和Function特殊性
上面我们知道了Test.prototype
与test.__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)
输出结果如下:
由此再试一下:
console.log(typeof Object)
console.log(Object.__proto__ === Function.prototype)
console.log(Object.__proto__ === Function.__proto__)
得出一个结论:
Object是一个函数,
Object是由Function构造出来的,
Function是由自己构造出来的。
Object.__proto__
,Function.prototype
,Function.__proto__
是同一个东西。