简体   繁体   English

JS中的类继承和私有变量

[英]Class inheritance and private variables in JS

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. 当我运行new FirstSubClass()我在控制台中看到一个值数组。 And when I run new SecondSubClass() , again, I see a single value array. 当我再次运行new SecondSubClass()时,我看到一个单值数组。

However, why is it when I run them again (ie new FirstSubClass(); new SecondSubClass(); ) I then see the arrays added to rather than new ones being created? 但是,为什么我再次运行它们(即new FirstSubClass(); new SecondSubClass(); )然后我看到添加的数组而不是新的数组?

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 eg, new FirstSubClass() I then see a single value array no matter how many times I create a new instance of the class? 我怎么能避免这种情况,所以当我这样做时,例如, new FirstSubClass()然后我看到一个单独的值数组,无论我创建一个新的类实例多少次?

Keep in mind that you've only called new ParentClass() once for each subclass. 请记住,您只为每个子类调用了一次 new ParentClass() 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. 每次调用new FirstSubClass()生成一个共享相同原型对象的新实例。 The call to addToArray() therefore adds an element to that same array that was created when the prototype object was created. 因此,对addToArray()的调用会向创建原型对象时创建的同一个数组添加一个元素。

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

...really, they're getting public static access to the parent's stuff. ......实际上,他们正在获得对父母的东西的public static访问。

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. 更好的是, 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();

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. 只是调用this.static_method无济于事,因为它可以访问num ,这意味着你要包装你继承的东西以授予他们使用私有数据作为输入的权限,这意味着你正在做大部分工作无论如何,你要做的写作,无论继承,因为你对.prototype的期望是倒退的。

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. 您只是为每个子类构造一个ParentClass的新实例,并将其应用于您的原型。 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: 如果您希望每个实例都拥有自己的私有数组副本及其自己的函数“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');
}

try this: 试试这个:

http://jsfiddle.net/3z5AX/2/ 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();

All Subclasses share the same parent class, thus the same private anArray 所有子类共享相同的父类,因此相同的私有anArray

The solution is to use the Mixin pattern. 解决方案是使用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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM