【问题标题】:javascript and node.js: oopjavascript 和 node.js:哎呀
【发布时间】:2013-02-23 10:56:55
【问题描述】:

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

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());

谢谢大家。

【问题讨论】:

标签: javascript arrays node.js oop


【解决方案1】:

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

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 在 cmets 中所指出的,这不会继承任何原型方法。

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

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的风格。

【讨论】:

  • 这是一种有趣的方法(但请注意,它不支持base 方法的原型继承,仅支持构造函数设置)。更常见的 JS 习惯用法可能是使用 base.call(this)base.apply(this, arguments)(如果您需要在构造函数之间使用公共 args)。
  • 我没有想到.call,当然会更好(更快,更少的可变污染)。我会更新它,但老实说我很喜欢“超级”风格!
  • 这很有趣:)。请注意,您提到的两行 not 替换了原型(它仍然是 Object)。更令人困惑的是,您正在调用函数构造函数,就像调用普通函数一样。我不推荐这种方法,因为它似乎违背了 JavaScript 的原型特性,但它仍然是一个非常有趣的想法。
  • 这是伟大的工作 :) 谢谢大家。我需要了解更多的javascript。 :)
  • @BenjaminGruenbaum:我已经用关于原型的注释更新了它(我不经常使用原型,所以我没有考虑过)。但是当不需要 Base 的原型时,我认为这种方法没有问题,而且它肯定比我见过的任何其他方法都更简单、更直观。
【解决方案2】:

这就是 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:[]};

【讨论】:

  • 我希望结果集中的每一行都创建一个新对象。以便正确的结果 ['a'] ['b'] 我想要。 var base = function (name) { this.Rows = new Array (); }; // var top = function(name) { // this.name = name; //}; //top.prototype = new base(); var myClass = new base (""); myClass.Rows.push("a"); console.log (myClass.Rows); var myClass2 = 新基数 (""); myClass2.Rows.push ("b"); console.log (myClass2.Rows);这样的代码是正确的结果。结果在另一个类中出错,该类已经生成。
  • @KiPSOFT 我认为您的问题需要对 JavaScript oop 的工作原理有一点了解,如果您想更深入地讨论它是如何工作的,欢迎您访问chat.stackoverflow.com/rooms/17/javascript很想解释一下 JavaScript OOP 设计的工作原理 :)
  • :) 我现在明白了。你定义上层阶级。所以我想产生不止一个类我用一个子类为每个类重新定义Rows属性有什么用?
  • 在建议其他方法之前,我会喜欢一个实际的用例。如果您想了解更多关于 JavaScript 设计模式的信息,Addy Osmani 有一本关于该主题的好书 addyosmani.com/resources/essentialjsdesignpatterns/book。我发现在实践中我很少求助于经典的 oop 子类化,因为没有它我在 JavaScript 中获得了两个主要好处(多态性 - JS 是动态的,功能共享 - 原型设计)。可悲的是,构建可维护且正确的 JavaScript 代码超出了单个 SO 问题的范围 :-)
  • @KiPSOFT 运气好吗?你最后做了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-01
  • 2019-02-13
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多