我应该在构造函数中添加什么:与实例相关的东西或与类相关的东西?
考虑以下代码:
var count = 0
TView = function (x, y) { this.x = x, this.y = y, this.id = count++ }
TGroup = function() {}
TGroup.prototype = new TView
var v1 = new TView(1, 1)
var g1 = new TGroup(2, 2)
console.log(count, v1.id, g1.id, g1.x, g1.y)
输出:
2 1 0 undefined undefined
这里new TView
发生了两次......一旦我真的需要创建一个TView
实例,其他时候我分配一个TGroup
原型。因此我的问题。
答案 0 :(得分:1)
这里的问题是你的构造函数的参数没有从TGroup的构造函数传递给TView的构造函数......并且不打扰添加“super(x,y)”或类似的调用,它将不起作用:构造函数在JavaScripts“对象”并非“面向对象”。
免责声明:以下段落中的说明包含一些不完全正确的陈述,以便使关键概念更易于理解。请参阅下面的评论以获得澄清和纠正。
更好的思考方式是JavaScript中的对象基本上是一个哈希映射,包含常规值(即对象的字段)和函数(即方法)。这个类也是一个映射(好吧,它是一个函数,但JavaScript在这些方面有点糟糕......),它通常包含一个方法,也许还有一些值。现在,“类”地图上的其中一个值存储是特殊的“原型”地图。
当通过在“类”对象上使用new运算符创建新的“实例”映射时,会发生以下三种情况:首先,创建一个新映射;然后,类映射原型数组中存在的每个键值都被复制到新创建的映射,以及构造方法;最后,使用给定的参数调用构造函数方法。
所以你应该知道为什么,在你的例子中,你需要创建一个新的TView实例传递给TGroup.prototype。这意味着在创建TGroup的新实例时,它们将首先复制您在那里创建的第一个对象中的所有内容。注意到你的TGroup有id 0?那是因为TGroup复制了有史以来第一个TView的id。无论你创建多少个TGroup,它们都会有id 0.你的x和y参数:你设置TGroup的原型时所给的那个,无论你给TView输入什么。
请注意,此方法还存在其他问题。最重要的是,您不能简单地覆盖父方法,然后调用您的超级原始版本。
现在,有哪些解决方案?实际上有几个。其中一个可能是使用ECMA Script对象的最新功能,但我不会去那里。还有一些JavaScript库提供了更“面向对象”的策略。
最简单的策略可能只是遵循一个简单的习惯用法,即在每个实例原型中添加一个init_class name here方法,然后让你的构造函数调用init_ ()方法;然后,每个init _ ()方法应显式调用它的父init _ *()方法,传递需要给出的任何参数。
答案 1 :(得分:1)
您不应该创建Parent的实例来设置继承的原型部分,因为将共享Parent的实例特定成员(Parent的实例是Child.prototype)。
您的Child类不会重复使用Parent构造函数代码并初始化特定于实例的成员(this.something,this.somethingElse)。
通过原型和构造函数继承时,传递一个对象而不是单独的参数可能更好。
有关这三者的更详细说明,您可以找到here。