1

第一节内容:javaScript原型及原型链详解(二)

第一节中我们介绍了javascript中的原型和原型链,这一节我们来讲利用原型和原型链我们可以做些什么。

普通对象的继承

  var a = {
    x: 10,
    caculate: function(z) {
      console.log(this.x + this.y + z)
    }
  };

  var b = {
    y: 20,
    __proto__: a
  };

  var c = {
    y: 30,
    __proto__: a
  };

  b.caculate(30)    // 60
  c.caculate(40)    // 80

这样我们就通过的原型链实现了普通对象的继承,下面我们还是通过一张原型图来讲解一下继承的过程。
图片描述
上面代码中我们创建了三个普通对象a、b、c,其中a有一个x属性,和caculate方法;b和c都有一个y属性,同时让b和c的默认属性__proto__属性指向a对象,如图所示。
这是时候我们调用了b.caculate(30), c.caculate(40),显然b和c的自身方法中是没有caculate方法的,那么这个时候就会沿着b的原型链向上查找,然后找到了a中有caculate方法,则返回caculate方法,
如果a中也没有这个方法,那么会沿着原型链继续向上查找,找到则返回,找不到则返回undefined

函数对象的继承

比如我们有一个名为"Animal"的构造函数,还有一个叫做"Cat"的构造函数:

function Animal() {};
Animal.prototype.species = "动物";

function Cat(name, color) {
    this.name = name;
    this.color = color;
}

其中Animal对象中有一个原型属性species = "动物",Cat对象有两个自身对象name和color,这个时候我们如果需要让Cat对象拥有Animal对象中的属性应该怎么办呢? 很简单我们只需要让Cat继承Animal对象就行了,下面我们看如何让Cat继承Animal:

1    Cat.prototype= new Animal();
2    Cat.prototype.constructor = Cat;

3    var cat1 = new Cat("大白", "白色")
4    console.log(cat1.species)    // 动物

图片描述

上面的方法是通过直接继承prototype的方法实现的继承,如上图所示:我们一开始创建Cat对象时,Cat.prototype默认指向Cat的原型(如步骤1所示)。 然后我们更改Cat的原型链,让Cat.prototype指向Animal 的实例(实例中具有构造函数的所有属性和方法),如步骤2所示,这样就成功更改了Cat的原型链,当我们调用Cat.species属性时,沿着原型链就查找到Animal实例中的species属性了,这样就实现了函数对象的继承。
当然这还没完,因为我们还有重要的一步没完成,没错!就是上面的第2行代码,如果没有这行代码Animal实例中的constructor指针是指向Animal构造函数的,这样显然是不对的,因为constructor正常情况下应该指向它的构造函数,因此我们需要手动更改:Cat.prototype.constructor = Cat; 使constructor重新指向Cat对象。

我们这里讲的继承的方法只是常见的一种,另外还有多种方法实现继承,这里推荐阮一峰的一篇文章:构造函数的继承,里面讲了常见的实现继承的方法。这篇文章也是参考了里面的方法。

如果看了这两篇文章,你还是没搞清楚原型和原型链,给你推荐我学习的时候看的几篇文章,反复的看反复的阅读,总会弄明白的,毕竟我是花了三天时间才搞懂了。
最详尽的 JS 原型与原型链终极详解
深入理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)
前端开发必须知道的JS(一) 原型和继承


dayday_up
344 声望15 粉丝

韬光养晦,厚积薄发