最近在面试,几乎每家公司都有被问到原型相关的问题,虽然看过不少文章,但总感觉自己每次回答的时候都没办法把这个知识点讲得清楚,想来还是多借鉴一些文章,然后结合自己的面试经历来整理一下。
首先什么是原型?
JavaScript中除了基本类型外的数据类型,都是对象。但是由于其没有类(class,ES6引入了class,但只是语法糖)的概念,如何将所有对象联系起来就成了一个问题,于是就有了原型和原型链的概念。
简单来说,原型和原型链是JS中解决继承的一种方案。
原型链又是如何实现的?
当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象(__proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
一些跟原型相关的重要的知识点:
- 每一个构造函数都拥有一个prototype属性,这个属性指向一个对象,也就是原型对象。当使用这个构造函数创建实例的时候,prototype属性指向的原型对象就成为实例的原型对象。
- 原型对象默认拥有一个constructor属性,指向指向它的那个构造函数(也就是说构造函数和原型对象是互相指向的关系)。
每个对象都拥有一个隐藏的属性[[prototype]],指向它的原型对象,这个属性可以通过 - Object.getPrototypeOf(obj) 或 obj.__proto__ 来访问。
实际上,构造函数的prototype属性与它创建的实例对象的[[prototype]]属性指向的是同一个对象,即 对象.__proto__ === 函数.prototype 。 - 原型对象就是用来存放实例中共有的那部分属性。
- 在JavaScript中,所有的对象都是由它的原型对象继承而来,反之,所有的对象都可以作为原型对象存在。
- 访问对象的属性时,JavaScript会首先在对象自身的属性内查找,若没有找到,则会跳转到该对象的原型对象中查找。
总结:
- 当 new 一个函数的时候会创建一个对象,『函数.prototype』 等于 『被创建对象.__proto__』
- 一切函数都是由 Function 这个函数创建的,所以『Function.prototype === 被创建的函数.__proto__』
- 一切函数的原型对象都是由 Object 这个函数创建的,所以『Object.prototype ===
一切函数.prototype.__proto__』