第一节中咱们介绍了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中也没有这个方法,那么会沿着原型链继续向上查找,找到则返回,找不到则返回undefinedhtml
好比咱们有一个名为"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:java
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对象。segmentfault
咱们这里讲的继承的方法只是常见的一种,另外还有多种方法实现继承,这里推荐阮一峰的一篇文章:构造函数的继承,里面讲了常见的实现继承的方法。这篇文章也是参考了里面的方法。函数
若是看了这两篇文章,你仍是没搞清楚原型和原型链,给你推荐我学习的时候看的几篇文章,反复的看反复的阅读,总会弄明白的,毕竟我是花了三天时间才搞懂了。
最详尽的 JS 原型与原型链终极详解
深刻理解JavaScript系列(10):JavaScript核心(晋级高手必读篇)
前端开发必须知道的JS(一) 原型和继承学习