
原型链
在程序员的世界,万物皆对象!你没有听错哦,程序员其实是不缺对象的,那为啥网上传言程序员很难找到GF呢?接下来我们对程序员的对象一探究竟。
程序员的对象是这样的:
每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
基于原型链的继承
继承属性
对象在访问属性或方法时,先检查自己的实例,如果存在就直接使用。如果不存在那么就去原型对象上去找,存在就直接使用,如果没有就顺着原型链一直往上查找,找到即使用,找不到就重复该过程直到原型链的顶端,如果还没有找到相应的属性或方法,就返回undefined。
// 让我们从一个自身拥有属性a和b的函数里创建一个对象o
function man() {
this.name = 'theway';
this.age = 30;
};
let d = new man(); // {name: 'theway', age: 30}
// 在man函数的原型上定义属性
man.prototype.age = 18;
man.prototype.sex = 'male';
// 不要在 man 函数的原型上直接定义 man.prototype = {age: 18, sex: male};这样会直接打破原型链
// d.__proto__ 有属性 age 和 sex
// (其实就是 man.prototype 或者 d.constructor.prototype)。
// 综上,整个原型链如下:
// {name: 'theway', age: 30} ---> {age: 30, sex: 'male'} ---> Object.prototype---> null
插入一张图让你更清晰地了解原型链

我们可以得出以下结论
-
构造函数Man可以通过prototype属性访问到它的原型对象。
-
通过构造函数Man实例化出来的 d 可以通过__proto__属性访问到Man的原型对象。
-
Man的原型对象可以通过constructor(构造器)属性访问其关联的构造函数。
-
d 可以通过 constructor 访问到构造函数
我们可以通过三种方式来访问原型对象
-
构造函数.prototype
-
实例对象.proto
-
object.getPrototypeOf(实例对象)
prototype: 函数对象拥有的属性,指向它的原型对象。 proto
proto: 所有的对象都拥有__proto__属性,指向实例的原型。
constructor construtor 构造器,原型对象可以通过constructor来访问其所关联的构造函数。当然,每个实例对象也从原型中继承了该属性。
注意: __proto__属性并不在ECMAScript标准中,只为了开发和调试而生,不具备通用性,不能出现在正式的代码中。
搞清楚了以上概念,我们再来看下原型链:
function Man () {};
function Woman () {};
var m1 = new Man();
var w1 = new Woman();

// 让我们看一看食物链(原型链)的顶端 null
Object.prototype.__proto__; //null
// Function.prototype的原型对象为Object.prototype而不是它自己
Function.prototype.__proto__ == Object.prototype; //true
// Function和Object的构造函数都是Function
Function.constructor == Function; //true
Object.constructor == Function; //true
// Function.prototype的构造函数是Function
Function.prototype.constructor == Function; //true
// m1的原型对象为Man.prototype
m1.__proto__ == Man.prototype; //true
// Man.prototyepe|Woman.prototype的constructor指向Man|Woman的构造函数
// Man.prototyepe|Woman.prototype的原型对象为Object.prototype
// 先删除实例成员,通过原型成员访问
delete Man.prototype.constructor;
delete Woman.prototype.constructor;
Man.prototype.constructor == Object; //true
Woman.prototype.constructor == Object //true
Man.prototype.__proto__ == Object.prototype; //true
Woman.prototype.__proto__ == Object.prototype; //true
// Man和Woman的构造函数为Function
// Man和Woman的构造函数的原型对象为空函数
Man.constructor == Function; //true
Woman.constructor == Function; //true
Man.__proto__ == Function.prototype; //true
Woman.__proto__ == Function.prototype; //true