webentwicklung-frage-antwort-db.com.de

Greifen Sie über ein JavaScript-Objekt auf das übergeordnete Elternteil zu

So etwas wie

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

this.OMETHING ist, wie ich mir das Format vorstelle, aber es kann nicht sein. Was wird zurück zum übergeordneten Objekt eines Objekts?

50
Robert

JavaScript bietet diese Funktionalität nicht nativ. Und ich bezweifle, dass Sie diese Art von Funktionalität sogar erstellen könnten. Zum Beispiel:

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

Wem gehört Bobby?

38
harley.333

Ich habe einfach in der ersten Funktion hinzugefügt 

parentThis = this;

und verwenden Sie parentThis in der Unterfunktion. Warum? In JavaScript sind Objekte weich. Ein neues Mitglied kann durch einfache Zuweisung zu einem Soft-Objekt hinzugefügt werden (nicht wie z. B. Java, wo klassische Objekte schwer sind. Die einzige Möglichkeit, einem harten Objekt ein neues Mitglied hinzuzufügen, ist das Erstellen einer neuen Klasse.) Mehr dazu hier: http://www.crockford.com/javascript/inheritance.html

Und am Ende musst du das Objekt nicht töten oder zerstören. Warum ich hier gefunden habe: http://bytes.com/topic/javascript/answers/152552-javascript-destroy-object

Hoffe das hilft

55
jazkat

In diesem Fall können Sie life verwenden, um auf das übergeordnete Objekt zu verweisen. Oder Sie können einen Verweis auf life im Benutzerobjekt speichern. In der Sprache kann Ihnen keine feste Variable parent zur Verfügung stehen, da Benutzer lediglich eine Referenz auf ein Objekt sind und es möglicherweise andere Referenzen gibt.

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!

Es könnte hilfreich sein, so etwas zu verwenden:

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

Wenn ich Ihre Frage richtig lese, sind Objekte im Allgemeinen unklar, wo sie sich befinden. Sie wissen nicht, wer ihre Eltern sind. Um diese Informationen zu finden, müssen Sie die übergeordnete Datenstruktur analysieren. Das DOM kann dies für uns tun, wenn Sie über Elementobjekte in einem Dokument sprechen, aber es sieht so aus, als würden Sie von Vanilla-Objekten sprechen.

4
Adam Bellaire

Über Anruf:

Sie können dieses Problem lösen, indem Sie .call() verwenden.

  • muss für eine Funktion aufgerufen werden addName.call()
  • sie übergeben ihm ein Objekt dessen, was Sie "das" sein wollen addName.call({"name" : 'angela'});
  • sie können zusätzliche Argumente übergeben, die in der Funktion verwendet werden können, in der sie für addName.call({"name": "angela"}, true); aufgerufen wird, wobei addName möglicherweise ein Argument von boolean append akzeptiert.

Call verwenden:

Für dieses spezielle Problem können wir das "übergeordnete" Objekt über call übergeben, um die this zu überschreiben, die normalerweise im untergeordneten Objekt vorhanden ist.

Sehen Sie sich zuerst unser Problem an

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

Hier ist ein Lösungsaufruf

Und JSFIDDLE um zu sehen, wie es funktioniert.

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

Abschließend

Sie können .call() immer dann verwenden, wenn Sie eine Methode für eine Eigenschaft Ihres Hauptobjekts verwenden: app.options.someFunction(arg) sollte immer mit .call - app.options.someFunction.call(this, arg); aufgerufen werden. Auf diese Weise können Sie sicherstellen, dass Sie jederzeit auf alle Teile des Objekts zugreifen können. Dadurch können Sie auf die Methoden einer anderen Eigenschaft wie app.helpers.anotherFunction() zugreifen.

Eine gute Idee ist in somefunction, speichern Sie this in einer Variablen _parentThis. Es ist also offensichtlich, was die this widerspiegelt.

4
amurrell

Bitte schön:

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

Stellen Sie außerdem sicher, dass Sie nach der Definition "Mädchen" kein Komma haben. Dies führt dazu, dass das Skript in IE abstürzt (jedes Mal, wenn Sie nach dem letzten Eintrag in einem Array in IE ein Komma haben).

Lass es laufen

3
cmcculloh

Ich habe etwas verwendet, das Singleton-Pattern ähnelt:

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

Wie andere bereits gesagt haben, ist es nicht möglich, einen Elternteil direkt von einem verschachtelten Kind zu suchen. Alle vorgeschlagenen Lösungen empfehlen verschiedene Möglichkeiten, über einen expliziten Variablennamen auf das übergeordnete Objekt oder den übergeordneten Bereich zurückzugreifen.

Das direkte Überfahren zum übergeordneten Objekt ist jedoch möglich, wenn Sie rekursive ES6 Proxies für das übergeordnete Objekt verwenden.

Ich habe eine Bibliothek namens ObservableSlim geschrieben, die es Ihnen ua ermöglicht, von einem untergeordneten Objekt zum übergeordneten Objekt zu gelangen. 

Hier ist ein einfaches Beispiel ( jsFiddle Demo ):

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.

Ich habe so etwas gemacht und es funktioniert wie ein Zauber.

Einfach.

P.S. Es gibt mehr das Objekt, aber ich habe gerade den relevanten Teil gepostet.

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

Wenn Sie alle Elternschlüssel eines Knotens in einem Literalobjekt ({}) abrufen möchten, können Sie Folgendes tun:

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

Dieser Algorithmus verwendet das FIFO-Konzept, um die Diagramme mit der BFS-Methode zu durchlaufen. Dieser Code erweitert die Klasse Object um die statische Methode parentKeys, die einen literal Object (Hashtabellenassoziatives Array ...) des Javacript als Parameter erwartet.

Ich hoffe ich habe geholfen.

0
rplaurindo

Mit dem folgenden Code können Sie auf das übergeordnete Objekt des Objekts zugreifen:

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

Ich würde empfehlen, dass Sie über Javascript Objects lesen, um zu erfahren, wie Sie mit Objects arbeiten können, es hat mir sehr geholfen. Ich fand sogar Funktionen heraus, von denen ich nicht einmal wusste, dass sie existieren.

0
Rodrigo Morales