[面试]这可能是最悲凉的原型链理解

681 阅读4分钟

慢慢理解世界,慢慢更新自己。

写于,实习一个月部门解散后,坐在工位无所事事。

对于原型链的理解

原型链并不是一个独立的概念,在MDN的官网上,我们去查原型链这个名词的时候,我们会搜索到一个“继承与原型链” ,那么说明,我们在理解原型链时,需要将其与继承相关联。

在面向对象编程中,我们常常会遇到继承到概念,“extends” 其实,extend直译是 延长,拓展,扩大的意思。其实基于原型链的继承,同样也是为了解决扩展的需求。

在编程中,我们经常会想获取并扩展一些东西。假如,我们有一个person对象及其属性和方法, 并希望studentteacher作为基于person稍加修改的变体。我们想重用person中的内容,而不是复制/重新实现它的方法,而只是在其之上构建一个新的对象。

那么相对于面向对象的extends, JavaScript使用了原型继承。

原型继承

我们上面有粗略提到JavaScript提出原型继承的一个目的,那么它的设计思想是

原型对象上的属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。

那么对于上面这句话,我们需要明确的有两部分

  1. 什么是原型对象?
  2. 实例对象是什么?

请看如下代码

function Person(name, age) {
	this.name = name;
  this.age = age;
}

let person1 = new Person('gaoxing', 18);
let person2 = new Person('danxiao', 19);

那么可以想一下,上面代码中那个是原型对象,那个是实例对象。

首先,很明确,person1,person2是实例对象。

那么,类推,原型对象是 函数Person吗?

明确的回答,不是

原型对象是Person.prototype。

所以当我们看见以下代码的时候,就会更加明确JavaScript提出原型继承的设计思想。

function Person(name, age) {
	this.name = name;
  this.age = age;
}
// 将通用方法写在原型对象上
Person.prototype.sayName = function(){
	console.log('我的名字是'+this.name);
}
let person1 = new Person('gaoxing', 18);
let person2 = new Person('danxiao', 19);
// 原型对象上的方法,被实例对象共享
person1.sayName();
person2.sayName();

那么,函数Person是什么?其实,可以理解成一个构造器。用来生成实例对象。

官方定义: 在JavaScript中,prototype对象是实现面向对象的一个重要机制。每个函数就是一个对象(Function),函数对象都有一个子对象prototype对象,类是以函数的形式来定义的。 prototype表示该函数的原型,也表示一个类的成员的集合。

也就是说,每个函数都有自己的一个prototype属性。

那么,实例对象是如何与原型对象建立关系的呢?

在JavaScript中,对象有一个特殊的隐藏属性[[Prototype]],它要么为null, 要么就是对另一个对象的引用。被引用的对象被称为原型。

这个属性是隐藏属性,我们无法直接去操纵它。但是JavaScript提供了一个获取对象对应原型的方法。

Object.getPrototypeOf(obj)

那么,我们经常使用的 __proto__是什么呢?

__proto__属性是一个访问器属性(一个getter函数和一个setter函数),暴露了通过它访问的对象的内部[[Prototype]]。

它一开始并不是JavaScript官方支持的,而是浏览器支持的,并且不断普遍,直到现代浏览器都实现了它,JS才将其标准化。

当在一个实例对象中找不到对应的属性和方法的时候,JS就会通过[[Prototype]]向上寻找,只要搜寻的这个对象上有[[Prototype]],并且在这个对象上没有找到想要找的东西,那么就会一直找下去。

对象的原型对象的原型是null。

从一开始的实例对象向上找原型上属性或者方法的过程,形成一个链状(解释有点牵强,相信各位帅哥美女都能懂我的意思。)所以被称为原型链。

下面请看一个经典的图,并尝试用我上面说的,去理解它

图片来自 juejin.cn/post/684490…

constructor

其实根据上面的图,和这个单词的意思(构造器)。就能很好的理解这个的作用。

就是原型对象指向构造函数的一个指针。

在构造函数执行new的时候发生了什么?

大家可以参考,我之前写的

juejin.cn/post/720850…

结语

近距离接触了“毕业”,本来充满欢乐的部门,现在满是人走茶凉的悲凉。

望诸君武运昌隆。前路漫漫,我们江湖再见!

参考资料