web-dev-qa-db-fra.com

Accéder au parent de l'objet javascript du parent

Quelque chose comme

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

this.SOMETHING est ce que j’imagine que le format est, mais ce n’est peut-être pas Qu'est-ce qui va revenir au parent d'un objet?

50
Robert

JavaScript n'offre pas cette fonctionnalité de manière native. Et je doute que vous puissiez même créer ce type de fonctionnalité. Par exemple:

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

À qui appartient Bobby?

38
harley.333

J'ai simplement ajouté en première fonction 

parentThis = this;

et utilisez parentThis dans la sous-fonction. Pourquoi? Parce qu'en JavaScript, les objets sont mous. Un nouveau membre peut être ajouté à un objet logiciel par simple affectation (pas comme ie. Java où les objets classiques sont durs. La seule façon d'ajouter un nouveau membre à un objet dur est de créer une nouvelle classe) Plus d'informations à ce sujet ici: http://www.crockford.com/javascript/inheritance.html

Et aussi à la fin, vous n'avez pas à tuer ou à détruire l'objet. Pourquoi j'ai trouvé ici: http://bytes.com/topic/javascript/answers/152552-javascript-destroy-object

J'espère que cela t'aides

55
jazkat

Dans ce cas, vous pouvez utiliser life pour référencer l'objet parent. Ou vous pouvez stocker une référence à life dans l'objet utilisateurs. Il ne peut pas y avoir de parent fixe disponible dans la langue, car les utilisateurs sont simplement une référence à un objet, et il pourrait y avoir d'autres références ...

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!

Vous trouverez peut-être utile d'utiliser quelque chose comme ceci:

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
19
Shog9

Si je lis bien votre question, les objets en général sont agnostiques quant à leur emplacement. Ils ne savent pas qui sont leurs parents. Pour trouver cette information, vous devez analyser la structure de données parent. Le DOM a les moyens de le faire pour nous lorsque vous parlez d'objet élément dans un document, mais il semble que vous parlez d'objet Vanilla.

4
Adam Bellaire

A propos de Call:

Vous pouvez en quelque sorte résoudre ce problème en utilisant .call() qui:

  • doit être appelé sur une fonction addName.call()
  • vous passez un objet de ce que vous voulez être le "this" addName.call({"name" : 'angela'});
  • vous pouvez passer des arguments supplémentaires pouvant être utilisés dans la fonction sur laquelle il est appelé addName.call({"name": "angela"}, true);, où peut-être que addName accepte un argument de boolean append.

Utiliser appel:

Pour ce problème particulier, nous pouvons passer l'objet "parent" via call pour remplacer le this normalement présent dans l'objet enfant.

Regarde d'abord notre problème

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';
    }
};

Maintenant, voici un appel d'utilisation de solution

Et JSFIDDLE pour le voir fonctionner.

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';
    }
};

En conclusion

Vous pouvez utiliser .call() chaque fois que vous utilisez une méthode sur une propriété de votre objet principal: app.options.someFunction(arg) doit toujours être appelé avec .call - app.options.someFunction.call(this, arg); - de cette manière, vous pourrez ainsi avoir toujours accès à toutes les parties de l'objet. Cela pourrait vous donner accès aux méthodes d'une autre propriété comme app.helpers.anotherFunction().

Une bonne idée est dans la somefunction, stocker this dans une variable _parentThis, il est donc évident que la this reflète.

4
amurrell

Voici:

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();

Assurez-vous également que vous n’avez pas de virgule après la définition des "filles". Cela provoquera un blocage du script dans IE (chaque fois que vous avez une virgule après le dernier élément d'un tableau dans IE, il meurt).

Voir le courir

3
cmcculloh

J'ai utilisé quelque chose qui ressemble à un motif 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;
    }
}
1
Parchandri

Comme d'autres l'ont déjà dit, il n'est pas possible de rechercher directement un parent à partir d'un enfant imbriqué. Toutes les solutions proposées conseillent différentes manières de renvoyer à l'objet parent ou à la portée parent via un nom de variable explicite.

Toutefois, le passage direct à l’objet parent est possible si vous utilisez des méthodes ES6 Proxies récursives sur l’objet parent.

J'ai écrit une bibliothèque appelée ObservableSlim qui, entre autres choses, vous permet de remonter d'un objet enfant au parent. 

Voici un exemple simple ( démo 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);
1
Elliot B.

J'ai fait quelque chose comme ça et ça marche à merveille.

Simple.

P.S. Il n'y a plus l'objet mais je viens de poster la partie 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);
        };
    }
})();
0
transilvlad

Si vous voulez obtenir toutes les clés parents d'un nœud dans un objet littéral ({}), vous pouvez le faire:

(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);

Cet algorithme utilise le concept FIFO pour itérer les graphiques à l'aide de la méthode BFS. Ce code étend la classe Object en ajoutant la méthode statique parentKeys qui attend un literal Object (table de hachage - tableau associatif ...) du javacript, en tant que paramètre.

J'espère avoir aidé.

0
rplaurindo

Avec le code suivant, vous pouvez accéder au parent de l'objet:

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"]

Je vous recommanderais de lire sur javascript Objects pour savoir comment vous pouvez travailler avec Objects, cela m'a beaucoup aidé. J'ai même découvert des fonctions dont je ne savais même pas qu'elles existaient.

0
Rodrigo Morales