编写思路:
原型链基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
构造函数本身跟普通函数一样,也不存在定义构造函数的特殊语法。唯一区别在于调用的方式不同,任何函数只要通过new 操作符来调用,都可以叫做构造函数。默认情况下构造函数的首字母大写,不大写也没有问题,主要是为了与普通函数区分。
创建一个新函数都会有一个prototype(原型)属性,这个属性指向函数的原型对象。

在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性是一个指向prototype属性所在函数的指针(也就是构造函数)。创建一个自定义构造函数之后,其原型对象默认只会取得constructor属性,其他方法,则会从Object继承而来的。

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。这个指针(内部属性)叫做[[Prototype]],可以通过_proto_进行或者。用它来连接实例与构造函数的原型对象。

如何读取属性值:当对象某个对象属性时,首先先从对象实例本身开始读取,如果存在就返回,不存在就开始向原型对象查找属性。
每个构造函数都有一个prototype(原型)属性,指向原型对象,而原型对象中有一个指向构造函数的指针,实例有一个指向原型对象的指针。
显示原型:每个构造函数都有一个prototype(原型)属性,指向原型对象。
隐式原型:实例有一个指向原型对象的指针(_proto_)。
假设: 让原型对象等于另一个类型的实例,会怎么样?
答:此时的原型对象将包含一个指向另一个原型(B)的指针,相应的,另一个原型(B)中也包含着一个指向另一个构造函数(B)的指针,假如另一个原型(B)又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构造了实例与原型的链条,也就是所谓原型链的基本概念。
function Person () {
this.name = '张三';
}
Person.prototype.getName = function() {
return this.name;
}
function Student() {
this.age = 18;
}
// 将Person实例赋值给Student的原型对象
Student.prototype = new Person();
Student.prototype.getAge = function(){
return this.age;
}
var student1 = new Student();
console.log(student1.getName); // '张三'
上面代码解释:
图片展示上面代码中各个构造函数、原型、实例的关系

解释上面代码中的关系
记住所有函数的默认原型都是Object实例,因此默认原型中都有一个指针,指向Object.prototype,这就是所有自定义类型都会继承toString()等方法的根本原因。
这里的代码Student继承了Person,而Person继承了Object,如果student1调用toString方法,是调用的Object.prototype中的那个方法。
总结:
__proto__,沿着原型链查找,一直找到Object.prototype.__proto__。prototype属性,会指向函数的原型对象。__proto__,会指向Object.prototype。Object.prototype.__proto__,为null。只要原型链中出现过的原型都是。
第一种使用instanceof操作符
student1 instanceof Object; // true
student1 instanceof Student; // true
student1 instanceof Person; // true
第二种isPrototypeOf()
Object.prototype.isPrototypeOf(student1); // true