原型和原型链解析
在JavaScript中,万物皆对象,分为普通对象和函数对象两部分。
const obj_1 = {};
const obj_2 = new Object();
function fun_1();
const f2 = function fun_2(){};
const f3 = new Function();
其中 obj_1和obj_2都是普通对象,fun_1,fun_2,fun3都是函数对象
我们先创建一个函数
function Fun (name, age, address){
this.name = name;
this.age = age;
this.address = address;
}
const fun_1 = new Fun("zzw", 22, "北京朝阳区");
const fun_2 = new Fun("thx", 22, "安徽蚌埠");
在上面例子中我们初始化了两个Fun的实例对象,并且这两个实例都默认存在一个constructor构造函数属性,该属性指向了Fun。
也就是说
fun_1.constructor === Fun
fun_2.constructor === Fun
所以得出结论,函数实例化对象中的constructor属性永远指向函数本身
那么什么是原型对象呢?
prototype
在JavaScript中,每次定义对象时,都会生成一连串的预定义属性,其中,每个函数对象都默认存在一个prototype属性,这个属性指向函数的原型对象
可以看到,每一个对象中都存在**proto属性,但只有函数对象才会拥有prototype**属性
那么究竟什么是原型对象呢?
在上图中我们能看到
竟然是一个普通的Object对象!
在默认的情况下,所有的原型对象都会默认存在一个constructor构造函数属性,并且这个属性指向prototype属性所在的函数(Fun)
换句话说,就是原型对象prototype的构造函数属性constructor指向了函数函数本身Fun
至此,我们是不是就发现
得出结论:
- fun_1的constructor属性由初始化对象得来
- Fun源性对象上的constructor属性由创建时得来
- 原型对象Fun.prototype是函数对象Fun的一个实例
但需要注意的是,并不是所有的函数对象都存在prototype属性
Function.prototype这个就是一个特殊的函数对象,但它为什么是函数对象呢?也因为它属于function…
现在,我们已经认识到什么是原型对象了,那么它的作用是什么呢?
首当其冲的当然是用于模拟继承啦
给prototype设置方法,实例化出来的对象,自然而然也就继承了这个方法
综上所述,我们得出:
这个原型对象之间的关系链接只存在于实例化对象和构造器函数的prototype源性对象之间,也就是fun_1和Fun.prototype之间
__ proto__
在JavaScript中,所有的对象都存在一个proto 对象,它用来指向创建它的原型对象prototype,对象fun_1中就有一个proto属性,fun_1的构造函数是Fun,而Fun的原型对象是Fun.prototype,所以
那么有一下几个问题
fun_1的__proto__是什么?
实例化对象的__proto__指向构造函数本身的原型对象,也就是Fun.prototype
Fun.__proto__是什么?
Fun的__proto__是Fun.constructor.prototype,而Fun.constructor的类型是Function,所以Fun,__proto__指向Function.prototype
Fun.prototype.__proto__是什么?
Fun.prototype是一个Object对象,所以当然是指向Object的prototype了
Object.prototype.__proto__是什么?
首先Object是顶级对象,那么它的__proto__自然也是顶级了
为null证明已经没有任何指向了,它已经是顶级了
又得出结论:
所有函数对象的**proto**都指向了Function.prototype,所有的构造器都来自于Function.prototype,并且所有的构造器也都是Object对象,可以给构造器添加修改删除属性等,同时它还继承了Object.prototype上的所有方法,比如toString(), valueOf等
我们做一个小小的实验:
初始化一个Object对象,然后查看它所有的方法
再初始化一个数组对象:
是不是很震惊,很神奇,所以建议大家一定要多看书,比如JavaScript高级程序设计,不然你是没法和别人吹牛逼的
等等… 其他的大家可以自己再去尝试,如number和function等
小小的总结一下原型链__proto__:
由于fun_1已经是实例化对象,所以它自身就已经是prototype原型对象,则fun_1的原型链指向它的构造器Fun的原型对象,而构造器Fun的原型链指向Function的原型对象,而Function原型对象的原型链指向Object的原型对象从而继承Object上的方法,Object原型对象上的原型链则指向为null,因为它已经是最顶级了
大总结一波
原型对象:prototype
原型链:proto
原型链是可以理解为是寻找上级元素的媒介,fun_1 -> Fun -> Function -> Object -> null,从而形成一个链条
原型对象就是用来操作构造器上的各种属性和方法,以及继承等
实例对象testTwo和testOne的原型对象存在一种链接关系,并且这种关系也只存在在实例对象和构造器原型对象之间,而不是实例对象和构造器之间,也就是说testTwo实例化之后,使用原型链层层指向上级的原型对象,并在原型对象上找到该属性或者方法,一直到Object指向为null时才会出现undifend,即
testTwo.__proto__指向testOne的prototype,也就是说,testTwo.method === testOne.prototype.method
借鉴:(非常感谢这个作者让我明白了原型和原型链之间的关系)
原文地址