继承与原型链 
这篇文章很详细,有几个重点如下:
1 重要概念 
每个实例对象都有一个私有属性(称之为 __proto__)指向它的构造函数的原型对象(prototype)。该原型对象也有自己的原型对象(__proto__),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
可以这样理解,每一个对象都有一个父对象,父对象也有它自己的父对象,最顶层的父对象是 null。类似 Java 中类、父类、父类的父类。
父对象是什么意思呢?即以这个父对象为“模子”来创建子对象,如父对象 fatherObj 是{a: 1, b: 2},那么子对象 subObj 也具备属性 a、b。
如何表示一个对象的父对象呢?用 __proto__ 表示,即 subObj.__proto__。
2 画原型链 
当访问一个对象的属性时,会自底向上遍历原型链查找属性,如果能找到,返回结果,停止遍历,找不到,返回 undefined。
例子一:
const o = { a: 1 }o ---> Object.prototype ---> nullo ---> o.__proto__ ---> null
例子二:
function Cat(name) {
  this.name = name
}
Cat.prototype.eat = function () {
  console.log('eat fish')
}
const cat = new Cat('小白')cat ---> Cat.prototype ---> Object.prototype ---> nullcat ---> cat.__proto__ ---> cat.__proto__.__proto__ ---> null
即:
{name: '小白'} ---> {eat: ..., constructor: ...} ---> {hasOwnProperty: ...} ---> null

例子三:
const a = ['yo', 'whadup', '?']数组都继承于 Array.prototype,其中包含 indexOf,forEach 等方法,原型链如下
a ---> Array.prototype ---> Object.prototype ---> null
例子四:
function f() {
  return 2
}函数都继承于 Function.prototype,其中都包含 call,bind 等方法,原型链如下
f ---> Function.prototype ---> Object.prototype ---> null