Javascript原型:替换与添加

时间:2014-04-13 17:58:14

标签: javascript prototypal-inheritance

我正在使用一个相当简单的Point2D数据结构,我构建为可以继承,比如未来的Point3D,我已经按照我能找到的所有指南和类似问题,但似乎没有任何帮助我的问题。

我已经将Point2D定义如下:

function Point2D (px, py)
{
  this.x = px;
  this.y = py;

  Point2D.prototype =
  {
    constructor: Point2D,

    move:function (mx, my)
    {
      this.x = mx;
      this.y = my;
    },
    translate:function (dx, dy)
    {
      this.x += dx;
      this.y += dy;
    }
  };
};

我按如下方式实例化对象:

var p2d1 = new Point2D(2,3);

然后我调用以下方法之一:

p2d1.move(1,2);

结果是:

TypeError: Object #<Point2D> has no method 'move'

我不知道为什么我的方法无法解决。

我已经搞砸了一段时间,发现我可以用这种方式声明Point2D方法并且它们可以工作。

Point2D.prototype.move = function () {};

任何人都可以解释为什么他们第一次更换整个原型的样式工作,但添加现有原型的功能有效吗?

3 个答案:

答案 0 :(得分:2)

第一次致电new Point()时,Point.prototype仍是“空”原型。即创建的实例不会继承任何方法。

在实例已创建之后,您更改(替换)原型。 JavaScript按值分配,不按引用分配。快速举例:

var a = 5;
var b = {c: a};
a = 10;

b.c仍为5,因为分配到a并未更改b.c所指的内容。

Point2D.prototype.move = function () {};

有效,因为您替换Point2D.prototype,您只是在改变现有对象。

总体而言,*.prototype的分配应在外部构造函数中进行:

function Point2D (px, py) {
  this.x = px;
  this.y = py;
};

Point2D.prototype = { };

答案 1 :(得分:1)

我不确定,但在“类”声明中定义原型是不寻常的,对我来说,很难确切地定义如何解决问题。在进行手动继承时,我倾向于遵循更多这些模式:

function Foo() {
   this.bar = ...
}

Foo.prototype.baz = function() { ... }

OR

function Foo() { ... }
function Bar() { ... }

Foo.prototype = new Bar();

OR

Foo.prototype = {
    blah: ...
}

此外,我通常不会手动创建“构造函数”属性,因为这是设置原型的副作用,但我知道一些流行的库会这样做。在上面的中间例子中,Foo.prototype.constructor == Bar。

答案 2 :(得分:0)

如果你真的想要扭曲你的大脑,请创建Point2D的第二个实例并观察它是否有可用的移动方法!

所以这就是正在发生的事情。

define Point2D class
create instance of Point2D class
  create initialization object
  create execution context object per new keyword usage
  attach prototype to execution context (at this point just Object)
  run constructor method
    assign value of x
    assign value of y
    assign new prototype value to Point2D class

您要做的是将原型设置移动到与类定义相同的范围。