Javascript 原型与继承

Javascript 原型与继承,javascript,Javascript,最近我从Java世界开始学习Javascript。我把这本书叫做。我现在对原型和继承有点困惑。我想知道将函数设置为对象属性和函数原型之间的区别。从书中的例子: function Rectangle(w, h) { this.width = w; this.height = h; this.area = function( ) { return this.width * this.height; } } 使用此新版本的构造函数,您可以编写如下代码: // How big is a sheet o

最近我从Java世界开始学习Javascript。我把这本书叫做。我现在对原型和继承有点困惑。我想知道将函数设置为对象属性和函数原型之间的区别。从书中的例子:

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.prototype.area = function() {
    return this.width * this.height;
};
矩形对象始终引用相同的函数

那是不对的。每个
矩形
对象都将有其自己的函数副本分配给
区域
属性

而如果使用基于原型的定义,则会在所有实例中共享一个函数

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

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

在这种情况下,我应该将区域定义为原型:Rectangle.prototype.area=function()。。。这样所有的重角共享相同的函数,因为矩形的计算面积总是相同的,这是一件好事。当具有或高度更改时,调用区域确保始终返回正确的值。您可以在创建对象时设置面积,但随后您必须为with和height创建getter和设置,以便在更改任何一个对象时重新计算面积。如果您想了解prototype的工作原理以及如何从函数创建对象实例,请试着运行以下代码:我建议使用Firefox和firebug插件或Chrome,您可以在控制台中复制和粘贴代码,并运行它,而无需每次重新加载页面。@HMR:上面已经有一个“参考”答案,所以:我发布的链接是针对试图了解原型如何工作的人的(基本)。你发布的链接是一个很好的完整参考,但在开始时很难理解。更完整一点的是goog.inherits,它设置了childs超类,当您想在使用goog.base(在同一页上)@zerkms+1重写父函数时使用它,谢谢您的链接。使用_init,goog.inherit解决参数化构造函数的好方法需要您自己调用Parent.call或Parent.apply。在这种情况下,我应该将区域定义为prototype:Rectangle.prototype.area=function()。。。这样所有的重角共享相同的函数,因为矩形的计算面积总是相同的,这是一件好事。当具有或高度更改时,调用区域确保始终返回正确的值。您可以在创建对象时设置面积,但随后您必须为with和height创建getter和设置,以便在更改任何一个对象时重新计算面积。如果您想了解prototype的工作原理以及如何从函数创建对象实例,请试着运行以下代码:我建议使用Firefox和firebug插件或Chrome,您可以在控制台中复制和粘贴代码,并运行它,而无需每次重新加载页面。@HMR:上面已经有一个“参考”答案,所以:我发布的链接是针对试图了解原型如何工作的人的(基本)。你发布的链接是一个很好的完整参考,但在开始时很难理解。更完整一点的是goog.inherits,它设置了childs超类,当您想在使用goog.base(在同一页上)@zerkms+1重写父函数时使用它,谢谢您的链接。使用_init,goog.inherit解决参数化构造函数的好方法需要您自己调用Parent.call或Parent.apply。@Adio:就我个人而言,我不认为还有其他区别。重新设置和重新定义区域将影响矩形的所有实例,即使是在重新定义区域函数之前创建的实例。不能更改实例上原型的值:b=new Rectangle();b、 面积=55;这将向b添加一个值为55的area属性,但不会影响其他矩形实例的面积(它们从矩形中获取)。这让人困惑,所以我给你发了一个链接,让你再次尝试:@HMR:我不知道你在说什么。在继续争论之前,请指出我说过的话,它会改变它。而且,嗯,我确实理解javascript中引用是如何工作的。这并没有让我感到困惑,因为我完全理解基于原型的继承在js中是如何工作的。@zerkms试图回答Adio的问题“还有其他区别吗”,假设他是指用“this”或prototype指定属性(甚至不提var/closures)。令人困惑的部分是针对OP的,因为通过原型的“继承”并不像在基于类的语言中那样工作。在评论中解释起来并不容易,因此贴出了人们最喜欢的东西的链接(比如不希望实例之间共享原型值,也不能通过实例分配原型的新值)。我发现我忘记了pref注释中的@Adio,很抱歉。@Adio:我个人认为我不会在意其他差异。重新设置和重新定义区域将影响矩形的所有实例