918 Stimmen

Selbstreferenzen in Objektliteralen/Initialisierern

Gibt es eine Möglichkeit, so etwas wie das Folgende in JavaScript zum Laufen zu bringen?

var foo = {
    a: 5,
    b: 6,
    c: this.a + this.b  // Doesn't work
};

In der aktuellen Form führt dieser Code offensichtlich zu einem Referenzfehler, da this bezieht sich nicht auf foo . Aber ist Gibt es eine Möglichkeit, die Werte in den Eigenschaften eines Objektliterales von anderen, früher deklarierten Eigenschaften abhängig zu machen?

1voto

Gaurav Punkte 793

Wie wäre es mit dieser Lösung wird dies mit verschachtelten Objekten mit Array als auch arbeiten

      Object.prototype.assignOwnProVal
     = function (to,from){ 
            function compose(obj,string){ 
                var parts = string.split('.'); 
                var newObj = obj[parts[0]]; 
                if(parts[1]){ 
                    parts.splice(0,1);
                    var newString = parts.join('.'); 
                    return compose(newObj,newString); 
                } 
                return newObj; 
            } 
            this[to] = compose(this,from);
     } 
     var obj = { name : 'Gaurav', temp : 
                  {id : [10,20], city:
                        {street:'Brunswick'}} } 
     obj.assignOwnProVal('street','temp.city.street'); 
     obj.assignOwnProVal('myid','temp.id.1');

1voto

i474232898 Punkte 622

Hier ist ein Beispiel für das Verhalten von "this" im Objekt.

this.prop = 'external';
global.prop = 'global.prop';
const that = this;

const a = {
  prop: 'internal',
  prop1: this.prop, //external

  log() {
    return this.prop //internal
  },
  log1: () => {
    return this.prop //external
  },
  log2: () => {
    return function () {
      return this.prop; //'global.prop' in node; 'external' in chrome
    }()
  },
  log3: function () {
    return (() => {
      return this.prop; //internal
    })()
  },
}

0voto

flen Punkte 1669

Zwei faule Lösungen

Es gibt hier bereits ausgezeichnete Antworten, und ich bin kein Experte auf diesem Gebiet, aber ich bin ein Experte darin, faul zu sein, und in meinen Augen scheinen diese Antworten nicht faul genug zu sein.

Erstens: Objekt aus anonymer Funktion zurückgeben

Eine sehr leichte Abweichung von T.J. Crowder , Henry Wrightson y Rafael Rocha Antworten:

var foo = (() => {

  // Paste in your original object
  const foo = {
    a: 5,
    b: 6,
  };

  // Use their properties
  foo.c = foo.a + foo.b;

  // Do whatever else you want

  // Finally, return object
  return foo;
})();

console.log(foo);

Der kleine Vorteil dabei ist, dass Sie Ihr ursprüngliches Objekt einfach so einfügen können, wie es war, ohne sich um Argumente usw. zu kümmern (IMHO wird die Wrapper-Funktion auf diese Weise ziemlich transparent).

Zweitens: Verwendung von setTimeout

Dies hier kann funktionieren, wenn Sie nicht brauchen foo.c und zwar sofort:

var foo = {
  a: 5,
  b: 6,
  c: setTimeout(() => foo.c = foo.a + foo.b, 0)
};

// Though, at first, foo.c will be the integer returned by setTimeout
console.log(foo);
// But if this isn't an issue, the value will be updated when time comes in the event loop
setTimeout( () => console.log(foo), 0);

0voto

Lyokolux Punkte 775

Ok, ich habe eine andere Lösung gefunden. Hier möchte ich ein Objekt initialisieren, das die Anzahl der Millisekunden für jede Zeiteinheit darstellt. Es stellt sich heraus, dass enum in typescript in meinem Fall nicht verwendet werden kann, also habe ich mehrere Variablen deklariert, die ich einem Objekt wie folgt zuweise:

const SECOND = 1000
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR
const WEEK = 7 * DAY

export const TimeInMS = {
  SECOND,
  MINUTE,
  HOUR,
  DAY,
  WEEK
}

Die Nachteile dieser Methode sind:

  • Variablen werden als Konstanten definiert, auch wenn wir sie nicht brauchen. Dadurch wird unnötig Speicherplatz verbraucht.
  • jeder Wert des Objekts muss als eigenständige Variable deklariert werden

-1voto

Dheeraj Bhaskar Punkte 17881

Note : Diese Lösung verwendet Typescript (Sie können die Vanilla-JS, die TS kompiliert, wenn nötig) zu verwenden

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

    // this method is just to check/test this solution 
    check(){
        console.log(this.def.qwe);
    }
}

// these two lines are just to check
let instance = new asd();
instance.check();

Hier wurden Klassenausdrücke verwendet, um die gewünschte verschachtelte Objektliteralschnittstelle zu erhalten. Dies ist die nächste beste Sache IMHO zu können, um die Eigenschaften eines Objekts während der Erstellung zu verweisen.

Das Wichtigste dabei ist, dass Sie bei dieser Lösung genau die gleiche Schnittstelle haben, die Sie auch bei einem Objektliteral haben würden. Und die Syntax ist ziemlich nah an ein Objektliteral selbst (vs mit einer Funktion, etc.).

Vergleichen Sie Folgendes

Ich habe eine Lösung vorgeschlagen

class asd {
    def = new class {
        ads= 'asd';
        qwe= this.ads + '123';
    };

Lösung, wenn Objektliterale ausgereicht hätten

var asd = {
    def : {
        ads:'asd',
        qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
    }
}

Ein weiteres Beispiel

Hier in dieser Klasse können Sie mehrere relative Pfade untereinander kombinieren, was bei einem Objektliteral nicht möglich ist.

class CONSTANT {
    static readonly PATH = new class {
        /** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
         *
         */
        private readonly RELATIVE = new class {
            readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
            readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
            readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
            readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
            readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
            readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
        };
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X