2010-07-28 16 views
0

J'utilise l'héritage prototypique et je souhaite avoir des objets avec des tableaux d'instances. Donc, si je dérive des objets d'un objet avec un tableau d'instances et que j'accède au tableau, tous partagent le tableau. Je veux pousser quelque chose au tableau et changer seulement le tableau dans l'objet réel, pas dans tous les autres.Problème avec l'héritage prototypique et le tableau d'instance

Qu'est-ce qu'une solution élégante à ce problème avec l'utilisation de l'héritage prototypique standard et Object.create?

var sys = require('sys'); 

var obj ={ 
    data: [], 
    add: function(what){ 
     this.data.push(what) 
    } 
}; 

var one = Object.create(obj); 
one.add(1); 

var other = Object.create(obj); 
other.add(2); 

sys.puts(other.data.length); // is 2, but should be 1 

Répondre

2
var ObjectName = function(){ 
    this.data = []; 
} 

ObjectName.prototype.add = function(what){ 
    this.data.push(what); 
}; 

var one = new ObjectName(); 
one.add(1); 
+0

Je veux utiliser l'héritage prototypique avec Object.create – Peterfia

+0

Vous pouvez toujours utiliser object.create. Mais vous devez exécuter le constructeur pour initialiser l'objet avec la variable d'instance this.data. var one = Object.create (ObjectName.prototype); ObjectName.call (un); un.add (1); – Marco

1

Il n'y a pas de solution élégante avec Object.create, parce que vous faites mal.

Qu'est-ce que vous voulez est:

function MyArray() { 
    this.data = []; // per-instance data here 
} 

MyArray.prototype = { 
    add: function(what) { // prototype methods here 
     this.data.push(what); 
    } 
}; 

var one = new MyArray; 
one.add(1); 
... 
0

Vous pouvez également remplacer:

add: function(what) { // prototype methods here 
    this.data.push(what); 
} 

avec

add: function(what) { // prototype methods here 
    this.data = this.data.concat(what); 
} 

car cela va créer une nouvelle variable au lieu de le pousser en elle la l'instance du prototype.

0

Object.create peut ajouter des propriétés au nouvel objet, en transmettant un second paramètre avec des descripteurs de propriété.

var sys = require('sys'); 

var obj = { 
    add: function(what){ 
     this.data.push(what) 
    } 
}; 

var one = Object.create(obj, { 
    data: { 
     value: [], 
     writable: true, 
     enumerable: true, 
     configurable: true 
    } 
}); 
one.add(1); 

var other = Object.create(obj, { 
    data: { 
     value: [], 
     writable: true, 
     enumerable: true, 
     configurable: true 
    } 
}); 
other.add(2); 

sys.puts(other.data.length); // should be 1 

Bien sûr, vous voulez mettre cela dans une fonction constructeur pour que vous ne vous répétez pas:

function makeThing() { 
    return Object.create(obj, { 
     data: { 
      value: [], 
      writable: true, 
      enumerable: true, 
      configurable: true 
     } 
    }); 
} 

Bien que, à au point vous écrivez essentiellement un constructeur (avec avantage que vous n'avez pas besoin de l'appeler avec nouveau). En outre, si vous configurez writable, enumerable et configurable à true, vous pouvez simplement définir la propriété de façon normale, ce qui peut être fait en arrière compatible avec ECMAScript 3 en mettant en œuvre une version simple de Object.create:

function makeThing() { 
    var newObj = Object.create(obj); 
    newObj.data = []; 
    return newObj; 
}