4

说我有这个代码:

function ParentClass()
{
    var anArray = [ ];

    this.addToArray = function(what)
    {
        anArray.push(what);

        console.log(anArray);
    };
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass()
{
    this.addToArray('FirstSubClass');
}

SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;

function SecondSubClass()
{
    this.addToArray('SecondSubClass');
}

当我运行时,new FirstSubClass()我在控制台中看到一个单值数组。当我new SecondSubClass()再次运行时,我看到了一个单值数组。

但是,为什么当我再次运行它们时(即new FirstSubClass(); new SecondSubClass();)然后我看到添加了数组而不是创建了新数组?

这里的理由是我正在创建一个类的实例,因此为什么它们共享相同的私有财产?

我怎样才能避免这种情况,例如,当我这样做时,new FirstSubClass()无论我创建类的新实例多少次,我都会看到一个值数组?

4

5 回答 5

3

请记住,您只为每个子类调用了new ParentClass() 一次。这意味着私有数组变量是这些子类的原型对象的一部分。只有一个原型对象,所以只有一个数组(每个子类)。

每次调用都会new FirstSubClass()生成一个共享相同原型对象的新实例。因此,调用addToArray()将一个元素添加到创建原型对象时创建的同一数组中。

编辑——如果你想要每个实例的数组,你必须做这样的事情:

function ParentClass() {
  this.addToArray = function(value) { this.instanceArray.push(value); };
};

function FirstSubClass() {
  this.instanceArray = [];

  this.addToArray("First");
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;
于 2013-01-06T16:15:20.380 回答
2

首先,JS 中的子类化通常是一个坏主意,因为人们认为他们正在获得扩展,每个实例都有自己的属性和方法副本......

...真的,他们可以public static访问父母的东西。

更好的是,这些public static东西无法访问封装的变量,因此实际上没有对私有数据的操作,除非您使用私有函数(具有公共接口)将数据传递给公共静态数据并从中收集返回值。

var Parent = function () {
    this.static_prop = 0;
    this.static_method = function (num) { this.static_prop += 1; return num + this.static_prop; };
};

var Child = function (num) {
    this.public_func = function () { num = this.static_method(num); };
};

Child.prototype = new Parent();

var child = new Child(13);
child.public_func();

只是调用this.static_method无济于事,因为它对 0 的访问权限为 0 num,这意味着您正在包装您继承的东西以授予他们使用私有数据作为输入的访问权限,这意味着您正在做大部分的写作工作不管继承如何,我都会这样做,因为你的期望.prototype是倒退的。

我可以建议依赖注入吗?
基于组件的程序?

var Iterator = function () {
    var count = 0,
        min = 0,
        max = 0,

        reset = function () { count = min; },
        next = function () { count = count >= max ? min : count; return count += 1; },
        set_min = function (val) { min = val; },
        set_max = function (val) { max = val; },
        public_interface = { reset : reset, count : count, set_min : set_min, set_max : set_max };

    return public_interface;
},


Thing = function (iter) {
    var arr = [],

        currentObj = null,
        nextObj = function () {
            currentObj = arr[iter.next()];
        },
        add = function (obj) {
            arr.push(obj); iter.set_max(arr.length);
        },
        public_interface = { next : nextObj, add : add };

    return public_interface;
};


var thing = Thing(Iterator());
thing.add({});
thing.next();

这是一个令人费解的例子,但现在每个实例都将被准确地提供完成其工作所需的内容(因为构造函数需要它——或者您可以稍后通过公共方法或作为公共属性添加依赖项) .

每个模块的接口现在也可以变得尽可能简单和干净,因为您不必包装意外的静态助手来获取私有数据......

现在您知道什么是私有的,您知道您要向公众扩展什么,并且无论您想将它们放在哪里,您都可以清楚地了解它们。

于 2013-01-06T16:55:41.337 回答
1

您只需为每个子类构建一次 ParentClass 的新实例,并将其应用于您的原型。如果您希望每个实例都有自己的私有数组副本和自己的函数“addToArray”副本,则需要在其他对象构造函数中调用 ParentClass 构造函数:

function ParentClass(){
    var anArray = [ ];

    this.addToArray = function(what){
        anArray.push(what);
        console.log(anArray);
    };
}

FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass(){
    //call the parents constructor where "this" points to your FirstSubClass instance
    ParentClass.call( this );
    this.addToArray('FirstSubClass');
}

SecondSubClass.prototype = new ParentClass();
SecondSubClass.prototype.constructor = SecondSubClass;

function SecondSubClass(){
    ParentClass.call( this );
    this.addToArray('SecondSubClass');
}
于 2013-01-07T15:54:40.973 回答
0

试试这个:

http://jsfiddle.net/3z5AX/2/

function ParentClass()
{
    var anArray = [ ];

    this.addToArray = function(what)
    {
        anArray.push(what);

       document.getElementById("i").value = anArray;
    };
}

//FirstSubClass.prototype = new ParentClass();
FirstSubClass.prototype.constructor = FirstSubClass;

function FirstSubClass()
{  
  this.parent = new ParentClass()
  this.parent.addToArray('FirstSubClass');
}


var q = new FirstSubClass();
var r = new FirstSubClass();
于 2013-01-06T16:29:21.883 回答
0

所有子类共享相同的父类,因此相同的私有 anArray

解决方案是使用 Mixin 模式。

// I have the habbit of starting a mixin with $
var $AddToArray = function(obj) {
    var array = [];

    obj.addToArray = function(what) {
        array.push(what);
        console.log(array);
    };
}

var FirstClass = function() {
    $AddToArray(this);
}

var SecondClass = function() {
    $AddToArray(this);
}
于 2013-01-06T16:32:37.113 回答