¿Cómo puedo evitar usar `eval()` en este ejemplo?

Estoy tratando de usar una cadena como referencia a una variable para pasar a una función. Por ejemplo:

var names = ['Peter', 'John'],

var hasName = function(name){
    var params = ['names'];
    return $.inArray(name, eval( params[0] )) === -1;
};

Como evitar eval()?

EDIT:

La cuerda de params[0] viene de un data-qval de una input en mi html. La matriz que contiene los datos reales se puede declarar en cualquier lugar, params[0] es solo una referencia a esa matriz pasada como cadena en data-qval, es un parámetro. Pegué el código de mi plugin aquí.

http://pastebin.mozilla.org/1598528 línea 101.

Ejemplo completo: http://jsfiddle.net/elclanrs/ZsS2D/29/

Actualmente funciona, solo estoy buscando una manera de deshacerme de eval()...

preguntado el 26 de abril de 12 a las 08:04

No funcionará sin él. la cuerda de params[0] viene de un data- en una input -

@elclanrs: Es mucho mejor mostrar el código real, o al menos incluir ese tipo de detalles desde el principio. -

Demasiado código para pegar aquí. Es difícil explicar cuál es mi problema. Quizás eval() solo se necesita en este caso ... Puse un pastie aunque si ayuda. Traté de reducir el problema al mínimo, -

@ elclanrs: Eso suele ser lo mejor. Está bien si es mucho código, simplemente resuma su pregunta al principio y luego muestre el código después (de lo contrario, la gente no lee). -

4 Respuestas

En ese caso particular, solo use names:

var names = ['Peter', 'John'],
var hasName = function(name){
    var params = ['names'];
    return $.inArray(name, names ) === -1;
};

(Véase también la nota a continuación.) (Su edición hace que lo anterior no sea aplicable).

Si está tratando de buscar el names matriz en algún contenedor usando la cadena "names", tendría que tener una referencia al contenedor, por ejemplo:

var obj = {
    names: ['Peter', 'John'
};
var hasName = function(name){
    var params = ['names'];
    return $.inArray(name, obj[params[0]] ) === -1;
};

Sí hay is ningún contenedor que no sea el ámbito variable en el que está haciendo esto, tendrá que usar eval. Pero puede (y generalmente debe) ajustar las cosas para tener un contenedor (como arriba) para poder evitarlo. Tenga en cuenta que si names se declara en el ámbito global, tiene un contenedor (window).

Entonces, para resumir:

  1. If names es un var en el ámbito global (o un implícito global), window[params[0]] le dará una referencia.

  2. If names ya está en algún objeto contenedor, puede usar container[params[0]] para obtener una referencia a él.

  3. If names es un var dentro de una función, no puede acceder a ella usando una cadena de tiempo de ejecución sin eval; idealmente, en lugar de var names = [...];, Utilizar var container = {names: [...]}; y luego puedes usar container[params[0]].


Tenga en cuenta que su función se llama hasName, pero vuelve true cuando la matriz no se tener el nombre y false cuando lo hace probablemente quieras !== -1no, === -1.

Respondido 26 Abr '12, 09:04

Ya veo... Parece que estoy atascado con eval() porque no hay forma de saber dónde y cómo se declarará esta matriz. Depende del usuario que use el complemento. La matriz normalmente contendrá nombres de usuario para excluir para la validación. Los datos pueden provenir de cualquier lugar, no pueden conocer el contenedor... - elclanrs

@elclanrs: Yo cambiaría la API del complemento para que puede saber cuando y como names se define. Haga que el usuario lo pase al complemento como un parámetro de configuración o algo así. Pero si su código está en un archivo de complemento separado y está usando con éxito eval("names"), names es global y puedes usar window["names"] para conseguirlo. La única forma en que podría ser algo más que global sería si su complemento fuera un cierre sobre el alcance en el que names está definido, lo que requeriría que el código de su complemento se entremezcle con el código que lo define. - TJ Crowder

Gracias por tu ayuda de verdad. ¿Cuáles crees que serían las desventajas de mi enfoque con eval? Parece funcionar con cualquier matriz declarada en cualquier ámbito hasta el momento. es decir. var obj = { arr: [1] }; // eval( 'obj.arr' ) will work! - elclanrs

@elclanrs: eval es una herramienta muy grande. Activa un analizador JavaScript y (en la mayoría de los motores) un compilador JIT. Nuevamente, en su caso de uso, window[params[0]] lo haría, pero lo haría fuertemente Recomendamos no obligar a los usuarios de su complemento a crear variables globales para esto. Este es un caso claro en el que deberían pasarle la matriz para verificar. (Por separado, su línea 101 tiene un error: !~$.inArray(params[1] === 'true' siempre será false; está usando igualdad estricta para probar un booleano contra una cadena). - TJ Crowder

!~$.inArray(params[1] === 'true'... funciona bien para mí... no hay errores en la consola ni nada. y window[params[0]] no funcionó Puse un ejemplo de trabajo completo aquí jsfiddle.net/elclanrs/ZsS2D/29. - elclanrs

¿No es esto suficiente?

var hasName = function(name){
    return $.inArray(name, names) > -1;
};

Además, fíjate en la comparación.

Debido a que JavaScript trata a 0 como vagamente igual a falso (es decir, 0 == falso, pero 0 !== falso), si estamos comprobando la presencia de un valor dentro de la matriz, debemos comprobar si no es igual a (o mayor que ) -1.

Respondido 26 Abr '12, 08:04

@ Jakub: No hay necesidad de reemplazar el !== -1 con > -1. La documentación es claro: "El $.inArray() método... devuelve -1 cuando no encuentra una coincidencia". Así que no va a volver, digamos, -2. Usted puede utilizar > -1 (o >= 0) si lo desea, pero no es necesario. - TJ Crowder

Sí, suelo usar !~$.inArray() Solo quería dejarlo claro para todos para que más personas pudieran ayudar: elclanrs

Sí, pero su función escribe en la variable llamada hasName, que tendrá un valor de true cuando el nombre es no fundar. - jakub konecki

@JakubKonecki: Veo lo que quieres decir, tengo que admitir que me lo perdí. === cuando debería ser !==. - TJ Crowder

@elclanrs: Cómo... oblicuo. ¿Realmente no le gustan las personas que tendrán que mantener su código? ;-)- TJ Crowder

¿Cadenas como referencias a variables? Si es un objeto global en un navegador, estará en el objeto de la ventana, por lo que puede hacer window[variableName] para obtener su valor. Lo mismo para los objetos, es decir, en lugar de object.foo, tu puedes hacer object['foo'] or bar = 'foo', object[bar]. Para variables de alcance local, no puede hacerlo sin usar un objeto o eval.

Respondido 26 Abr '12, 09:04

if names es global, puede usar el espacio de nombres global, es decir window

var hasName = function(name,namespace){
    namespace = namespace || window;
    return $.inArray(name, namespace.names) > -1;
};
hasName('Peter'); //=> true;

Esto también puede ser una idea:

var MYNS = { names:['Peter','John']
            ,hasName: function(name){
               return $.inArray(name, this.names) > -1;
             }
           };
 MYNS.hasName('Peter'); //=>true

Respondido 26 Abr '12, 09:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.