JS中的类继承和私有变量

时间:2013-01-06 16:12:43

标签: javascript oop prototypal-inheritance

说我有这段代码:

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 实例,因此为什么它们共享相同的私有属性?

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

5 个答案:

答案 0 :(得分: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;

答案 1 :(得分:1)

首先,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无济于事,因为它可以访问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();

这是一个令人费解的例子,但是现在每个实例都会得到它完成工作所需的内容(因为构造函数需要它 - 或者您可以稍后通过公共方法或公共方式添加依赖项) - 特性)。

每个模块的接口现在也可以像你想的那样简单和干净,因为你不必包装意外的静态助手来获取私有数据......

现在你知道什么是私人的,你知道你在向公众宣传什么,而且无论你想把它们放在哪里都可以得到干净的信息。

答案 2 :(得分: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');
}

答案 3 :(得分: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();

答案 4 :(得分: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);
}