在JS里面,原型链无异是比较难理解的一块,现在结合自己的理解,来分析这个究竟是什么原理。
原型链的理解
在JS中,万物皆对象。Object和Function是两个比较特殊的函数对象。js创建对象通过下面的步骤:
1,先创建一个空对象
2,把this指向这个空的对象
3,把对象的内置属性 proto 指向FF的prototype属性(这时候对象的_proto_属性和这个构造函数的prototype属性,都指向了同一个对象)
4,通过this把属性和方法加在这个空对象上
5,return this指向的对象
实例的constructor指向构造函数。
https://www.jianshu.com/p/dee9f8b14771
https://blog.csdn.net/a790012863/article/details/80144922
基于自己的理解,我们做出如下推测:
一、JS的对象分为两类,函数对象和普通对象
二、函数对象是一种特殊的对象,它包含两部分内容。
1、一部分为函数的模板(函数的描述信息)这部分包括函数的代码以及prototype属性等。
2、第二部分包含这个函数对象的公共实例部分,因此修改这部分的属性的时候,将会影响到所有已创建的实例,这个公共实例也是由相同的函数模板创建的。
三、普通对象中包含两个关键的属性
1、constructor:构造器,它实际上指向了创建这个实例的函数模板。
2、__proto__:【并非所有浏览器的实现均是如此】指向了创建这个实例的的函数的公共部分,也就是上面的第二个内存区域。
我们画图如下,边验证边画的,有点乱,稍后再整理:
基于上面的猜测,我们来进行一一验证。
对象的各种情况
首先我们先自定义一个函数,用来验证,继承的部分待会在研究。
function Person(name,age){
this.name = name;
this.age = age;
this.getName = function(){
console.log(this.name);
}
}
Person.prototype.getAge = function(){
console.log(this.age);
}
constructor属性
对象的一个属性,总是指向创建这个对象的函数模板。
p1.constructor == Person: true
我们可以知道,普通对象的构造器确实指向了创建它的函数模板。
Person.constructor == Function: true
我们知道Person是个函数对象,它是由Function创建的。
Object.constructor == Function: true
Object同样是个函数对象。
Function.constructor == Function: true
函数同样是个函数对象。
Person.prototype.constructor == Person: true
我们可以看到,公共实例的构造器指向的是函数模板。
prototype属性
这个属性只存在于函数对象中,总是指向函数的原型实例。
一般情况下,这个指向的是一个普通对象,但是,Function.prototype不是一个普通对象,它是一个函数对象!
typeof Function.prototype == function
__proto__ 属性
对象都有这个属性,这也是构成原型链的核心所在。它默认总是指向创建该对象的函数对象的公共实例。
p1.__proto__ == Person.prototype: true
Person.prototype.__proto__ == Object.prototype: true
这里要说明的是,公共实例的constructor指向对应的函数模板,但是其__proto__属性指向Object的公共实例。
验证上面的结论了。但此处猜测原型实例是由Object创建出来的,并不是函数模板创建出来的,否则为什么没有函数模板中的属性呢?
Person.__proto__ == Function.prototype: true
函数对象是函数的实例,因此指向函数的原型实例。
Function.prototype.__proto__ == Object.prototype: true
函数的原型实例也是由Object创建的
Object.prototype.__proto__ == null: true
这个就是原型链的根了,指向为null
Function.__proto__ == Function.prototype == Object.__proto__
他们都是函数对象,指向都是Function的prototype
既然Function的prototype是一个函数对象,那么它的prototype是什么呢?不好意思,没有这个属性。
Function.prototype.prototype == undefined
原型链的应用
好了,基于上面的理解,我们针对原型链主要可以用在下面几个地方:
继承
(未完待续……)