原型链和继承

在一切开始之前回顾一下实例prototype__proto__的关系

function Person(nick, age){
    this.nick = nick;
    this.age = age;
}
Person.prototype.sayName = function(){
    console.log(this.nick);
}

var p1 = new Person();
p1.sayName();

image

  1. 我们通过函数定义了类Person,类(函数)自动获得属性prototype
  2. 每个类的实例都会有一个内部属性__proto__,指向类的prototype属性

有趣的现象

我们定义一个数组,调用其valueOf方法

[1, 2, 3].valueOf(); // [1, 2, 3]

很奇怪的是我们在数组的类型Array中并不能找到valueOf的定义,根据之前的理论那么极有可能定义在了Array的prototype中用于实例共享方法,查看一下

image

我们发现Arrayprototype里面并未包含valueOf等定义,那么valueOf是哪里来的呢?

一个有趣的现象是我们在Object实例的__proto__属性(也就是Object的prototype属性)中找到了找到了这个方法

image

那么Array的实例为什么同样可以查找到Object的prototype里面定义的方法呢?

查找valueOf过程

因为任何类的prototype属性本质上都是个类Object的实例,所以prototype也和其它实例一样也有个__proto__内部属性,指向其类型Object的prototype

我们大概可以知道为什么了,自己的类的prototype找不到的话,还会找prototype的类型的prototype属性,这样层层向上查找

大概过程是这样的

  1. 记当前对象为obj,查找obj属性、方法,找到后返回

  2. 没有找到,通过obj的__proto__属性,找到其类型Arrayprototype属性(记为prop)继续查找,找到后返回

  3. 没有找到,把prop记为obj做递归重复步骤一,通过类似方法找到prop的类型Object的 prototype进行查找,找到返回

image

画的比较丑,看个大师的手笔

image

图片来源

这就是传说中的原型链,层层向上查找,最后还没有就返回undefined

类型

我们之前介绍过instanceof操作符,判断一个对象是不是某个类型的实例

[1, 2, 3] instanceof Array; //true

可以看到[1, 2, 3]是类型Array的实例

[1, 2, 3] instanceof Object; //true

这个结果有些匪夷所思,怎么又是Array的实例,又是Object的实例,这不是乱套了

其实这个现象在日常生活中很常见其实,比如我们有两种类型

  1. 类人猿
  2. 动物

我们发现黑猩猩既是类人猿这个类的物种(实例),也是动物的实例

是不是悟出其中的门道了,类人猿是动物的一种,也就是说我们的两个类型之间有一种父子关系

这就是传说中的继承,JavaScript正是通过原型链实现继承机制的

results matching ""

    No results matching ""