Accedere al genitore del genitore dall’object javascript

Qualcosa di simile a

var life= { users : { guys : function(){ this.SOMETHING.mameAndDestroy(this.girls); }, girls : function(){ this.SOMETHING.kiss(this.boys); }, }, mameAndDestroy : function(group){ }, kiss : function(group){ } }; 

questo è COSA immagino che il formato sia, ma potrebbe non esserlo. Cosa farà risalire al genitore di un object?

JavaScript non offre questa funzionalità in modo nativo. E dubito che potresti persino creare questo tipo di funzionalità. Per esempio:

 var Bobby = {name: "Bobby"}; var Dad = {name: "Dad", children: [ Bobby ]}; var Mom = {name: "Mom", children: [ Bobby ]}; 

A chi appartiene Bobby?

Ho semplicemente aggiunto in prima funzione

 parentThis = this; 

e usare parentThis in sottofunzione. Perché? Perché in JavaScript, gli oggetti sono morbidi. Un nuovo membro può essere aggiunto a un object morbido mediante un semplice assegnamento (non come ad esempio Java dove gli oggetti classici sono difficili. L’unico modo per aggiungere un nuovo membro a un object duro è creare una nuova class) Ulteriori informazioni qui: http : //www.crockford.com/javascript/inheritance.html

E anche alla fine non devi uccidere o distruggere l’object. Perché l’ho trovato qui: http://bytes.com/topic/javascript/answers/152552-javascript-destroy-object

Spero che questo ti aiuti

In questo caso, è ansible utilizzare la life per fare riferimento all’object padre. Oppure puoi memorizzare un riferimento alla life nell’object utente. Non ci può essere un parent fisso a tua disposizione nella lingua, perché gli utenti sono solo un riferimento a un object e potrebbero esserci altri riferimenti …

 var death = { residents : life.users }; life.users.smallFurryCreaturesFromAlphaCentauri = { exist : function() {} }; // death.residents.smallFurryCreaturesFromAlphaCentauri now exists // - because life.users references the same object as death.residents! 

Potresti trovare utile usare qualcosa del genere:

 function addChild(ob, childName, childOb) { ob[childName] = childOb; childOb.parent = ob; } var life= { mameAndDestroy : function(group){ }, kiss : function(group){ } }; addChild(life, 'users', { guys : function(){ this.parent.mameAndDestroy(this.girls); }, girls : function(){ this.parent.kiss(this.boys); }, }); // life.users.parent now exists and points to life 

Se sto leggendo correttamente la tua domanda, gli oggetti in generale sono agnostici su dove sono contenuti. Non sanno chi sono i loro genitori. Per trovare tali informazioni, è necessario analizzare la struttura dei dati padre. Il DOM ha modi per farlo per noi quando parli di oggetti element in un documento, ma sembra che tu stia parlando di oggetti vanilla.

A proposito di chiamata:

Puoi risolvere questo problema usando .call() che:

  • deve essere chiamato su una funzione addName.call()
  • si passa un object di ciò che si desidera essere il “this” addName.call({"name" : 'angela'});
  • puoi passare argomenti addizionali che possono essere usati nella funzione chiamata su addName.call({"name": "angela"}, true); dove forse addName accetta un argomento di append booleano.

Usa chiamata:

Per questo particolare problema, possiamo passare l’object “genitore” attraverso la call per sovrascrivere this normalmente presente nell’object figlio.

Guarda prima il nostro problema

 var app = { init: function() { var _this = this; // so we can access the app object in other functions $('#thingy').click(function(){ alert(_this.options.thingy()); }); $('#another').click(function(){ alert(_this.options.getAnother()); }); }, options: { thingy: function() { // PROBLEM: the this here refers to options return this.getThingy(); }, getAnother: function() { // PROBLEM 2: we want the this here to refer to options, // but thingy will need the parent object return 'another ' + this.thingy(); }, }, getThingy: function() { return 'thingy'; } }; 

Ora, ecco una soluzione per utilizzare la chiamata

E JSFIDDLE per vederlo funzionare.

 var app = { init: function() { var _this = this; // so we can access the app object in other functions $('#thingy').click(function(){ // SOLUTION: use call to pass _this as the 'this' used by thingy alert(_this.options.thingy.call(_this)); }); $('#another').click(function(){ // SOLUTION 2: Use call to pass parent all the way through alert(_this.options.getAnother.call(_this)); }); }, options: { thingy: function() { // SOLUTION in action, the this is the app object, not options. return this.getThingy(); }, getAnother: function() { // SOLUTION 2 in action, we can still access the options // AND pass through the app object to the thingy method. return 'another ' + this.options.thingy.call(this); }, }, getThingy: function() { return 'thingy'; } }; 

In conclusione

Puoi usare .call() ogni volta che usi un metodo su una proprietà dell’object principale: app.options.someFunction(arg) dovrebbe sempre essere chiamato con .callapp.options.someFunction.call(this, arg); – in questo modo puoi assicurarti di avere sempre accesso a ogni parte dell’object. Potrebbe darti accesso ai metodi di un’altra proprietà come app.helpers.anotherFunction() .

Una buona idea è nella somefunction , memorizzarla in una variabile _parentThis è ovvio che cosa riflette this .

Ecco qui:

 var life={ users:{ guys:function(){ life.mameAndDestroy(life.users.girls); }, girls:function(){ life.kiss(life.users.guys); } }, mameAndDestroy : function(group){ alert("mameAndDestroy"); group(); }, kiss : function(group){ alert("kiss"); //could call group() here, but would result in infinite loop } }; life.users.guys(); life.users.girls(); 

Inoltre, assicurati di non avere una virgola dopo la definizione “ragazze”. Ciò causerà l’arresto anomalo dello script in IE (ogni volta che si dispone di una virgola dopo l’ultimo elemento in un array in Internet Explorer muore).

Guardalo correre

Ho usato qualcosa che assomiglia a un modello singleton:

 function myclass() = { var instance = this; this.Days = function() { var days = ["Piątek", "Sobota", "Niedziela"]; return days; } this.EventTime = function(day, hours, minutes) { this.Day = instance.Days()[day]; this.Hours = hours; this.minutes = minutes; this.TotalMinutes = day*24*60 + 60*hours + minutes; } } 

Come altri hanno già detto, non è ansible cercare direttamente un genitore da un bambino annidato. Tutte le soluzioni proposte consigliano vari modi di riferirsi all’object genitore o all’ambito genitore attraverso un nome di variabile esplicito.

Tuttavia, è ansible attraversare direttamente fino all’object padre se si utilizzano proxy ES6 ricorsivi sull’object padre.

Ho scritto una libreria chiamata ObservableSlim che, tra le altre cose, ti permette di attraversare da un object figlio al genitore.

Ecco un semplice esempio ( demo di jsFiddle ):

 var test = {"hello":{"foo":{"bar":"world"}}}; var proxy = ObservableSlim.create(test, true, function() { return false }); function traverseUp(childObj) { console.log(JSON.stringify(childObj.__getParent())); // returns test.hello: {"foo":{"bar":"world"}} console.log(childObj.__getParent(2)); // attempts to traverse up two levels, returns undefined because test.hello does not have a parent object }; traverseUp(proxy.hello.foo); 

Ho fatto qualcosa di simile e funziona come un fascino.

Semplice.

PS C’è di più l’object ma ho appena postato la parte pertinente.

 var exScript = (function (undefined) { function exScript() { this.logInfo = []; var that = this; this.logInfo.push = function(e) { that.logInfo[that.logInfo.length] = e; console.log(e); }; } })(); 

Con il seguente codice è ansible accedere al genitore dell’object:

 var Users = function(parent) { this.parent = parent; }; Users.prototype.guys = function(){ this.parent.nameAndDestroy(['test-name-and-destroy']); }; Users.prototype.girls = function(){ this.parent.kiss(['test-kiss']); }; var list = { users : function() { return new Users(this); }, nameAndDestroy : function(group){ console.log(group); }, kiss : function(group){ console.log(group); } }; list.users().guys(); // should output ["test-name-and-destroy"] list.users().girls(); // should output ["test-kiss"] 

Ti consiglierei di leggere sugli oggetti javascript per sapere come puoi lavorare con gli oggetti, mi ha aiutato molto. Ho persino scoperto delle funzioni che non sapevo nemmeno fossero esistite.

Se vuoi ottenere la chiave di tutti i genitori di un nodo in un object letterale ( {} ), puoi farlo:

 (function ($) { "use strict"; $.defineProperties($, { parentKeys: { value: function (object) { var traces = [], queue = [{trace: [], node: object}], block = function () { var node, nodeKeys, trace; // clean the queue queue = []; return function (map) { node = map.node; nodeKeys = Object.keys(node); nodeKeys.forEach(function (nodeKey) { if (typeof node[nodeKey] == "object") { trace = map.trace.concat(nodeKey); // put on queue queue.push({trace: trace, node: node[nodeKey]}); // traces.unshift(trace); traces.push(trace); } }); }; }; while(true) { if (queue.length) { queue.forEach(block()); } else { break; } } return traces; }, writable: true } }); })(Object); 

Questo algoritmo utilizza il concetto FIFO per iterare i grafici usando il metodo BFS . Questo codice estende la class Object aggiungendo il metodo statico parentKeys che si aspetta un literal Object (tabella hash – array associativo …) del Javacript, come parametro.

Spero di aver aiutato.