Search code examples
javascriptclassloaderprototypal-inheritancestatic-variables

Creating different instance of the same prototype in Javascript


I'd like to create 2 different "instances" of the same prototype in Javascript. Please note that the word "instances" here does not refer to "instantiated classes" but 2 distinct class instances (one specific class that has been loaded from 2 different class loaders in Java terms for example).

Assuming I have this object:

var protoObj = {
  prop: "",
  method: function () {
    // do stuffz
  }
}

protoObj.method.staticProperty = 0;

function childObj (prop)  {
  this.prop = prop;
}
childObj.prototype = protoObj;

var child1 = new childObj("First Child");
var child2 = new childObj("Second Child");

console.log("Prop:", child1.prop); //prints "Prop: First Child"
console.log("Prop:", child2.prop); //prints "Prop1: Second Child"

child1.method.staticProperty = 1;
child2.method.staticProperty = 2;

console.log("Child1 Static:", child1.method.staticProperty); //prints "Child1 Static: 2" <-- I wanted this to be 1. I want each instance to have its own "parent"
console.log("Child2 Static:", child2.method.staticProperty); //prints "Child2 Static: 2"

My goal is for child1.method.staticProperty to have a different value from child2.method.staticProperty

You might ask why this is needed? Storing state in function properties is wrong indeed, but the code above comes from the Typescript compiler which compiles "Class Statics" as properties of JavaScript constructor functions. What I need is to have different static values for the same class name.

Note that in my case the protoObj is essentially a javascript applicationApi (a 20K line file) and our goal is to be able to create 2 distinct instances of he application while loading the library only once.


Solution

  • My goal is for child1.method.staticProperty to have a different value from child2.method.staticProperty

    That is only possible when the two methods are distinct, so there are two prototype objects that your objects inherit from - which is not possible without creating two protoObjs or cloning it, which you said you don't want to.

    Note that in my case the protoObj is essentially a javascript applicationApi (a 20K line file) and our goal is to be able to create 2 distinct instances of he application

    Include the script file twice to execute it twice and create two distinct objects:

    <script type="text/javascript" src="applicationApi.js"></script>
    <script type="text/javascript">
        console.assert(childObj.prototype == protoObj);
        var firstInstance = childObj;
        protoObj.method.staticProperty = 1;
    </script>
    <script type="text/javascript" src="applicationApi.js"></script>
    <script type="text/javascript">
        console.assert(childObj.prototype == protoObj);
        var secondInstance = childObj;
        protoObj.method.staticProperty = 2;
    </script>
    <script type="text/javascript">
        console.log(new firstInstance);
        console.log(new secondInstance);
        console.log(firstInstance !== secondInstance);
    </script>
    

    Notice however that the need to do this suggests a fault in the design of the api library.

    …while loading the library only once.

    Just send the appropriate caching headers and it'll be done implicitly.