30分钟了解JavaScript原型链

228 阅读3分钟

js

原型链

在程序员的世界,万物皆对象!你没有听错哦,程序员其实是不缺对象的,那为啥网上传言程序员很难找到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

插入一张图让你更清晰地了解原型链

prototype

我们可以得出以下结论

  • 构造函数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();

chain

// 让我们看一看食物链(原型链)的顶端 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

好了,JavaScript原型链就说到这里了,欢迎交流。