最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Class inheritance and private variables in JS - Stack Overflow

programmeradmin5浏览0评论

Say I have this code:

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');
}

When I run new FirstSubClass() I see a single value array in the console. And when I run new SecondSubClass(), again, I see a single value array.

However, why is it when I run them again (i.e. new FirstSubClass(); new SecondSubClass();) I then see the arrays added to rather than new ones being created?

The rationale here is that I'm creating new instances of a class, therefore why are they sharing the same private property?

How can I avoid this so when I do, for e.g., new FirstSubClass() I then see a single value array no matter how many times I create a new instance of the class?

Say I have this code:

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');
}

When I run new FirstSubClass() I see a single value array in the console. And when I run new SecondSubClass(), again, I see a single value array.

However, why is it when I run them again (i.e. new FirstSubClass(); new SecondSubClass();) I then see the arrays added to rather than new ones being created?

The rationale here is that I'm creating new instances of a class, therefore why are they sharing the same private property?

How can I avoid this so when I do, for e.g., new FirstSubClass() I then see a single value array no matter how many times I create a new instance of the class?

Share Improve this question asked Jan 6, 2013 at 16:12 Ahmed NuamanAhmed Nuaman 13.3k16 gold badges56 silver badges88 bronze badges
Add a ment  | 

5 Answers 5

Reset to default 3

Keep in mind that you've only called new ParentClass() once for each subclass. That means that the private array variable is part of the prototype object for those subclasses. There's only one prototype object, so there's only one array (per subclass).

Each call to new FirstSubClass() generates a new instance that shares the same prototype object. The call to addToArray() therefore adds an element to that same array that was created when the prototype object was created.

edit — if you want per-instance arrays, you'd have to do something like this:

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;

First, sub-classing in JS is typically a bad idea, because people think that they're getting extension, where every instance has its own copy of properties and methods...

...really, they're getting public static access to the parent's stuff.

Even better, that public static stuff has no access to the encapsulated variables, so there's really no manipulation of private data, unless you're using private functions (with a public interface) to pass data to and collect return values from, the public static stuff.

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();

Just calling this.static_method wouldn't help, because it would have 0 access to num, which means that you're wrapping things which you inherited to grant them access to use private data as inputs, which means that you're doing most of the writing you'd be doing anyway, regardless of inheritance, because your expectations of .prototype were backwards.

Might I suggest Dependency Injection, instead?
Component-based programs?

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();

It's a convoluted example, but now every instance is going to be given exactly what it needs to do its job (because the constructor requires it -- or you can add the dependency later, through a public method, or as a public-property).

The interfaces for each module can now also get as simple and as clean as you'd like, as you don't have to wrap unexpected static-helpers to get private data...

Now you know what's private, you know what you're extending to the public, and you have clean ins and outs wherever you want to put them.

You are only constructing a new instance of ParentClass once per subclass and that is to apply it to your prototype. If you want each instance to have its own copy of the private array and its own copy of the function "addToArray" you will need to invoke the ParentClass constructor function within your other objects constructors:

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');
}

try this:

http://jsfiddle/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();

All Subclasses share the same parent class, thus the same private anArray

The solution is to use the Mixin pattern.

// 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);
}
发布评论

评论列表(0)

  1. 暂无评论