Question Auto-références dans les déclarations littérales d'objets


Existe-t-il un moyen d'obtenir les éléments suivants pour travailler en JavaScript?

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

Dans la forme actuelle, ce code renvoie évidemment une erreur de référence depuis this ne se réfère pas à foo. Mais est Y a-t-il un moyen d'avoir des valeurs dans les propriétés d'un littéral d'objet dépendant d'autres propriétés déclarées précédemment?


501
2018-01-06 14:53


origine


Réponses:


Eh bien, la seule chose dont je peux vous parler sont les getters:

var foo = {
  a: 5,
  b: 6,
  get c () {
    return this.a + this.b;
  }
};

foo.c; // 11

Ceci est une extension syntaxique introduite par la spécification ECMAScript 5th Edition, la syntaxe est prise en charge par la plupart des navigateurs modernes (y compris IE9).


494
2018-01-06 14:58



Vous pourriez faire quelque chose comme:

var foo = {
   a: 5,
   b: 6,
   init: function() {
       this.c = this.a + this.b;
       return this;
   }
}.init();

Ce serait une sorte d'initialisation unique de l'objet.

Notez que vous attribuez en fait la valeur de retour de init() à foodonc vous devez return this.


276
2018-01-06 14:59



La réponse évidente et simple est manquante, donc pour être complet:

Mais est Y a-t-il un moyen d'avoir des valeurs dans les propriétés d'un littéral d'objet dépendant d'autres propriétés déclarées précédemment?

Toutes les solutions ici la reportent jusqu'à la création de l'objet (de différentes manières), puis affectent la troisième propriété. le le plus simple façon de faire simplement ceci:

var foo = {
    a: 5,
    b: 6
};
foo.c = foo.a + foo.b;

Tous les autres ne sont que des moyens plus indirects de faire la même chose. (Felix est particulièrement intelligent, mais nécessite de créer et de détruire une fonction temporaire, ce qui ajoute de la complexité et laisse une propriété supplémentaire sur l'objet ou [si vous le souhaitez. delete cette propriété] influe sur la performance des accès de propriété ultérieurs sur cet objet.)

Si vous avez besoin que tout soit dans une expression, vous pouvez le faire sans la propriété temporaire:

var foo = function(o) {
    o.c = o.a + o.b;
    return o;
}({a: 5, b: 6});

Ou bien sûr, si vous devez le faire plus d'une fois:

function buildFoo(a, b) {
    var o = {a: a, b: b};
    o.c = o.a + o.b;
    return o;
}

alors où vous devez l'utiliser:

var foo = buildFoo(5, 6);

136
2018-05-26 12:11



Instanciez simplement une fonction anonyme:

var foo = new function () {
    this.a = 5;
    this.b = 6;
    this.c = this.a + this.b;
};

59
2018-04-11 22:32



Certaines fermetures devraient traiter de cela;

var foo = function() {
    var a = 5;
    var b = 6;
    var c = a + b;

    return {
        a: a,
        b: b,
        c: c
    }
}();

Toutes les variables déclarées dans foo sont privés à foo, comme vous vous en doutez avec toute déclaration de fonction et parce qu'elles ont toutes une portée, elles ont toutes accès les unes aux autres sans devoir se référer à this, comme on peut s'y attendre avec une fonction. La différence est que cette fonction retourne un objet qui expose les variables privées et affecte cet objet à foo. En fin de compte, vous revenez juste l'interface que vous voulez exposer comme un objet avec le return {} déclaration.

La fonction est ensuite exécutée à la fin avec le () ce qui fait que l’objet foo entier est évalué, que toutes les variables à l’instanciation et l’objet de retour sont ajoutés comme propriétés de foo().


18
2017-07-02 09:04



Vous pourriez le faire comme ça

var a, b
var foo = {
    a: a = 5,
    b: b = 6,
    c: a + b
}

Cette méthode s’est avérée utile lorsque j’ai dû me référer à l’objet sur lequel une fonction était initialement déclarée. Voici un exemple minimal de mon utilisation:

function createMyObject() {
    var count = 0, self
    return {
        a: self = {
            log: function() {
                console.log(count++)
                return self
            }
        }
    }
}

En vous définissant comme objet contenant la fonction d'impression, vous autorisez la fonction à faire référence à cet objet. Cela signifie que vous n'aurez pas à "lier" la fonction d'impression à un objet si vous devez le transmettre ailleurs.

Si vous préférez, utilisez plutôt this comme illustré ci-dessous

function createMyObject() {
    var count = 0
    return {
        a: {
            log: function() {
                console.log(count++)
                return this
            }
        }
    }
}

Ensuite, le code suivant enregistrera 0, 1, 2 et donnera ensuite une erreur

var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!

En utilisant la méthode self, vous garantissez que print retournera toujours le même objet quel que soit le contexte dans lequel la fonction est exécutée. Le code ci-dessus fonctionnera très bien et connectera 0, 1, 2 et 3 lors de l’utilisation de la version auto de createMyObject().


14
2018-05-24 22:25



Maintenant, dans ES6, vous pouvez créer des propriétés mises en cache paresseuses. Lors de la première utilisation, la propriété est évaluée une fois pour devenir une propriété statique normale. Résultat: la deuxième fois que la surcharge de la fonction mathématique est ignorée.

La magie est dans le getter.

const foo = {
    a: 5,
    b: 6,
    get c() {
        delete this.c;
        return this.c = this.a + this.b
    }
};

Dans la flèche getter this ramasse le portée lexicale.

foo     // {a: 5, b: 6}
foo.c   // 11
foo     // {a: 5, b: 6 , c: 11}  

13
2017-11-08 23:43



Il y a plusieurs façons d'accomplir ceci; c'est ce que j'utiliserais:

function Obj() {
 this.a = 5;
 this.b = this.a + 1;
 // return this; // commented out because this happens automatically
}

var o = new Obj();
o.b; // === 6

7
2018-01-06 18:55