Autorreferencias en literales/inicializadores de objetos

Resuelto kpozin asked hace 13 años • 32 respuestas

¿Hay alguna manera de hacer que algo como lo siguiente funcione en JavaScript?

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

En el formato actual, este código obviamente arroja un error de referencia ya que thisno hace referencia a foo. Pero, ¿ hay alguna forma de que los valores de las propiedades de un objeto literal dependan de otras propiedades declaradas anteriormente?

kpozin avatar Jan 06 '11 21:01 kpozin
Aceptado

Bueno, lo único que puedo contarte es getter :

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

console.log(foo.c) // 11
Expandir fragmento

Esta es una extensión sintáctica introducida por la especificación ECMAScript 5.ª edición, la sintaxis es compatible con la mayoría de los navegadores modernos (incluido IE9).

Christian C. Salvadó avatar Jan 06 '2011 14:01 Christian C. Salvadó

Podrías hacer algo como:

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

Esto sería una especie de inicialización única del objeto.

Tenga en cuenta que en realidad está asignando el valor de retorno de init()a foo, por lo tanto debe hacerlo return this.

Felix Kling avatar Jan 06 '2011 14:01 Felix Kling

Falta la respuesta obvia y simple, así que para completar:

Pero, ¿ hay alguna forma de que los valores de las propiedades de un objeto literal dependan de otras propiedades declaradas anteriormente?

No. Todas las soluciones aquí lo difieren hasta que se crea el objeto (de varias maneras) y luego asignan la tercera propiedad. La forma más sencilla es hacer esto:

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

Todos los demás son simplemente formas más indirectas de hacer lo mismo. (Felix es particularmente inteligente, pero requiere crear y destruir una función temporal, lo que agrega complejidad; y deja una propiedad adicional en el objeto o [si tiene deleteesa propiedad] afecta el rendimiento de los accesos posteriores a la propiedad en ese objeto).

Si necesita que todo esté dentro de una expresión, puede hacerlo sin la propiedad temporal:

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

O por supuesto, si necesitas hacer esto más de una vez:

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

luego donde necesitas usarlo:

var foo = buildFoo(5, 6);
T.J. Crowder avatar May 26 '2012 12:05 T.J. Crowder