JavaScript中原型和原型链的解析

原型和原型链解析

在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

在这里插入图片描述

至此,我们是不是就发现
在这里插入图片描述

得出结论:

  1. fun_1的constructor属性由初始化对象得来
  2. Fun源性对象上的constructor属性由创建时得来
  3. 原型对象Fun.prototype是函数对象Fun的一个实例

但需要注意的是,并不是所有的函数对象都存在prototype属性
Function.prototype这个就是一个特殊的函数对象,但它为什么是函数对象呢?也因为它属于function…

现在,我们已经认识到什么是原型对象了,那么它的作用是什么呢?
首当其冲的当然是用于模拟继承啦
prototype设置方法,实例化出来的对象,自然而然也就继承了这个方法

在这里插入图片描述

综上所述,我们得出:
这个原型对象之间的关系链接只存在于实例化对象和构造器函数的prototype源性对象之间,也就是fun_1Fun.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

借鉴:(非常感谢这个作者让我明白了原型和原型链之间的关系)
原文地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值