0

I have "scene" with graphics "objects"...

Scene.prototype.objects=new Array();

Scene.prototype.add=function(obj){
  var last=this.objects.length;
  this.objects[last]=obj}

Scene.prototype.remove=function(obj){
  this.objects.splice(obj.id,1)}

Scene.prototype.advance=function(){
  for (var id in this.objects){
    var obj=this.objects[id];
    obj.id=id;
    obj.advance();
  }
}
Scene.prototype.paint=function(context){...}

each time creating and deleting many objects. Array.prototype.splice re-index array right? Does anyone know a better technique (adding and removing on javascript Array)?

In my opinion, is another possibility to do that something like

Scene.prototype.remove=function(obj){
  delete this.objects[obj.id]; // don,t care about this.objects.length
  delete obj; // not necessary...
}

I have not tried it yet...

I need a good book about JavaScript :)

Martin Drlík
  • 1,434
  • 1
  • 14
  • 27
  • JavaScript book you'll probably want to read is 'JavaScript: The Good Parts' by Douglas Crockford. It's 150 pages of JS good and bad (yes, there are few these...) parts. – Grzegorz Rożniecki May 27 '11 at 09:19
  • Drlik: Maybe http://javascriptgarden.info/ is useful? – KooiInc May 27 '11 at 09:52
  • Thanks all for reply. I'll use a hash (rather than array, but if delete some_array[index] would work... its seems same). Either way, I'll still have to do sort objects. – Martin Drlík May 27 '11 at 10:35

3 Answers3

2

Your delete method wouldn't work, because objects is an Array, and obj.id is the id of the object reference stored in an element in that Array. splice would be the method to use, but you'll have to know the index of the element in the Array. Maybe you should 'remeber' it this way:

Scene.prototype.add=function(obj){
  var last=this.objects.length;
  obj.objectsIndex = last;
  this.objects[last]=obj
}

After which you can:

Scene.prototype.remove=function(obj){
  this.objects.splice(obj.objectsIndex,1)};
  //reindex the objects within the objects Array
  for (var i=0; i<this.objects.length;i++){
     this.objects[i].objectsIndex = i;
  }
}

Note: Adding the objects Array to the prototype of your Scene constructor means it will be the same for all instances (static), is that what you want?

KooiInc
  • 119,216
  • 31
  • 141
  • 177
  • actually, I do create a scene like this... "function Scene() {this.objects = new Array (); this.views = new Array ();...}" (anyway I have only one scene), but good point... I have no idea about that. – Martin Drlík May 27 '11 at 09:49
  • Well, in that case you don't need (or even want) `Scene.prototype.objects=new Array();` ;~) – KooiInc May 27 '11 at 09:51
  • I consider that the splice re-indexed (and re-size) array... as I see it obj.id has been set to corret array index corresponding to obj instance. – Martin Drlík May 27 '11 at 09:55
  • You're right about that. So you'll have to reindex after every remove. Adjusted my answer to reflect that. – KooiInc May 27 '11 at 10:05
  • It wouldn't work because of the id. It would work with `this.objects[obj.objectsIndex]` (using the `add` method from my answer), but there are reasons to use `splice` for arrays. See for example http://stackoverflow.com/questions/500606/javascript-array-delete-elements – KooiInc May 27 '11 at 10:30
  • I tried var x=Array();x[0]="Text";x[1]="Text2";x[2]="Text3";delete x[0];var y=Array();for (var i in x)y.push(x[i]); alert(y.length);//2 – Martin Drlík May 27 '11 at 11:02
  • Let's say I extended `Array.prototype` with a `prettyPrint` method, an `each` method and a `frequencies` method, what would the length of `Array y` be in that case? – KooiInc May 27 '11 at 11:06
  • Array.prototype.prettyPrint=function(){...};var y=new Array();y.push(1);y.push(2);alert(y.length);//2 – Martin Drlík May 27 '11 at 11:27
  • That's because you're using `Array()` to create an array. Try the same using `var x = ["Text","Text2","Text3"]`. Anyway, I don't know what point you're trying to make, but I don't *forbid* you to use `delete` on array elements. Just pointing you to some known contraindications for using it. – KooiInc May 27 '11 at 11:49
  • I just wanted to point out that even the "delete method" remove an item from the array (although this is not the best solution, but I think it done faster than the splice-Real remove from array). – Martin Drlík May 27 '11 at 12:14
  • In a last effort: what would you predict to be the length of `x` here? `var x = ["Text","Text2","Text3"]; delete x[0]; delete x[1]; delete x[2]; alert(x.length);` – KooiInc May 27 '11 at 12:25
  • 3, so what? I am using "for (var i in array)...", How I wrote in question "delete this.objects[obj.id]; // don,t care about this.objects.length" – Martin Drlík May 27 '11 at 12:40
  • ... ah well, you can always use Resigs method: http://ejohn.org/blog/javascript-array-remove/ – KooiInc May 27 '11 at 13:18
0

I'd rather avoid using new Array() instead use [] (page 114 of book I mentioned in comment - 'JavaScript: The Good Parts' by Douglas Crockford ;)).

What's more, I don't think adding objects array to Scene prototype will work as you expect. You probably want to achieve some Object-Oriented structure, which requires some acrobatic skills in JavaScript, as it uses prototypal inheritance as it is class-free.

Try something like this:

var Scene = function(initial_objects) {
    this.objects = initial_objects || [];
};

Scene.prototype.add = function(obj) {
    this.objects.push(obj);
};

Scene.prototype.remove_by_index = function(index) {
    this.objects.splice(index, 1);
};

Scene.prototype.remove = function(obj) {
    var index = this.objects.indexOf(obj);
    if (index > -1) {
        this.objects.splice(index, 1);
    }
};

Read also this: http://javascript.crockford.com/inheritance.html

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
0

It seems you don't actually need an array for your objects. You can use another object has hash table:

(function() {

    var i = 0;

    Scene.prototype.objects = {};

    Scene.prototype.add = function(obj) {
      var id = i++;
      this.objects[id] = obj;
      obj.id = id;
    };

    Scene.prototype.remove = function(obj){
      if(obj.id in this.objects) {
          delete this.objects[obj.id];
      }
    };

    Scene.prototype.advance=function(){
      for (var id in this.objects){
        var obj=this.objects[id];
        obj.id=id;
        obj.advance();
      }
    };

    Scene.prototype.paint=function(context){...}

}());
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • @Kooilnc: Based on the OP's code I assumed it has not. If it does, then one can use this one instead of course. Just have to make sure that there are no clashes... – Felix Kling May 27 '11 at 11:26