【问题标题】:Prototypes and Inheritance原型和继承
【发布时间】:2013-05-20 22:17:30
【问题描述】:

最近我开始学习 Javascript,因为我来自 Java 世界。我得到了这本书,名为JavaScript The Definitive guide.。我现在对原型和继承有点困惑。我想知道将函数设置为对象属性和函数原型有什么区别。来自书中的例子:

function Rectangle(w, h) {
this.width = w;
this.height = h;
this.area = function( ) { return this.width * this.height; }
}

使用这个新版本的构造函数,您可以编写如下代码:

// How big is a sheet of U.S. Letter paper in square inches?
var r = new Rectangle(8.5, 11);
var a = r.area( );

这个解决方案效果更好,但仍然不是最优的(为什么)。创建的每个矩形都会有 三个属性(是的,那又怎样?)。每个的宽度和高度属性可能不同 矩形,但每个 Rectangle 对象的面积总是指同一个 函数(当然,有人可能会更改它,但您通常打算使用这些方法 一个对象是恒定的)。对方法使用常规属性是低效的 旨在由同一类的所有对象共享(为什么???有什么问题?)(即所有对象 使用相同的构造函数创建)。

【问题讨论】:

  • 在这种情况下,我应该将 area 定义为原型: Rectangle.prototype.area=function()... 这样所有 Recangle 共享相同的函数,因为 Rectangle 的计算面积总是相同的,这是一个好东西。当 with 或 height 发生变化时,调用 area 确保始终返回正确的值。您可以在创建对象时设置面积,但是您必须为 with 和 height 创建 getter 和设置,以便在更改其中任何一个时重新计算面积。
  • 如果你想了解原型如何工作以及如何从函数创建对象实例而不是尝试运行此代码:stackoverflow.com/questions/16063394/… 我建议使用带有 firebug 插件的 Firefox 或 Chrome,你可以复制和粘贴代码在控制台中运行它,而无需每次都重新加载页面。
  • @HMR:SO 上已经有一个“参考”答案:stackoverflow.com/questions/1595611/…
  • 我发布的链接是针对那些试图了解原型如何工作的人(基本)。您发布的链接是一个很好的完整参考,但在开始时很难消化。更完整一点是 goog.inherits docs.closure-library.googlecode.com/git/… 这将设置 childs superClass_ 当您想在使用 goog.base 覆盖父函数时调用父函数(在同一页面上)
  • @zerkms +1 感谢您提供链接。用_init解决参数化构造函数的好方法,goog.inherit需要你自己调用Parent.call或Parent.apply。

标签: javascript


【解决方案1】:

矩形对象总是引用同一个函数

这是不正确的。每个rectangle 对象都有自己的分配给area 属性的函数副本。

如果您使用基于原型的定义,您将在所有实例之间共享一个函数。

所以从性能和内存消耗的角度来看,最好将其定义为

Rectangle.prototype.area = function() {
    return this.width * this.height;
};

【讨论】:

  • @Adio:我个人认为我不会关心其他差异。
  • 重新设置和重新定义区域将影响 Rectangle 的所有实例,即使是在重新定义区域函数之前创建的实例。您不能更改实例上原型的值: b=new Rectangle();b.area=55;这将向 b 添加一个 area 属性,值为 55,但不会影响其他 Rectangle 实例的 area (它们从 Rectangle 中获取)。这很令人困惑,所以我将链接发送给您以再次进行实验:stackoverflow.com/questions/16063394/…
  • @HMR:我不知道你在说什么。在继续争论之前,请指出我的话,当我说它会改变它时。而且,嗯,我确实了解引用在 javascript 中是如何工作的。这并没有让我感到困惑,因为我完全理解基于原型的继承在 js 中是如何工作的。
  • @zerkms 试图回答 Adio 的问题“是否存在其他差异”,假设他的意思是用“this”或原型指定属性(甚至没有提到 var/closures)。令人困惑的部分是针对 OP,因为通过原型的“继承”并不像在基于类的语言中那样真正起作用。在评论中解释起来并不容易,因此发布了与人们最常见的事情的链接(例如不期望在实例之间共享原型值,并且无法通过实例分配原型的新值)。我看到我忘记了 pref 评论中的 @Adio,对此感到抱歉。
猜你喜欢
  • 2013-07-17
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多