js原型链中的__proto__和prototype区别与联系

function Persion() {
}
let person1 = new Persion();

__proto__prototype的关系如上图所示,如果明白这两则关系的话这个图是很清晰易见的,看不懂的话可以继续往下看


首先需要明确的一点是,JS中除了一些基本数据类型外其他的都是对象,既然都是对象那么在继承关系或者实例关系中就会存在共享属性(公共区)的概念

在其他语言中存在class类的概念,那么公共区的引用由类来指向没什么问题,但js中没有类的概念(es6后的class本质是语法糖),在js中创建对象是通过构造函数 + new的方式,所以公共区的引用就由构造函数来指代,(注意明确函数也是对象)

而这个指代公共区的引用就是prototype, 因此prototype只有在函数对象中拥有,而它所指向的公共区也是一个对象,里面包含constructor, __proto__两个属性
基于最上面例子来画图大概就是
在这里插入图片描述
用代码进行简单模拟为

function Persion() {
}
let o = {
constructor: function() {},
__proto__: xxx
};
Persion.prototype = o;
// 但prototype对象的创建和赋值时自动默认进行的,当一个函数被定义时它就会存在

看到这里可以明确prototype是指向公共区的引用,而我们知道prototype也就是js中的原型概念


然后问题回到了__proto____proto__又被称为隐式原型,这个属性可以看到在例子中的persion1这个对象实例中和protype指向的对象中都有这个属性,它的作用其实和prototype很像
在函数中通过prototype指向原型(公共区),那么使用函数作为构造函数创造的实例怎么指向这个公共区原型呢?就是使用__proto__,实例person1通过这个属性指向公共区也就是原型,所以得到

persion1.__proto__ === Persion.prototype

在这里插入图片描述

而对于prototype所指对象内部的__proto__, 会指向上一级的公共区,在本例中就是Object的公共区,由此就会形成原型链继承的逻辑
在继承关系中,对一个实例对象查找某个属性或方法就会沿着原型链查找,就本例而言,

  • 1、person1.a会现在person1的实例属性中查询,也就是自身这个对象中查看是个有这个属性
  • 2、person1自身属性不存在时,查找persion1.__proto__也就是Person的公共区,也是persion1的原型
  • 3、还是找不到的话就会根据prototype对象中的__proto__指向继续向上查找,形成基于原型链继承关系的层层查找

那么在es6中提出的class语法下的prototype__proto__的指向是怎么样的呢,可以通过以下例子来感受下

class A {
}
// class语法创建类,其默认继承Object
function B() {}
// 构造函数语法创建类,其默认继承Object
let aa = new A();
let bb = new B();
aa.__proto__ === A.prototype; // true
A.prototype.__proto__ === Object.prototype; // true

bb.__proto__ === B.prototype; // true
B.prototype.__proto__ === Object.prototype; // true

// B的例子就是本文中简述的例子应该是显而易见的
// 但A是class,es6中的class属于语法糖

补充:

关于类的 prototype 属性和__proto__属性

大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype属性。Class 作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。

(1)子类的__proto__属性,表示构造函数的继承,总是指向父类。

(2)子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

class A {
}
class B extends A {
}

B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true

Object.setPrototypeOf(B.prototype, A.prototype);
// 等同于
B.prototype.__proto__ = A.prototype;

Object.setPrototypeOf(B, A);
// 等同于
B.__proto__ = A;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值