recorrer orientado objetos objeto literales lista herencia eliminar elemento buscar array agregar javascript object-literal

orientado - objetos literales javascript



Autoreferencias en literales de objetos/inicializadores. (21)

¿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 formulario actual, este código obviamente arroja un error de referencia, ya que no se refiere a foo . Pero, ¿ hay alguna forma de que los valores en las propiedades de un objeto literal dependan de otras propiedades declaradas anteriormente?


Nota: esta solución utiliza Typescript (puede usar el JS de vainilla que TS compila si es necesario)

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

Aquí utilizamos expresiones de clase para obtener la interfaz literal del objeto anidado que queremos. Esto es lo mejor que tengo para hacer referencia a las propiedades de un objeto durante la creación.

Lo más importante a tener en cuenta es que al utilizar esta solución, tiene exactamente la misma interfaz que tenía desde un objeto literal. Y la sintaxis es bastante similar a un objeto literal en sí (frente a usar una función, etc.).

Compara lo siguiente

Solucion he propuesto

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

Solución si los literales de objetos hubieran bastado.

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

Otro ejemplo

Aquí en esta clase, puede combinar múltiples rutas relativas entre sí, lo que no es posible con un objeto literal.

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


¿Qué tal esta solución también funcionará con objetos anidados con matriz?

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


Ahora en ES6 puedes crear propiedades en caché perezosas. En el primer uso, la propiedad se evalúa una vez para convertirse en una propiedad estática normal. Resultado: La segunda vez que se omite la sobrecarga de la función matemática.

La magia está en el getter.

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

En el captador de flechas, this recoge el ámbito léxico circundante .

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


Algunos cierres deberían lidiar con esto;

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

Todas las variables declaradas dentro de foo son privadas a foo , como cabría esperar con cualquier declaración de función y debido a que todas están dentro del alcance, todas tienen acceso entre sí sin necesidad de referirse a this , tal como cabría esperar con una función. La diferencia es que esta función devuelve un objeto que expone las variables privadas y asigna ese objeto a foo . Al final, devuelve solo la interfaz que desea exponer como un objeto con la declaración return {} .

La función se ejecuta al final con () que hace que se evalúe el objeto foo completo, todas las variables creadas en instancias y el objeto devuelto se agregue como propiedades de foo() .


Aquí hay una forma limpia de ES6:

var foo = (o => ({ ...o, c: o.a + o.b }))({ a: 5, b: 6 }); console.log(foo);

Lo uso para hacer algo como esto:

const constants = Object.freeze( (_ => ({ ..._, flag_data: { [_.a_flag]: ''foo'', [_.b_flag]: ''bar'', [_.c_flag]: ''oof'' } }))({ a_flag: 5, b_flag: 6, c_flag: 7, }) ); console.log(constants.flag_data[constants.b_flag]);


Bueno, lo único de lo que puedo hablarles son los captadores:

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

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


Crear una nueva función en su objeto literal e invocar a un constructor parece una desviación radical del problema original, y es innecesario.

No puede hacer referencia a una propiedad de hermano durante la inicialización literal del objeto.

var x = { a: 1, b: 2, c: a + b } // not defined var y = { a: 1, b: 2, c: y.a + y.b } // not defined

La solución más simple para las propiedades computadas es la siguiente (sin montón, sin funciones, sin constructor):

var x = { a: 1, b: 2 }; x.c = x.a + x.b; // apply computed property


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

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

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

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

Todos los demás son formas más indirectas de hacer lo mismo. (Felix''s es particularmente inteligente, pero requiere crear y destruir una función temporal, agregar complejidad, y dejar una propiedad adicional en el objeto o [si delete esa propiedad] afecta el rendimiento de los accesos de propiedad posteriores 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 necesita 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; }

entonces donde necesitas usarlo:

var foo = buildFoo(5, 6);


Hay varias maneras de lograr esto; esto es lo que usaría:

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


La clave de todo esto es SCOPE .

Debe encapsular el "padre" (objeto principal) de la propiedad que desea definir como su propio objeto instanciado, y luego puede hacer referencia a las propiedades de hermanos utilizando la palabra clave this

Es muy, muy importante recordar que si se refiere a this sin hacerlo primero, entonces se referirá al ámbito externo ... que será el objeto de la window .

var x = 9 //this is really window.x var bar = { x: 1, y: 2, foo: new function(){ this.a = 5, //assign value this.b = 6, this.c = this.a + this.b; // 11 }, z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object) };


Lanzar una opción ya que no vi este escenario exacto cubierto. Si no desea que c actualice cuando a o b actualicen, entonces, un ES6 IIFE funciona bien.

var foo = ((a,b) => ({ a, b, c: a + b }))(a,b);

Para mis necesidades, tengo un objeto que se relaciona con una matriz que terminará siendo utilizada en un bucle, así que solo quiero calcular una configuración común una vez, así que esto es lo que tengo:

let processingState = ((indexOfSelectedTier) => ({ selectedTier, indexOfSelectedTier, hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier) .some(t => pendingSelectedFiltersState[t.name]), }))(tiers.indexOf(selectedTier));

Ya que necesito establecer una propiedad para indexOfSelectedTier y necesito usar ese valor al configurar la propiedad hasUpperTierSelection , calculo ese valor primero y lo paso como parámetro al IIFE


Las otras respuestas publicadas aquí son mejores, pero aquí hay una alternativa que:

  • Establece el valor en la inicialización (no un captador, ni derivado, etc.)
  • No requiere ningún tipo de init() o código fuera del literal del objeto
  • Es un objeto literal y no una función de fábrica u otro mecanismo de creación de objetos.
  • No debería tener ningún impacto en el rendimiento (excepto en la inicialización)

Funciones anónimas autoejecutables y almacenamiento de ventanas.

var foo = { bar:(function(){ window.temp = "qwert"; return window.temp; })(), baz: window.temp };

El pedido está guaranteed ( bar antes de baz ).

Por supuesto, contamina la window , pero no puedo imaginarme a alguien escribiendo un script que requiera que window.temp sea ​​persistente. Tal vez tempMyApp si eres paranoico.

También es feo pero ocasionalmente útil. Un ejemplo es cuando está utilizando una API con condiciones de inicialización rígidas y no tiene ganas de refactorizar, por lo que el alcance es correcto.

Y está seco, por supuesto.


Para completar, en ES6 tenemos clases (admitidas al momento de escribir esto solo por los últimos navegadores, pero disponibles en Babel, TypeScript y otros transpilers)

class Foo { constructor(){ this.a = 5; this.b = 6; this.c = this.a + this.b; } } const foo = new Foo();


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 algún tipo 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 return this .


Podrías hacerlo así

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

Ese método me ha resultado útil cuando tuve que referirme al objeto en el que originalmente se declaró una función. El siguiente es un ejemplo mínimo de cómo lo usé:

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

Al definirse a sí mismo como el objeto que contiene la función de impresión, permite que la función se refiera a ese objeto. Esto significa que no tendrá que "vincular" la función de impresión a un objeto si necesita pasarlo a otra parte.

Si, en cambio, utilizarías this como se ilustra a continuación

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

Luego el siguiente código registrará 0, 1, 2 y luego dará un error

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!

Al utilizar el método del self, garantiza que la impresión siempre devolverá el mismo objeto independientemente del contexto en el que se ejecute la función. El código anterior se ejecutará correctamente y registrará 0, 1, 2 y 3 cuando se use la versión propia de createMyObject() .


Puedes hacerlo utilizando el patrón del módulo. Al igual que:

var foo = function() { var that = {}; that.a = 7; that.b = 6; that.c = function() { return that.a + that.b; } return that; }; var fooObject = foo(); fooObject.c(); //13

Con este patrón puedes instanciar varios objetos foo de acuerdo a tus necesidades.

http://jsfiddle.net/jPNxY/1/


Si su objeto se escribe como una función que devuelve un objeto, Y utiliza los "métodos" de atributo de objeto ES6, entonces es posible:

const module = (state) => ({ a: 1, oneThing() { state.b = state.b + this.a }, anotherThing() { this.oneThing(); state.c = state.b + this.a }, }); const store = {b: 10}; const root = module(store); root.oneThing(); console.log(store); root.anotherThing(); console.log(store); console.log(root, Object.keys(root), root.prototype);


Simplemente ejemplifica una función anónima:

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


Un enfoque diferente, para mantener las cosas un poco más simples y no para definir nuevas funciones en el objeto , es mantener el objeto original con sus propiedades, crear un segundo objeto con las propiedades dinámicas que usan las propiedades del primer objeto y luego fusionar usando la spread .

Asi que:

Objeto

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

Objeto 2

var foo2 = { c: foo.a + foo.b };

Unir

Object.assign(foo, foo2);

o

foo = {...foo, ...foo2};

Resultado de foo:

{ "a":5, "b":6, "c":11 }

Todo dentro del mismo js, ​​no hay nuevas funciones dentro del objeto, solo se usa asignar o difundir.


Utilizo el siguiente código como alternativa, y funciona. Y la variable puede ser matriz también. (@ Fausto R.)

var foo = { a: 5, b: 6, c: function() { return this.a + this.b; }, d: [10,20,30], e: function(x) { this.d.push(x); return this.d; } }; foo.c(); // 11 foo.e(40); // foo.d = [10,20,30,40]


solo por el bien del pensamiento: coloque las propiedades del objeto fuera de una línea de tiempo:

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

Hay mejores respuestas arriba también . Así es como modifiqué el código de ejemplo que cuestionaste.

ACTUALIZAR:

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