为什么人们在使用apply()和call()方法很容易继承时在javascript中使用原型?

时间:2013-05-09 11:20:03

标签: javascript inheritance prototype

Shape由矩形继承。这种继承可以通过许多方法完成。这里我使用了apply()和call()。当draw方法是child被调用时,从那个方法再次调用基类的draw方法。我以两种方式完成了这件事。一个是制作基类的原型绘制方法,另一个是使用apply()和call()方法 第一种方法:

function Shape () {
  this.name='Shape';
  this.getName = function () {
   return this.name;
  };
  this.draw = function () {
   alert("Something");
  };
} 

function Rectangle () {
  Shape.apply(this);
  var X=this.draw;
  this.name = 'rectangle';
  this.id=500;
  this.draw = function () {
    X.call(this);
  };
}

第二种方法:

function Shape () {
  this.name='Shape';
  this.id=100;
  this.getName = function () {
    return this.name;
  };
}

Shape.prototype.draw = function() {
  alert("Something");
};

function Rectangle () {
  this.name = 'rectangle';
  this.id=200;  
  this.draw = function () {
    Shape.prototype.draw.call(this);
  };
}

Rectangle.prototype = new Shape();
Rectangle.prototype.constructor = Rectangle;

这两种方法都做类似的事情(在提供输出的情况下)。我知道通过使用apply()和call()方法,我无法直接获取基类原型的访问权限。使用apply()和call()的继承对我来说似乎不那么复杂。如果两者都相同那么为什么人们不使用apply()和call()那么多?为什么我需要使用原型?如果我不使用原型并使用apply()和call()继承基类,我将面临什么问题?

2 个答案:

答案 0 :(得分:2)

继承使您能够使用基类的方法(和属性),而无需在派生类中显式创建它们(或链接到它们)。

您的“备用”方法需要每个方法Shape实现通过每个派生类进行代理,即使该派生类没有专门化该方法

使用原型可以避免这种情况,因为无论何时调用方法或访问派生类中不存在的属性,JS解释器都会自动遍历属性链,直到它在超类中找到该方法。

答案 1 :(得分:0)

一个区别是Rectangle类的'draw'函数是一个实例变量;因此它将在 Rectangle的每个实例中使用内存。

此外,如果您正在使用原型,并且您根本不想更改父方法的行为(例如,在第二个示例中,Rectangle的'draw'方法除此之外不会执行任何操作Shape的draw方法,那么你不必重新定义方法 - 当在矩形上调用'draw'时,运行时将爬上原型链,找到正确的链接形状

所以你的第二个例子可能是:

function Shape () {
  this.name='Shape';
  this.id=100;
}

Shape.prototype.getName = function () {
  return this.name;
};

Shape.prototype.draw = function() {
  alert("Something");
};

function Rectangle () {
  this.name = 'rectangle';
  this.id=200;  
}

// Notice we don't repeat "getName" since it is defined in 
// the parent class, and there is no need to do something else. 

// In case you actually want to "override" the behavior
Rectangle.prototype.draw = function () {
  Shape.prototype.draw.call(this);
  alert("Do something else than Shape");
};

Rectangle.prototype = new Shape();
Rectangle.prototype.constructor = Rectangle;