创建同一个类的对象:Javascript原型,私有成员,继承

时间:2010-02-17 04:02:46

标签: javascript oop inheritance private-members value-objects

有些代码可能会说超过一千个字:

/**
 * Represents an amount of a resource
 * @param {number} amount
 * @param {string} type
 */
function Resource(amount, type) 
{
    var nAmount = amount;
    var sType = type;

    if (amount < 0) 
    {
        throw new IllegalArgumentException("amount has to be positive");
    }

    /**
     * @method Resource
     * @return {number} amount of the resource
     */
    this.getAmount = function() 
    {
        return nAmount;
    };

    /**
     * @method Resource
     * @return {string} resource type
     */
    this.getType = function() 
    {
        return sType;
    };
}

/**
 * Addition of two resources produces a new resource with the sum amount
 * the new object uses the old one as prototype
 * @param {Resource} resource
 * @return {Resource} new Resource object
 */
Resource.prototype.plus = function(resource) 
{
    if (!(resource instanceof Resource && this.getType() == resource.getType())) 
    {
        throw new IllegalArgumentException("resources don't match.");
    }

    var newRes = Object.create(this); // create a new object based on the current one
    // execute the Resource constructor on it
    Resource.call(newRes, this.getAmount() + resource.getAmount(), this.getType());
    return newRes;
};

资源对象是被认为是不可变的ValueObject。它们在添加操作上返回一个新对象。现在,我不是只调用“new Resource(args)”来创建要返回的新对象,而是根据旧对象创建了一个新对象。这也允许继承。

当我开始在我的所有ValueObjects上使用它时(以防万一我想在将来的某个时候继承它们),我开始考虑这个了。

JavaScript不允许不可变对象。然而,对象易受直接方法覆盖或调用其构造函数的攻击。我所能做的就是决定这些都是坏习惯。不幸的是ECMAScript5“冻结”还没有在这里,虽然我的模式与它兼容。

现在我有一个在不可变对象上调用构造函数的“坏样式”以及这个代码重复,我正在考虑创建一个新函数来封装这个过程:

Object.recreate = function(proto, constructor, args) 
{
    var obj = Object.create(proto);
    constructor.apply(obj, args);
    return obj;
};

因此:

Resource.prototype.plus = function(resource) 
{
    // if ... {throw ...}
    return Object.recreate(this, Resource, 
            [this.getAmount() + resource.getAmount(), this.getType()]);
};

也许有人对这个功能的名称有更好的了解。 '重新创造'是我的第一个想法。您如何看待这种模式?这是一种过度抽象吗?我应该为课程保存这个,我相信我会继承吗?我错过了什么重要的事吗?

编辑:我看到我忘了提到一些重要内容,这些内容在本文中没有反映出来。使用Object.create可以轻松克隆ValueObject。他们的私人成员是不可改变的。但是可变的私人会员呢?如果在克隆上调用set(),它会在闭包中设置原始原型对象!当我的Object.recreate重新创建闭包时,这个问题就解决了。

那么使用私有变量进行继承是否有更好的方法?为什么每个人都用糖来创造课堂?我已经阅读了很多关于原型主义的内容,我仍然没有掌握它。

2 个答案:

答案 0 :(得分:0)

我认为复制或克隆会是一个更好的名称。这个article解释了创建这种通用函数的机制。

答案 1 :(得分:0)

多年后回到这一点,我可以说我编写的代码在混合概念方面存在缺陷。 JavaScript实际上可以通过闭包提供真正的私有变量。但是,由于ValueObjects无论如何都是不可变的,因此无法更改私有状态,并且它会使事情过于复杂以隐藏它。

此外,巧妙的Object.recreate是一种过度抽象的“工厂方法”,如果需要,应该为每个类分别声明。

使用合成而不是继承! Crockford提供了很好的JavaScript见解:https://crockford.com/javascript/prototypal.html