2011-09-14 4 views
2

Je rencontre des problèmes pour trouver des informations détaillées sur ce problème. Je voudrais instancier Bar() dans Foo() sans avoir à passer un pointeur vers Foo(). Ou un moyen pour Bar() de savoir que c'est un enfant de Foo(). Est-ce possible? Ou suis-je déjà en train d'utiliser une méthode suffisante?Essayer d'obtenir un objet pour identifier son objet parent sans passer le parent dans l'instance de l'enfant

Fondamentalement, je suis en train d'éviter un appel comme:

var bar1 = new Bar(this,someValue); 

Ci-dessous j'ai un exemple grossier de la méthode que je utilise actuellement.

function Bar(p,val) { 
    var par = p, 
     value = val; 
    this.__defineGetter__("value", function() { 
     return par.dun.value + value; 
    }); 
} 

function Dun(val) { 
    var value = val; 
    this.__defineGetter__("value", function() { 
     return value; 
    }); 
} 

function Foo() { 
    var dun = new Dun(15); 
    var bar1 = new Bar(this, 10); 
    var bar2 = new Bar(this, 20); 
    this.__defineGetter__("dun", function() { 
     return dun; 
    }); 
    this.__defineGetter__("bar1", function() { 
     return bar1; 
    }); 
    this.__defineGetter__("bar2", function() { 
     return bar2; 
    }); 
} 
var myFoo = new Foo(); 
myFoo.bar1.value; 

Merci.

Répondre

2

Non, cela n'est pas possible car il n'y a pas de logique parent/enfant intégrée dans JavaScript. Ce ne sont que des références à des objets.

Mise à jour

oh désolé, je pense que j'ai mal compris votre question. J'ai posé la même question il y a quelque temps: here. Ce que vous essayez de faire, c'est d'obtenir l'objet qui est "ceci" dans la fonction qui a appelé la fonction en cours.

La réponse est: vous ne pouvez pas le faire ...

Mais vous pouvez le faire en utilisant le champ:

function Dun(val) { 
    var value = val; 
    this.__defineGetter__("value", function() { 
     return value; 
    }); 
} 

function Foo() { 
    var dun = new Dun(15); 
    var bar1 = new Bar(10); 
    var bar2 = new Bar(20); 
    this.__defineGetter__("dun", function() { 
     return dun; 
    }); 
    this.__defineGetter__("bar1", function() { 
     return bar1; 
    }); 
    this.__defineGetter__("bar2", function() { 
     return bar2; 
    }); 
    function Bar(val) { 
     this.__defineGetter__("value", function() { 
      return dun.value + val; 
     }); 
    } 
} 
var myFoo = new Foo(); 
myFoo.bar1.value; 

PS: Non lié à votre question, mais bien de savoir: depuis

function(val){} 

est le même que

function(){ 
    var val = arguments[0]; 
} 

vous n'avez pas besoin de créer une nouvelle var et de lui transmettre la valeur des arguments. Vous pouvez utiliser la variable d'argument directement.

+0

Alors, je devrais coller à la façon dont je le fais maintenant? :) – Duncan

+0

Oui, soit, ou vous définissez Bar à l'intérieur de Foo et ensuite utilisez la portée pour y accéder. –

+0

@Duncan, je vous ai montré une autre façon de le faire dans ma nouvelle réponse (dont je ne suis pas sûr est mieux que de simplement passer ceci au constructeur), mais c'est une autre option à regarder. – jfriend00

0

Vous devez donner à l'enfant objet une des opérations suivantes:

  1. Un pointeur direct d'un objet à l'autre, comme dans votre exemple de code.
  2. Informations uniques sur l'objet parent, de sorte qu'il puisse déterminer indirectement ce parent par d'autres moyens. Par exemple, vous pouvez stocker toutes les instances de Foo dans un objet de registre global (un littéral d'objet ou un tableau), que l'objet enfant bar peut rechercher. Il serait à la recherche de l'objet qui a un enfant bar égal à lui-même. De cette façon, le fait qu'il s'agisse d'un enfant de Foo est l'identifiant unique. À moins, bien sûr, qu'un bar peut être partagé sur plusieurs foo s. Alors vous êtes arrosé.:)


1: L'inconvénient est que vous stockez tous les cas de Foo jamais créé, ce qui signifie qu'ils ne seront jamais les ordures collectées: vous serez une fuite de mémoire, qui peut être mauvais si votre environnement reste pendant un certain temps (par exemple une application node.js).

1

Il n'existe aucun moyen de connaître automatiquement le pointeur this de l'appelant d'un new. Donc, si vous voulez savoir ce que cette valeur est sans la passer en tant que partie du constructeur, alors vous devrez définir un état semi-global contenant les informations appropriées. Vous pouvez le faire comme ceci:

function Bar(val) { 
    var par = Bar.parent(), 
     value = val; 
    this.__defineGetter__("value", function() { 
     return par.dun.value + value; 
    }); 
} 

// global methods and state on the Bar function 
Bar.createContext = []; 
Bar.push = function(o) {Bar.createContext.push(o);} 
Bar.pop = function() {Bar.createContext.pop();} 
Bar.parent = function() {return(Bar.createContext[Bar.createContext.length - 1]);} 

function Dun(val) { 
    var value = val; 
    this.__defineGetter__("value", function() { 
     return value; 
    }); 
} 

function Foo() { 
    Bar.push(this);    // set global state 
    var dun = new Dun(15); 
    var bar1 = new Bar(10);  // don't need to pass "this" since it's in the global state 
    var bar2 = new Bar(20); 
    this.__defineGetter__("dun", function() { 
     return dun; 
    }); 
    this.__defineGetter__("bar1", function() { 
     return bar1; 
    }); 
    this.__defineGetter__("bar2", function() { 
     return bar2; 
    }); 
    Bar.pop();     // restore global state 
} 
var myFoo = new Foo(); 
myFoo.bar1.value; 

Et, vous pouvez le voir travailler ici: http://jsfiddle.net/jfriend00/wMgBL/

Questions connexes