先通过一张图来了解一下 prototype 和 __proto__

__proto__ 这个属性(除了 null),指向的就是他们类的原型,例如
    function 的 __proto__ 都是指向 Function.prototype,包括普通的 function Foo() 还有 function Object() 和 function Funtion()Foo 的实例,所以 __proto__ 指向的是 Foo.prototypeFunction.prototype 的 __proto__ 则是指向 Object.prototypeObject.prototype 的 __proto__ 指向的是 nullfunction 才有 prototype 属性,指向的是自己的原型,就像
    function Foo() 的 prototype 就是指向 Foo.prototypefunction Object() 的 prototype 就是指向 Object.prototypefunction Function() 的 prototype 就是指向 Function.prototype原型链继承,简单的说就是子类的原型是父类的实例。
var Person = function (age) {
  this.age = age;
};
Person.prototype = {
  sayAge: function () {
    console.log(this.age);
  }
};
var Student = function (name, age) {
  this.name = name;
  this.age = age;
};
Student.prototype = new Person();
var Jason = new Student('Jason', 21);
Jason.sayAge() // 21
这样就可以继承父类原型的方法。但是在构造子类的时候,没有办法给父类传递参数。
这时候就要用类式继承(借用构造函数)
类式继承其实就是子类的构造函数用 call 借用了父类的构造函数。这样就可以给父类传递构造的参数了
var Person = function (age) {
  this.age = age;
};
Person.prototype = {
  sayAge: function () {
    console.log(this.age);
  }
};
var Student = function (name, age) {
  Person.call(this, age);
  this.name = name;
};
var Jason = new Student('Jason', 21);
但是这样就还不可以与父类共享原型中的方法,所以一般我们会把原型链继承和类式继承组合使用,称组合继承
var Person = function (age) {
  this.age = age;
};
Person.prototype = {
  sayAge: function () {
    console.log(this.age);
  }
};
var Student = function (name, age) {
  Person.call(this, age);
  this.name = name;
};
Student.prototype = new Person();
var Jason = new Student('Jason', 21);