2

I'm currently working on some code based on John Resig -Simple JavaScript Inheritance. And i'm having some trouble with the initialization of arrays. If i put an array as an attribute for an object and don't initialize the array during the call of init(), all the modification made to the array like push, unshift will affect further creations of objects. As i dunno if i'm clear enough, here is an example:

<html>
  <head>
    <script type="text/javascript">
    /*
    insert all the John Resig code here
     */

    var Person = Class.extend({
      arrayTest:[],

      init: function(){
      },
      arrayModif: function(){
        this.arrayTest.push(4);
 this.arrayTest.push(2);
      }
    });

    function example(){
      var a=new Person();
      document.write("This is a before any modifications:"+a.arrayTest+"<br/>");
      a.arrayModif();
      document.write("This is a after modifications:"+a.arrayTest+"<br/>");
      var b=new Person();
      document.write("This is b after creation:"+b.arrayTest+"<br/>");
    };
   </script>
  </head>
  <body onload="example();">
  </body>
 </html>

And it will have the following output:

This is a before any modifications:
This is a after modifications:4,2
This is b after creation:4,2

I was wondering if someone had any idea of how to modify John Resig code to achieve the following output, without putting something in init():

This is a before any modifications:
This is a after modifications:4,2
This is b after creation:

Thanks.

4 Answers 4

2

I use a small addition that checks for arrays in the class (not in sub-objects of that class!), and copies those arrays on initialization to get a local copy instead of one in the prototype only.

var _arrays = [];
// Copy the properties over onto the new prototype
for (var name in prop) {
  // ... Existing code ...

  if (prototype[name] instanceof Array) {
    _arrays.push(name);
  }
}

// The dummy class constructor
function Class() {
  // All construction is actually done in the init method
  if ( !initializing ) {
    for (var i = 0; i < _arrays.length; i++) {
      this[_arrays[i]] = this[_arrays[i]].slice(0);
    }
    if ( this.init ) {
      this.init.apply(this, arguments);
    }
  }
}
Sign up to request clarification or add additional context in comments.

5 Comments

What do you mean exactly by sub-objects? Any object of a class that inherits that class?
@Py: An example: Class.extend({a: [], b: {c: []}}): it will find the array a, but not b.c. I could not find a better description for it.
I get it. And as far as I can say, your solution works just fine :)
As a side question, do you know a way to do the same with objects? That seems a bit harder to me (mostly because using [] instanceof Object is true as well).
@Py: Indeed, objects are tricky (functions are objects too etc.), so I did not try to convert them too.
2

Combining what x4u and Crescent Fresh said, it looks like you want:

var Person = Class.extend({ 

   init: function(){ 
      this.arrayTest = [];
   },
   arrayModif: function(){
      this.arrayTest.push(4);
      this.arrayTest.push(2);
  }
});

2 Comments

Yes, that was what I actually meant. ;)
Yeah but i wrote: without putting something in init(). I knew that putting the this.arrayTest=[] in the initialization works, i was just wondering if somehow, it could be achieved without adding something to the init(), and only changing something in John Resig code.
0

I haven't used John Resig's code yet but I'd try to set the initial value of variables in the constructor:

var Person = Class.extend({ 
  arrayTest:[], 

  init: function(){ 
      arrayTest = [];
  }, 

1 Comment

this.arrayTest = []. It's not needed at all on the prototype.
0

The same issue. I made this test:

MyClass = Class.extend({
    obj:[],
    addObj: function(obj)
    {
        this.obj[ this.obj.length ] = obj;
    }
});

instance = new MyClass();
alert(instance.obj);    // ok: empty
instance.addObj(123);
alert(instance.obj);    // ok: alerts 123

instance2 = new MyClass();  // instance 2, empty array is expected
alert(instance2.obj);   // error: alerts 123, must be empty

instance.addObj(456);
alert(instance2.obj);   // error: alerts 123,456, must be empty

Possible solution (add fix to Resig's code, here is an idea): if there are arrays in the "class", you can replace user's init() function with another function that will initialize arrays automatically and than call user's init().

Or you can manually initialize arrays in init() function, this solution is faster (but not safe).

MyClass = Class.extend({
    obj:[],
    addObj: function(obj)
    {
        this.obj[ this.obj.length ] = obj;
    }
    init: function()
    {
        this.obj = [];
    }
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.