Convertir cadena a nombre de variable en JavaScript

260

He buscado soluciones, pero no pude encontrar ninguna que funcione.

Tengo una variable llamada onlyVideo.

"onlyVideo"la cadena se pasa a una función. Quiero establecer la variable onlyVideodentro de la función como algo. ¿Cómo puedo hacer eso?

(Hay una serie de variables que podrían llamarse a la función, por lo que necesito que funcione dinámicamente, no ifdeclaraciones codificadas ).

Editar: Probablemente haya una mejor manera de hacer lo que intentas hacer. Lo pregunté al principio de mi aventura de JavaScript. Mira cómo funcionan los objetos JavaScript.

Una simple introducción:

// create JavaScript object
var obj = { "key1": 1 };

// assign - set "key2" to 2
obj.key2 = 2;

// read values
obj.key1 === 1;
obj.key2 === 2;

// read values with a string, same result as above
// but works with special characters and spaces
// and of course variables
obj["key1"] === 1;
obj["key2"] === 2;

// read with a variable
var key1Str = "key1";
obj[key1Str] === 1;
Switz
fuente
55
¿Para qué estás usando esto? ¿Está absolutamente seguro de que necesita establecerlo en una variable local normal y que un Objeto (Hash) no funcionará?
Dogbert
mmm ... Todavía no entiendo por qué quieres hacer esto en un mundo con matrices. De todos modos, parte de su código y explicación ayudarían mucho.
Kevin Chavez
Creo que necesitamos más detalles sobre cuál es su objetivo final
mcgrailm

Respuestas:

281

Si es una variable global, entonces window[variableName] o en su caso window["onlyVideo"]debería hacer el truco.

ingo
fuente
35
Incluso si no es global, puede acceder a él de esa manera scope[property]o inclusothis[property]
Wojciech Bednarski
77
@WojciechBednarski: No confunda el alcance y el contexto. thises el contexto, lo que apunta depende de cómo se llama la función. En JS, el 50% del tiempo thises a windowmenos que habilite el modo estricto y se thisconvierta undefinedy arroje un error. El alcance es algo completamente diferente y no es un objeto (excepto el alcance global que refleja el windowobjeto)
slebetman
3
No funciona en WebWorkers(donde se selfrefiere al alcance global, tal como lo hace en el navegador, donde es igual a window) y Node.js, donde globalestá la variable que desea. Y más reciente funciona con ámbitos locales, como el cuerpo de la función.
Tomáš Zato - Restablece a Mónica el
¿hay alguna forma de definir un constuso de este método?
toing_toing
165

Javascript tiene una eval()función para tales ocasiones:

function (varString) {
  var myVar = eval(varString);
  // .....
}

Editar: Lo siento, creo que leí la pregunta demasiado rápido. Esto solo te dará la variable, para configurarla necesitas

function SetTo5(varString) {
  var newValue = 5;
  eval(varString + " = " + newValue);
}

o si usa una cadena:

function SetToString(varString) {
  var newValue = "string";
  eval(varString + " = " + "'" + newValue + "'");
}

Pero me imagino que hay una manera más apropiada de lograr lo que estás buscando. No creo que eval () sea algo que realmente quieras usar a menos que haya una buena razón para ello. eval ()

goggin13
fuente
3
Sí, preferiría esto en lugar de usar window (tiene algunas advertencias)
Ingo
12
¿Por qué se eval()rechazó una respuesta a eliminación, y esta se votó a favor?
BoltClock
44
@goggin Deberías probar el argumento con expresiones regulares para asegurarte de que sea un nombre válido. Simplemente evaluar el argumento sin verificarlo primero es ridículamente inseguro.
Šime Vidas
16
Esta es la única respuesta realista a la pregunta. El hecho de que involucrara la evaluación "eeeeevil" no lo hace menos cierto. Javascript no tiene variables variables (como $$ varname en php), por lo que esta es realmente la única respuesta. El uso window[varname]tiene el efecto secundario de introducir variables globales, que podrían no ser deseadas. @ Shaz No creo que le des suficiente crédito a los intérpretes modernos de JS. Son extremadamente rápidos, y analizar y ejecutar una operación simple de asignación de una línea no aumentará el uso de la CPU de nadie, siempre que no se realice en un temporizador de 1 ms o en un bucle cerrado.
MooGoo
2
@TheParamagneticCroissant Personas apasionadas por el cuidado de códigos. Los que solo valoran el tiempo y el dinero no lo hacen.
Jimbo
41

En cuanto a las soluciones eval vs. globales variables ...

Creo que hay ventajas para cada uno, pero esto es realmente una falsa dicotomía. Si eres paranoico del espacio de nombres global, solo crea un espacio de nombres temporal y usa la misma técnica.

var tempNamespace = {};
var myString = "myVarProperty";

tempNamespace[myString] = 5;

Bastante seguro de que podría acceder como tempNamespace.myVarProperty (ahora 5), ​​evitando usar la ventana para el almacenamiento. (La cadena también se puede poner directamente entre los corchetes)

jm0
fuente
Un poco refactorice su código para hacer la misma línea var tempNamespace = {["myVarProperty"]: "Definitivamente solo video"};
Tioma
1
Esta es una muy buena solución: parece que se debe evaluar eval () a menos que sea absolutamente necesario, una solución muy elegante aquí.
skwidbreth
Comenzando con la colección document.body.getElementsByTagName ('*') es fácil encontrar todos los elementos que tienen un atributo 'id' y crear una variable para el valor del objeto elemento de cada uno en un objeto 'id' global. Entonces puede referirse a <div id = container> en JavaScript como 'id.container'. ¡Tan fácil!
David Spector
15
var myString = "echoHello";

window[myString] = function() {
    alert("Hello!");
}

echoHello();

Di no al malvado eval. Ejemplo aquí: https://jsfiddle.net/Shaz/WmA8t/

Shaz
fuente
3
Haga que esto funcione en el ámbito local y eliminaré el voto negativo.
Tomáš Zato - Restablece a Mónica el
@ TomášZatofunction aScope() { this[myString] = function() { alert("Hello!"); };};
rrw
@richmondwang thisno hace referencia al ámbito local, sino al objeto al que está vinculada la función durante la llamada.
Tomáš Zato - Restablece a Mónica el
8

Puede acceder al objeto de ventana como una matriz asociativa y configurarlo de esa manera

window["onlyVideo"] = "TEST";
document.write(onlyVideo);
Eric Conner
fuente
8

El método de la ventana ['variableName'] SOLO funciona si la variable se define en el ámbito global. La respuesta correcta es "Refactor". Si puede proporcionar un contexto de "Objeto", existe una posible solución general, pero hay algunas variables que ninguna función global podría resolver en función del alcance de la variable.

(function(){
    var findMe = 'no way';
})();
Lance Caraccioli
fuente
6

Si está intentando acceder a la propiedad de un objeto, debe comenzar con el alcance de windowy recorrer cada propiedad del objeto hasta llegar al que desea. Suponiendo que a.b.cse haya definido en otra parte del script, puede usar lo siguiente:

var values = window;
var str = 'a.b.c'.values.split('.');

for(var i=0; i < str.length; i++)
    values = values[str[i]];

Esto funcionará para obtener la propiedad de cualquier objeto, sin importar cuán profundo sea.


fuente
Tu ejemplo es genial. Observo que si uso namecomo nombre de variable, su ejemplo falla, pero funciona con otros nombres de variables. Esto puede tener que ver con el objeto Window que ya tiene una namevariable. Además, incluir el .valuemétodo causó fallas. La capacidad de interpretar variables de objeto profundamente anidadas es lo que estoy buscando y su método indica una buena dirección. Gracias.
Theo
No hay problema. La respuesta es más para demostrar el concepto en lugar de ser una respuesta de copiar / pegar (como la mayoría de las respuestas aquí en SO, creo)
1
Las respuestas de SO son aún mejores cuando puede pasar el tiempo mejorándolas en lugar de arreglarlas. ;-)
Theo
No funciona:Uncaught TypeError: Cannot read property 'split' of undefined
Roberto14
5

Puedes hacer asi

var name = "foo";
var value = "Hello foos";
eval("var "+name+" = '"+value+"';");
alert(foo);

Eliyah Sundström
fuente
0

Se puede hacer así

(function(X, Y) {
  
  // X is the local name of the 'class'
  // Doo is default value if param X is empty
  var X = (typeof X == 'string') ? X: 'Doo';
  var Y = (typeof Y == 'string') ? Y: 'doo';
  
  // this refers to the local X defined above
  this[X] = function(doo) {
    // object variable
    this.doo = doo || 'doo it';
  }
  // prototypal inheritance for methods
  // defined by another
  this[X].prototype[Y] = function() {
    return this.doo || 'doo';
  };
  
  // make X global
  window[X] = this[X];
}('Dooa', 'dooa')); // give the names here

// test
doo = new Dooa('abc');
doo2 = new Dooa('def');
console.log(doo.dooa());
console.log(doo2.dooa());

Yunzen
fuente
0

El siguiente código facilita la referencia a cada uno de sus DIV y otros elementos HTML en JavaScript. Este código debe incluirse justo antes de la etiqueta, de modo que se hayan visto todos los elementos HTML. Debería ir seguido de su código JavaScript.

// For each element with an id (example: 'MyDIV') in the body, create a variable
// for easy reference. An example is below.
var D=document;
var id={}; // All ID elements
var els=document.body.getElementsByTagName('*');
for (var i = 0; i < els.length; i++)
    {
    thisid = els[i].id;
    if (!thisid)
        continue;
    val=D.getElementById(thisid);
    id[thisid]=val;
    }

// Usage:
id.MyDIV.innerHTML="hello";
David Spector
fuente
0

déjame aclararlo

function changeStringToVariable(variable, value){
window[variable]=value
}
changeStringToVariable("name", "john doe");
console.log(name);
//this outputs: john doe
let file="newFile";
changeStringToVariable(file, "text file");
console.log(newFile);
//this outputs: text file
Kalidan
fuente
1
¡Bienvenido a Stack Overflow! Si bien este código puede resolver la pregunta, incluir una explicación de cómo y por qué esto resuelve el problema realmente ayudaría a mejorar la calidad de su publicación, y probablemente resultaría en más votos positivos. Recuerde que está respondiendo la pregunta para los lectores en el futuro, no solo la persona que pregunta ahora. Por favor, editar su respuesta para agregar explicaciones y dar una indicación de lo que se aplican limitaciones y supuestos.
Daniil