2

我有一个问题 node.js 结构与 javascript oop。我使用另一个类创建了一个类。

var base = function (name) {    
    this.Rows = new Array();    
};

var top = function (name) {
    this.name = name;   
};

top.prototype = new base();

var myClass = new top("");
myClass.Rows.push("a");
console.log(myClass.Rows);
var myClass2 = new top("test");
myClass2.Rows.push("b");
console.log(myClass2.Rows);

此代码返回以下结果;

[ 'a' ]
[ 'a', 'b' ]

但是我不必被算法发现为这段代码的结果?

[ 'a' ]
[ 'b' ]

谢谢你的帮忙。

已解决:我解决了这个问题。重构代码;

var base = function (name) {
  this.Rows = new Array();
}

var top = function(name) {
  top.prototype.constructor.call(this, name);
  this.name = name;
}

top.prototype = Object.create(new base());

谢谢大家。

4

2 回答 2

6

这就是 JavaScript 原型继承的工作原理。

这对于语言的新手来说似乎相当混乱:)

两个对象myClassmyClass2具有相同的原型(在 中设置top.prototype = new base();

这意味着当您访问他们的Rows属性时,因为他们都没有,所以他们访问了他们的原型之一。因为两者都是相同的,所以它们都作用于同一个对象。如果您将该行添加console.log(myClass2.Rows);到代码的末尾,它也会输出 [ 'a', 'b' ]

原型继承似乎让初学者感到困惑,因为在经典语言中,如果类A扩展类B,那么所有A的属性都会被复制到B——在 JavaScript 中情况并非如此。

如果将代码重构为以下内容,则可以完成相同的功能:

var base = function () {    

};

base.prototype.getRows = function(){
    return this.rows;
}

var top = function (name) {
    this.name = name;   
    this.rows= [];    
};

top.prototype = new base();

var myClass = new top("");
myClass.getRows().push("a");
console.log(myClass.getRows());
var myClass2 = new top("test");
myClass2.getRows().push("b");
console.log(myClass2.getRows());

这将产生您期望的“经典”结果。

然而,JavaScript 的原型模型更侧重于共享功能。我可能会将您的代码重构为:

var myClass = {Rows:[]},myClass2 = {Rows:[]};
于 2013-03-08T00:53:31.283 回答
2

是的,原型是共享的。我认为您打算使用这种类型的继承:

var base = function (name) {
    this.Rows = new Array();
};

var top = function (name) {
    base.call(this,name); // this replaces your prototype
    this.name = name;
};

var myClass = new top("");
myClass.Rows.push("a");
console.log(myClass.Rows);
var myClass2 = new top("test");
myClass2.Rows.push("b");
console.log(myClass2.Rows);

call 将调用该函数,就好像它是一个方法一样,因此它将对象设置为base,然后您使用特定属性覆盖它。正如 nrabinowitz 在评论中所指出的,这不会继承任何原型方法。

也是我最初的建议,我很喜欢,但与上述相比没有任何好处:

var top = function (name) {
    this.super=base; // these two lines replace your prototype
    this.super(name);
    this.name = name;
};

该方法将“base”变成一个成员函数,然后调用它。它将“top”设置为新的“base”对象,然后对其进行自定义。我选择“super”作为变量名,因为它类似于 Objective C 的风格。

于 2013-03-08T00:59:04.297 回答