js 基础——原型链
原型链是 js 实现面向对象编程的机制。本文期待简洁地向小白介绍原型链是什么?当我们用js写代码的时候原型链体现在哪?
什么是原型、原型链
原型(prototype 属性)
我们可以类比面向对象编程中的类的概念。js 每一个函数在创建时都会生成原型对象。函数的原型对象起到的就是类的作用。
例如我们在声明一个函数之后,可以访问该函数的 prototype 属性,这个属性就是我们说的原型,他包含了 a 这个类的构造函数(即我们声明的函数)。这也就是为什么有 “ js 万物皆对象 ” 的说法,你每声明一个函数,其实就声明了一个对象类。
了解了原型对象这个概念之后,我们就可以理解为什么在 vue 实例中是要这样注册方法了Vue.prototype.fnName = () => {}
__proto__
属性和原型链
原型是怎么形成链的呢?这就离不开__proto__
属性。
每个对象都会有隐含属性__proto__
,这个属性的作用是指向原型链的上一级原型。
可以看到,当我们用 new 创建 a 的实例 c 时,c 的__proto__
指向了 a 的原型。__proto__
像一条链子一样把 c 和 c 的类连接了起来。
同时我们也发现 a 的__proto__
指向 Object 的原型,而不是 Function 的原型。这说明 new 关键字在创建实例时与 function 关键字的逻辑不一样,这个我们会在后面的章节探讨。
__proto__
的设计让我们获得了 c => a.prototype => Object.prototype => null 的原型链。
而 js 检索变量和方法的逻辑就是现在自身对象中查询,若找不到,就会根据原型链的关系逐级往上找,直到null报错。通过这一点,原型链让 JavaScript 对象拥有封装、继承和多态等面向对象特性。我们因此能够在自身创建的对象中调用 js 数据类型封装的方法。
值得一提的是,所有构造函数的原型链上层都是 Function 的原型。
function 和 new Function 创建的函数的原型原型链上层都是 Object 的原型。
constructor 构造函数
对于一个类而言,构造函数的作用是什么?是对对象进行类封装好的处理。
new 关键字创建实例实现的过程就是:
- 创建一个空对象
- 将该对象的
__proto__
赋值为输入的原型对象 - 在空对象的作用域下执行构造函数
- 返回该对象