3

[已编辑:并不是很好的例子vector2dvector3d我现在使用ptandptMass代替。]

我一直在为此寻找答案,但似乎没有好的解决方案。

假设我有一个对象如下。

function pt(x,y){
    this.x = x;
    this.y = y;
}

现在,我想要一个点质量,如下所示。

function ptMass(x,y,m){
    this.x = x;
    this.y = y;
    this.m = m;
}

最好使用继承来创建ptMass类。

我目前正在使用以下方式来做到这一点。

function ptMass(x,y,m){
    pt.apply(this.arguments);
    this.m = m;
}

有没有办法做到这一点prototype 我尝试了以下方法,但它不起作用。

pt = function(m){this.m = m};
ptMass.prototype = new pt();

还有一个问题,使用原型继承有何进步?

4

2 回答 2

3

首先,为什么继承更好?
尽管我自己更喜欢组合(模块/组件和依赖注入),但我得到了几个继承参数。

其次,您可以通过以下方式重用:

function Vector2D (x, y) {
    this.x = x;
    this.y = y;
}


function Vector3D (x, y, z) {
    Vector2D.call(this, x, y);
    this.z = z;
}

第三,在大型 JS 应用程序中,创建数万(或数百万)个多边形,额外的函数调用只会不必要地减慢它的速度。

四、不能用

Vector3D.prototype = new Vector2D();

首先,您没有初始化Vector2D 内部的任何内容x。 其次,如果您来自其他语言,则意味着保存STATIC属性和函数。y
prototype

即使您进行了初始化Vector2D,对于您的 Vector3D 类的每个实例,它仍然是完全相同的 Vector2D

为什么不只是:

var point2D = function (x, y) {
        return { x : x,
                 y : y  };
    },
    point3D = function (x, y, z) {
        return { x : x,
                 y : y,
                 z : z };
    };

...当你有那些特定的构建块作为你的基本元素时,组成使用它们的不同模块?


编辑

function anObj (x, y) {
    var privateFunc = function () { return y; };

    return {
        x : x,
        method : function () { return privateFunc(); }
    };
}


var myObj = anObj(1, 2);
myObj.x;        // 1
myObj.method(); // 2

这里的好处是你现在有了私有变量(privateFuncy)。
缺点是在内存使用方面,对象的每个实例都需要拥有任何私有方法的OWN副本。
因此,如果您正在制作数十万个这样的对象(例如顶点/多边形),并且它们不需要具有私有状态,那么这不是使用的方法。

但是,如果您正在制作玩家或敌人、控制器或任何您不想被篡改的东西,那么您确实想要使用这样的方法(或更高级)。

如果您可能需要100% 私有的STATIC数据/方法,那么您应该尝试如下格式:

var objectMaker = (function () {
    var staticData = 32,
        staticFunc = function (num) { return num + staticData; };

    return function (x, y) {
        var privateData = 12,
            privateMethod = function (num) {
                return y + privateData + staticFunc(num);
            };

        return { x : x,
                 method : function (num) { return privateMethod(num); }
        };
    };
}());


var myObj = objectMaker(3, 4);
myObj.x;          // 3;
myObj.method(12); // 12 + y(y === 4) + privateData + staticData;

所以我们在这里所做的是我们有一个立即触发的函数(它在定义后立即触发,并将函数的返回给变量)。
所以在我们的特殊情况下,这个函数会立即返回我们想要用来创建新实例的实际函数。

立即函数内部的私有变量和函数(不是我们返回的构造函数)是静态的,因为您创建的每个实例都可以访问该闭包内完全相同的函数/数据。
缺点是这些静态函数无法访问私有(甚至是特定于实例的)数据。
这意味着您必须将值传递给静态函数,并捕获静态函数的返回,因为您不能依赖静态方法来修改实例值(从技术上讲,您可以直接修改对象/数组,如果您将它们传递给函数,否则您必须捕获返回值)。

现在您可以拥有大量在实例之间共享的辅助函数(较低的内存),同时仍然是私有和安全的。

如果您想要的是公共属性、公共方法和静态方法/属性,那么您可以像这样访问它们:

var Obj = function (x, y) {
    this.x = x;
    this.per_instance_method = function () { return y; };
};

Obj.prototype.staticData = { z : 32 };
Obj.prototype.staticMethod = function () { return this.x + this.staticData.z; };

var myObj = new Obj(3, 4);
myObj.staticMethod();

...只是不要期望任何原型方法可以访问任何实例的私有数据(如y)。

于 2012-11-29T15:54:27.463 回答
1

不,您的第一个几乎是正确的:

function vector3d(x,y,z){
    vector2d.apply(this, arguments);
    // you might also use vector2d.apply(this, [].slice.call(arguments, 0,2));
    // or simpler vector2d.call(this, x, y);
    this.z=z;
}

所以是的,你必须从构造函数中调用它。调用它一次以创建原型对象将正确设置继承,但会创建一个实例vector2D- 您既不需要也不想要它。甚至可能造成伤害。查看有关[不]使用“新”关键字[用于继承]的原因是什么的详细答案.

有没有办法用原型做到这一点?

vector3d.prototype = Object.create(vector2d.prototype);

将使所有实例vector3都从中继承的原型对象继承自 的原型对象vector2d。我不确定您是否需要,通常的二维方法都不适用于三维向量。

使用原型继承有何进步?

于 2012-11-29T15:56:27.950 回答