2009-06-17 19 views
42

Lo que quiero hacer es obtener el NOMBRE de una variable pasada a una función y el VALOR de esa variable y solo tiene que pasar una variable a la función. Por lo tanto:JavaScript: Obtener valor de argumento y NOMBRE de variable pasada

var x = "anything"; 

function showName() { 

} 

showName(x); 

o

showName("x"); 

que devolverá: "x = nada".

En este momento, tengo que hacer:

showName("x", x); 

con el fin de obtener el nombre y el valor de la variable que estoy pasando en la nota que no estoy interesado en el nombre del argumento en el prototipo de. showName, pero el nombre de la variable en la función de llamada. Además, la variable puede ser local, por lo que no puedo usar el objeto ventana para encontrar la variable.

+0

http://stackoverflow.com/questions/1007981/how-to-get-function-parameter-names-values-dynamically-from-javascript y http://stackoverflow.com/questions/914968/inspect- the-names-values-of-arguments-in-the-definition-execution-of-a-javascript –

+0

@Paulo - la dirección de esos enlaces obtiene los nombres de los parámetros definidos en la firma de la función. Esta pregunta se trata de obtener el nombre y el valor de la variable que se pasa a la función. – RedFilter

Respuesta

6
var x = "anything"; 

function showName(s) { 
    alert(s + " = " + eval(s)); 
} 

showName("x"); 

No se recomienda, pero ahí está.

+1

¿Qué pasa con x = 1; showName (x)? – BaroqueBobcat

+0

@BaroqueBobcat - la función anterior funciona bien para mí. Si está buscando casos extremos, la función puede modificarse fácilmente para codificar los datos de diferentes maneras en función del tipo o valor. Por ejemplo, una matriz vacía y una cadena vacía se muestran como vacías. Es posible que desee manejar esto de manera diferente, o agregar información adicional acerca de una mejor suposición sobre el tipo. El objetivo del ejemplo no es ser a prueba de balas, sino demostrar que una función puede obtener tanto el nombre del parámetro como el valor de un parámetro escalar. – RedFilter

52

La respuesta corta es que no se puede.

Cuanto más larga y mala es la respuesta, más difícil es con algo realmente desagradable. Y solo funciona cuando se llama desde otra función.

hay dos atributos interesantes disponibles que podrían ayudar

arguments.callee persona que llama

para fn para hacer algo como esto:

(function(){ 
    var showMe = function(s){ 
    alert(arguments.callee.caller.toString().match(/showMe\((\S)\)/)[1] + 
    ' = '+ s) 
    } 
    x = 1 
    showMe(x) 
})() 

Lo arguments.callee.caller. toString(). match (..) [1] hace es buscar el showMe que se llama en la función que lo llama y lo imprime y su valor.

Pero esto todavía es bastante limitado porque solo llegará a la primera llamada de showMe (x). Entonces, si hay dos llamadas a él, no funcionará.

Pero fue divertido jugar con estas cosas arcanas.

+45

+1, repugnante y fascinante. –

+0

Esto generará un error en Firefox y Safari cuando 'invocador' es' nulo' – user1596138

+0

@Jhawins verdadero. Probablemente haya una forma bastante estrafalaria de que puedas obtener una referencia a la cadena de la fuente de alguna manera. – BaroqueBobcat

1
No

seguro de que puede directamente obtiene lo que quiere de JavaScript, ya que el nombre de la variable no se realiza en torno al valor al que hace referencia (pensar en los nombres de variables como identificadores sólo el compilador reconoce; pero que son arrojados lejos en tiempo de ejecución).

Usted puede , sin embargo, hacer algo un poco diferente que permite el paso de argumentos en torno nombre.Crear un objeto anónimo y pasar eso a su función:

function showNames(o) 
{ 
    for(var ix in o) 
    { 
     alert(ix + ":" + o[ix]); 
    } 
} 

var z = { x : "Anything" } 
showNames(z); 
// or 
showNames({ a : "ay", b : "bee", c: "see" }) 

Para la iteración de las propiedades del objeto, tiendo a preferir un estilo funcional, como en:

Array.iteri = function(o, f) 
{ 
    for(var i in o) { f(i, o[i]) } 
} 

function showNames(o) 
{ 
    Array.iteri(o, function(i,v) 
    { 
     alert(i + ": " + v) 
    }); 
} 
showNames({ a : "ay", b : "bee", c: "see" }) 
+0

No es del todo cierto, JavaScript no es un lenguaje compilado, no hay "tirando en el tiempo de ejecución" – Ally

+1

@ally - Estaba hablando conceptualmente, pero la mayoría de los motores de JavaScript compilan (o pueden) código intermedio para el rendimiento. AFAIK, solo Chrome compila javascript directamente en lenguaje ensamblador. –

3

Se puede crear un hash y pase que en:

var x = {a: 1,b:2} 
function showVars(y) { 
    for (var z in y) { alert(z + " is " + y[z]); } 
} 
showVars(x); 

Esto no muestra necesariamente el nombre de la variable, pero sí permite pares de valores clave, que pueden ser más al punto de lo que necesita.

4

yo ya sabía que podía pasar en un objeto:

{a:"this is a"} 

donde un es el nombre de la variable, pero realmente desea pasar justo a una variable o el nombre de una variable (una o "a") y deje que la función de alguna manera encuentre el nombre de la variable y su valor.

La razón por la que quiero hacer esto algo extraño es que estoy escribiendo una rutina de impresión de depuración. Si llamo así:

var x = "some string"; 
say(x); 

o

say("x"); 

quiero que imprimir algo como:

X (string) = some string 

puedo encontrar bastante fiable del tipo de una variable pasada, y así que sé cómo imprimirlo, pero realmente quiero tratar de evitar el redundar de tener que llamarlo así:

say("x", x); 

que es lo que tengo que hacer ahora.

Lo que parece casi el trabajo es la respuesta de OrbMan. Claro, eval es evil, pero creo que está bien aquí porque es solo para una utilidad de depuración y no estará en el código publicado. He hecho un poco de rutina de prueba de mi propio uso de esta solución:

var x = "this is x"; 

function say(a) { 
    alert(a + " = " + eval(a)); 

} 

say("x"); 

y funciona pero sólo si x es global. Esto no funciona:

function wrapper() { 

    var x = "this is x"; 
    say("x"); 

} 

Por lo tanto, esta solución está cerca, pero desde que uso casi no hay variables globales, esto no va a funcionar. Maldición, está tan cerca. Lo que creo que necesito es "llamar por nombre" en lugar de "por valor" o "por referencia". Y necesito una función que funcione ya sea que se llame desde otra función o no.

Como he dedicado muchas horas a esto, hacer la pregunta aquí fue un acto de desesperación, tengo que concluir que realmente no hay forma de hacerlo. Shucks.

A todos los que respondieron, gracias por toda su ayuda.

+0

No hay necesidad de sus propias variables globales ni eval, de cómo echar un vistazo a mi respuesta. –

1

El siguiente código es lo mejor que puedes hacer.Desafortunadamente, las variables locales en una función son propiedades del objeto de llamada oculto, por lo que no se puede acceder desde Javascript, como la ventana [a], donde a es una propiedad del objeto ventana.

x = "this is x"; 
var say = function(a) { 
    document.write(a + " = " + window[a]); 
} 
say("x"); 

var wrapper = function() { 
    var x = "this is x"; 
    document.write(x + " = " + eval("x")) 
} 
wrapper() 
2

Esto es lo que uso para la depuración. No hay variables globales, sin eval, sin arguments.callee o arguments.caller:

var Helpers = (function() { 
    // ECMAScript 5 strict mode 
    'use strict'; 

    var Module = {}; 

    Module.debug = function() { 
     var i; 

     for (i = 0; i < arguments.length; i++) { 
      console.log(arguments[i] + ':', this[arguments[i]]); 
     } 
    }; 

    Module.SomeObject = function SomeObject() { 
     this.someMember = 1; 
     this.anotherMember = 'Whatever'; 

     Module.debug.call(this, 'someMember', 'anotherMember'); 

     var privateMember = { 
      name: 'Rip Steakface', 
      battleCry: 'Raaaaaaaaahhhhhhhhhrrrrrrrrrg!' 
     }; 

     Module.debug.call(privateMember, 'name', 'battleCry'); 
    }; 

    return Module; 
}()); 

Para aquellos que se preguntan por qué usted quiere hacer esto, es sólo una manera de conectarse de manera eficiente múltiples variables junto con sus nombres.

Si usted quiere ser capaz de registrar los miembros anidados, como en Module.debug.call(obj, 'hair.fluffiness'), puede modificar la función de este modo:

Module.debug = function() { 
    var i, j, props, tmp; 

    for (i = 0; i < arguments.length; i++) { 
     tmp = this; 
     props = arguments[i].split('.'); 

     for (j = 0; j < props.length; j++) { 
      tmp = tmp[props[j]]; 
     } 

     console.log(arguments[i] + ':', tmp); 
    } 
}; 

Por desgracia, no puedo encontrar ninguna manera de conectarse de manera eficiente múltiples variables privadas que no son miembros de un objeto, por ejemplo var roll = 3, value = 4; Module.debug.call(???);

Cuestiones relacionadas