【问题标题】:Constructor and inheriting properties from super class in javascriptjavascript中超类的构造函数和继承属性
【发布时间】:2020-07-13 01:55:25
【问题描述】:

我有一个关于在 javascript 中演示继承的代码的问题。 代码基于https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

您可以在这里观看现场演示:https://jsfiddle.net/gk6xar8w/3/

代码如下:

// Shape - superclass
function Shape() {
  this.x = 1;
  this.y = 2;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.',this.x,this.y);
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
  console.log("###### Inside Rectangle.constructor ######");
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 2); // Outputs, 'Shape moved. 2, 4'
rect.move(1, 2); // Outputs, 'Shape moved. 3, 6'

我有两个问题。

首先,我不确定Rectangle.prototype.constructor = Rectangle 的作用是什么。即使我注释掉这条线,我仍然得到相同的输出。为了帮助我理解,我在function Rectangle() {...} 中记录了“#### Inside Rectangle.constructor #####”。但即使我注释掉Rectangle.prototype.constructor = Rectangle,也会记录下来。

其次,最后两行都是rect.move(1, 2),它们的行为不符合我的预期。第一次调用输出2, 4,第二次调用输出3, 6

我们从父类中定义的this.x = 1this.y = 2 开始。我们第一次调用 rect.move(1,2) 时,它按预期添加了 x:1+1=2 和 y:2+2=4。但是第二次,它不像预期的那样 x:2+2=4 和 y:4+4=8。相反,它保留 this.x = 1this.y = 2 的初始值并执行 x: 1+2=3 和 y: 2+4=6

如果我能修复代码以便第一次调用 rect.move(1,2) 输出 2, 4 和第二次调用输出 4, 8 和第三次输出 8, 16 等等,那就太好了。

谢谢。

【问题讨论】:

  • 两次,您都要求它移动(1, 2)。我不确定您为什么期望结果会有所不同
  • 我想做多个移动和 x 和 y 的值以保持不变。如果我们不止一次地移动(1,2),在这种情况下它们会给出不同的值。
  • 要回答您的第一个问题,请参阅developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
  • xy 的值 保持不变。把它分解;以x: 1, y: 2 开头,然后添加(1, 2),即x: 1 + 1 = 2y: 2 + 2 = 4。现在的值是x: 2, y: 4。然后再次添加(1, 2),即x: 2 + 1 = 3y: 4 + 2 = 6
  • 我再问一次,你为什么希望它们有所不同?请编辑您的问题以解释您认为它们应该是什么以及您为什么这么认为

标签: javascript inheritance


【解决方案1】:

至于你的第一个问题,Rectangle.prototype.constructor = Rectangle 没有效果。那行设置了 Rectangle 类的构造函数,但是Rectangle()函数已经是构造函数,所以没有效果。

对于第二个问题,move 函数通过传递给函数的 x 值更改对象的 x 值。 y 值也是如此。 2+1=3 和 4+2=6

如果您希望 x 和 y 值每次翻倍,您可以使用此函数:

Shape.prototype.move = function() {
    this.x += this.x; // <-- uses this.x instead of x parameter
    this.y += this.y; // <-- uses this.y instead of y parameter
    console.info('Shape moved.',this.x,this.y);
};

【讨论】:

  • 如果 xy 值从未使用过,那么将它们传递给 move 有什么意义?
  • 对。他们可能应该被删除
【解决方案2】:

我现在明白了。

// Shape - superclass
function Shape() {
  this.x = 1;
  this.y = 2;
}

// superclass method
Shape.prototype.move = function() {
  this.x += this.x;
  this.y += this.y;
  console.info('Shape moved.',this.x,this.y);
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
  console.log("###### Inside Rectangle.constructor ######");
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(); // Outputs, 'Shape moved.'
rect.move(); // Outputs, 'Shape moved.'

这输出 1,2 -> 2,4 -> 4,8 -> ...并且不需要 move() 的参数。

在原始代码中,this.xthis.y 保持不变。很抱歉造成混乱,非常感谢。

这是一个有效的代码:

// Shape - superclass
function Shape() {
  this.x = 1;
  this.y = 2;
}

// superclass method
Shape.prototype.move = function(a) {
  this.x = this.x + a;
  this.y = this.y + a;
  console.info('Shape moved.',this.x,this.y);
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
  console.log("###### Inside Rectangle.constructor ######");
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(3); // x: 4, y: 5
rect.move(3); // x: 7, y: 8
rect.move(3); // x: 10, y: 11

请注意,this.xthis.y 是持久的。

【讨论】:

    猜你喜欢
    • 2011-12-26
    • 1970-01-01
    • 2014-09-02
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    相关资源
    最近更新 更多