JS基础系列--原型和原型链的通俗理解

547 阅读3分钟

在开始讲原型和原型链之前,我们先确认以下几个概念:

  1. 所有函数都含有一个prototype属性(显式属性)
  2. 所有引用类型(函数,数组,对象)都有一个_proto_属性(隐式属性)
  3. 原型对象:拥有prototype属性的对象,在定义函数时就被创建

先知道以上3点,下面我们一步一步来说明:

第一步:我们创建一个构造函数Person

function Person(name){
    this.name = name;  // 属性name
    this.sayHello = function(){ // 方法sayHello
        console.log(name + 'say hello');
    }
}

现在创建一个实例对象moose并传入名字“moose”

var moose = new Person('moose');

这时候我们来打印一下,看看moose是不是拥有Person的属性和方法

moose.sayHello(); // moose say hello

    我们知道moose这个对象在创建的时候并没有直接创建sayHello()方法,即使大家知道从Person中继承过来的,那到底是怎么实现的呢?这就是我们接下来要讲的原型和原型链。

    在Person这个构造函数定义的时候,同时创建的还有一个与之关联的“原型对象”,这个对象毕竟不是我们手动创建命名的一个对象,那要使用这个“原型对象”怎么办呢?JS提供了一个属性“prototype”给函数。Person.prototype就指向这个“原型对象”。

    这个时候我们通过Person这个构造函数创建了一个实例对象“moose”,要想实现继承这样一个关系,moose必须能够使用Person中的属性和方法。JS的做法是给实例对象提供了一个"__proto__"的属性,moose.__proto__也指向Person对应的这个实例对象。这样我们就得出了一个小结论:

console.log(Person.prototype === moose.__proto__); // true

到目前为止,原型链继承就实现了。

第一步原型关系图如下:


第二步:既然实例对象和构造函数都可以指向原型,那么原型是否有属性指向构造函数或者实例呢?

很遗憾,原型没有指向实例对象的属性,但是指向构造函数的有啊~:constructor登场

console.log(Person === Person.prototype.constructor); // true


既然说了原型相关的概念,我们不妨在说一下原型链,简单的说,原型链就是一条由一堆上下等级分明的原型组成的继承链。

第三步:就上面的例子而言:moose通过__proto__找到自己的原型,继承原型对应函数的属性和方法。那么我们难想到,原型对象本身就是一个对象呀,也拥有__proto__属性,那么它的原型又会是什么呢?

console.log(Person.prototype);


console.log(Person.prototype.__proto__ === Object.prototype); // true

从浏览器中打印出的结果页可以看到,Object.prototype原型的constructor属性指向的是Object函数。



那么Object.prototype的原型又是什么呢?

console.log(Object.prototype.__proto__); // null


这就说明Object.prototype 已经没有原型了,Object对象是根对象。

以上一整个查找原型的过程走的就是这样一条清晰的原型链。

拓展问题:instanceof原理是什么?

// 我们以数组为例
var arr = []
arr instanceof Array

    instanceof原理就是利用了原型链,当执行arr instanceof Array时,会从arr的_proto_一层一层往上找,看是否能不能找到Array的prototype。
    我们知道var arr = [] 其实是var arr = new Array()的语法糖,所以arr的_proto_指向Array的prototype,结果返回true

到此为止,我们大体的梳理了一下原型以及原型链相关的内容

特别感谢提供相关内容参考:

    github.com/mqyqingfeng…

    www.jianshu.com/p/6ec881835…

    segmentfault.com/a/119000001…

附:感谢您的阅读,希望对您有所帮助。如果以上内容中存在疑问和错误,欢迎留言或者私信。