类式继承3——借用并设置原型

综合以上两种模式,首先借用父对象的构造函数,然后将子对象的原型设置为父对象的一个新实例:

  1. function Child(a, c, b, d) {
  2. Parent.apply(this, arguments);
  3. }
  4. Child.prototype = new Parent();

这样做的好处是子对象获得了父对象的自有成员,也获得了父对象中可复用的(在原型中实现的)方法。子对象也可以传递任何参数给父构造函数。这种行为可能是最接近Java的,子对象继承了父对象的所有东西,同时可以安全地修改自己的属性而不用担心修改到父对象。

一个弊端是父构造函数被调用了两次,所以不是很高效。最后,(父对象的)自有属性(比如这个例子中的name)也被继承了两次。

我们来看一下代码并做一些测试:

  1. //父构造函数
  2. function Parent(name) {
  3. this.name = name || 'Adam';
  4. }
  5. //在原型上添加方法
  6. Parent.prototype.say = function () {
  7. return this.name;
  8. };
  9. //子构造函数
  10. function Child(name) {
  11. Parent.apply(this, arguments);
  12. }
  13. Child.prototype = new Parent();
  14. var kid = new Child("Patrick");
  15. kid.name; // "Patrick"
  16. kid.say(); // "Patrick"
  17. delete kid.name;
  18. kid.say(); // "Adam"

跟前一种模式不一样,现在say()方法被正确地继承了。可以看到name也被继承了两次,在删除掉自己的拷贝后,在原型链上的另一个就被暴露出来了。

图6-6展示了这些对象之间的关系。这些关系有点像图6-3中展示的,但是获得这种关系的方法是不一样的。

图6-6 除了继承“自己的属性”外,原型链也被保留了

图6-6 除了继承“自己的属性”外,原型链也被保留了