Javascript usa variable como nombre de objeto

91

Quiero usar el valor de una variable para acceder a un objeto.

Digamos que tengo un objeto llamado myobject.

Quiero llenar una variable con este nombre y usar la variable para acceder al objeto.

Ejemplo:

var objname = 'myobject';
{objname}.value = 'value';
PeeHaa
fuente

Respuestas:

125

Global:

myObject = { value: 0 };
anObjectName = "myObject";
this[anObjectName].value++;

console.log(this[anObjectName]);

Global: v2

var anObjectName = "myObject";
this[anObjectName] = "myvalue"

console.log(myObject)

Local: v1

(function() {
    var scope = this;

    if (scope != arguments.callee) {
        arguments.callee.call(arguments.callee);
        return false;
    }

    scope.myObject = { value: 0 };
    scope.anObjectName = "myObject";
    scope[scope.anObjectName].value++;

    console.log(scope.myObject.value);
})();

Local: v2

(function() {  
    var scope = this;

    scope.myObject = { value: 0 };
    scope.anObjectName = "myObject";
    scope[scope.anObjectName].value++;

    console.log(scope.myObject.value);    
}).call({});
Shaz
fuente
@Shaz: ambos hacen referencia al mismo alcance en realidad ;-) (Suponiendo que se ejecuten en un navegador) alert(this === window).
Sean Vieira
1
@PeeHaa - El local ejemplo, se establece una variable en el windowobjeto llamado objnameque se hace referencia a continuación, a través de this... se puede sustituir windowpor thisen el segundo ejemplo y todo puede funcionar. :-)
Sean Vieira
1
@SeanVieira: Eche un vistazo al ejemplo actualizado. Esperemos que esto funcione correctamente ahora.
Shaz
1
@Shaz: arguments.calleeestá en desuso, pero no obstante es una implementación muy inteligente, y no ensucia el alcance global. +1
Sean Vieira
1
Puede que no esté contaminando el alcance global, pero está creando un objeto que es compartido por cada invocación de la función. Su función se mantiene objnamecomo una propiedad de la función en sí. Puede fallar para funciones recursivas. No estoy seguro de cómo se puede usar esto en el mundo real.
Juan Mendes
27

Utilice corchetes alrededor del nombre de la variable.

var objname = 'myobject';
{[objname]}.value = 'value';
Vaishali Venkatesan
fuente
7
Esto es perfecto y simple y debería ser la mejor respuesta.
Brad
5
Esto arroja una excepción: SyntaxError: expresión esperada, obtuvo '.'. No funciona; ¿Por qué tantos votos a favor?
Lovro
9

¿Es una variable global? Si es así, estos son en realidad parte del windowobjeto, por lo que puede hacerlo window[objname].value.

Si es local para una función, no creo que haya una buena manera de hacer lo que quieres.

JW.
fuente
8

El objeto existe en algún ámbito, por lo que casi siempre puede acceder a la variable a través de esta sintaxis:

var objname = "myobject";
containing_scope_reference[objname].some_property = 'some value';

El único lugar donde esto se complica es cuando se encuentra en un ámbito cerrado y desea acceder a una variable local de nivel superior. Cuando tienes algo como esto:

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    console.log(this[x], window[x]); // Doesn't work
})();

Usted puede conseguir alrededor de eso usando evalen lugar de acceder a la cadena de ámbito actual ... pero yo no lo recomendaría a menos que usted ha hecho un montón de pruebas y se sabe que esa es la mejor manera de hacer las cosas.

(function(){
    var some_variable = {value: 25};
    var x = "some_variable";
    eval(x).value = 42;
    console.log(some_variable); // Works
})();

Su mejor opción es tener una referencia a un nombre en un objeto que siempre estará allí (como thisen el alcance global o una variable privada de nivel superior en un alcance local) y poner todo lo demás allí.

Así:

var my_outer_variable = {};
var outer_pointer = 'my_outer_variable';
// Reach my_outer_variable with this[outer_pointer]
// or window[outer_pointer]

(function(){
    var my_inner_scope = {'my_inner_variable': {} };
    var inner_pointer = 'my_inner_variable';
    // Reach my_inner_variable by using
    // my_inner_scope[inner_pointer]
})();
Sean Vieira
fuente
7

Podrías usar eval:

eval(variablename + ".value = 'value'");
Midas
fuente
¿No se evalconsidera evil? Si no, podría usarlo. Porque es global en este momento, pero quería moverlo a una función para limpiar cosas.
PeeHaa
1
Jajaja Si el nombre de la variable proviene de la entrada del usuario, asegúrese de validarlo, para que no contenga ningún código JS que evalpueda ejecutarse.
Midas
1
Este es uno de los pocos usos legítimos de eval, en mi opinión. Sin embargo, tenemos que asegurarnos de que la variable esté limpia.
Levi Morrison
2
Sí, no es realmente un problema. Pero eche un vistazo a la respuesta de Shaz. Creo que es una solución más limpia.
Midas
2
@PeeHaa: Si está considerando moverlo, ¿por qué no moverlo a una propiedad de un objeto conocido, para que pueda hacer algo como myVar[objname].value?
JW.
6

No puede hacer esto en general, excepto en el ámbito de la ventana, donde puede escribir window[objname].value = 'value';

Neil
fuente
4

Creo que la respuesta de Shaz para las variables locales es difícil de entender, aunque funciona para funciones no recursivas. Aquí hay otra forma en que creo que es más clara (pero sigue siendo su idea, exactamente el mismo comportamiento). Tampoco está accediendo a las variables locales dinámicamente, solo la propiedad de la variable local.

Esencialmente, está usando una variable global (adjunta al objeto de función)

// Here's  a version of it that is more straight forward.
function doIt() {
    doIt.objname = {};
    var someObject = "objname";
    doIt[someObject].value = "value";    
    console.log(doIt.objname);
})();

Que es esencialmente lo mismo que crear un global para almacenar la variable, por lo que puede acceder a él como una propiedad. Crear un global para hacer esto es un truco.

Aquí hay un truco más limpio que no crea variables globales, sino que usa una variable local.

function doIt() {
  var scope = {
     MyProp: "Hello"
  };
  var name = "MyProp";
  console.log(scope[name]);
}

Ver Javascript: ¿interpretar cadena como referencia de objeto?

Juan Mendes
fuente
1

Si el objeto está en algún espacio de nombres, es decir. Company.Module.Components.Foopuedes usar esta función:

CoffeeScript:

objByName: (name, context = window) ->
    ns = name.split "."
    func = context
    for n, i in ns
        func = func[n]
    return func

Js resultantes:

objByName: function(name, context) {
  var func, i, n, ns, _i, _len;
  if (context == null) {
    context = window;
  }
  ns = name.split(".");
  func = context;
  for (i = _i = 0, _len = ns.length; _i < _len; i = ++_i) {
    n = ns[i];
    func = func[n];
  }
  return func;
}

Entonces puedes crear un nuevo objeto o hacer lo que sea. Tenga en cuenta los paréntesis.

var o = new (objByName('Company.Module.Components.Foo'))
objByName('some.deeply.nested.object').value

Esta idea está tomada de una pregunta similar: cómo ejecutar una función de JavaScript cuando tengo su nombre como una cadena

Comunidad
fuente
1
let players = [];
players[something] = {};
players[something].somethingElse = 'test';
console.log(players); 

-> [algo: {algoElse: 'prueba'}];

part1cle
fuente
0

Cuando utilice la ventana [objname], asegúrese de que objname sea variables globales. De lo contrario, funcionará en algún momento y fallará en ocasiones. ventana [objname] .value.

lyon819
fuente
0

Uno de los desafíos que tuve con las respuestas es que asumió que el objeto era de un solo nivel. Por ejemplo,

const testObj = { testKey: 'testValue' }
const refString = 'testKey';
const refObj = testObj[refString];

funciona bien, pero

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testKey.level2Key';
const refObj = testObj[refString];

No funciona.

Lo que terminé haciendo fue construir una función para acceder a objetos de varios niveles:

objVar(str) {
    let obj = this;
    const parts = str.split('.');
    for (let p of parts) {
        obj = obj[p];
    }
    return obj;
}

En el segundo escenario, entonces, puedo pasar la cadena a esta función para recuperar el objeto que estoy buscando:

const testObj = { testKey:
                  { level2Key: 'level2Value' }
                }
const refString = 'testObj.testKey.level2Key';
const refObj = objVar[refString];
Mitch Parker
fuente
0

Puede establecer una propiedad de objetos de esta manera:

var obj = {};
obj.whateverVarName = 'yourVal';
console.log(obj);

ThisisFish
fuente
0

Si ya conoce la lista de posibles nombres de variables, intente crear un nuevo Objeto (iconObj) cuyo nombre de propiedades sea el mismo que el de los nombres de objeto. Aquí, en el siguiente ejemplo, la variable iconLib contendrá dos valores de cadena, ya sea 'ZondIcons' o 'MaterialIcons' . propertyName es propiedad del objeto ZondIcons o MaterialsIcon.

   const iconObj = {
    ZondIcons,
    MaterialIcons,
  }
  const objValue = iconObj[iconLib][propertyName]
Sumer
fuente
-1
var micro=[{'test':'hello'}];

var device = 'test';

console.log(micro[device]);
alfonsoolavarria
fuente