2011-07-05 35 views
11

En primer lugar, siento que sea un duplicado, pero cada vez que busqué en Google 'objeto' y 'código' obtuve las páginas de tutoriales.Objeto Javascript Obtiene código como cadena

Quiero saber si hay alguna manera fácil de obtener el código asociado a un objeto. Algo así como

function A(){ 
    this.name = 'Kaiser Sauze'; 
} 
a = new A(); 
console.log(a.displayCode()); 
//OUTPUT 
"function A(){ this.name = 'Kaiser Sauze';}" 

Quiero poder ver el código, modificarlo y volver a cargar la función, todo desde el navegador. Yo quería saber si había alguna manera de hacer esto, o si tengo que cebar la bomba haciendo algo como esto:

function A(){ 
    this.name = 'Kaiser Sauze'; 
    this.code = "function A(){ this.name = 'Kaiser Sauze';}" 
} 

continuación, cada vez que el usuario carga el editor de texto para ver this.code que conecte el onchange para actualizar this.code.

EDITAR

resulta yanqui sugirió una solución simple a este

function A(x){ 
    this.x = x ; 
} 
console.log(A.toString()); 
//OUTPUT 
"function A(x){ 
    this.x = x ; 
}" 

pero en mi aplicación la variable 'x' puede ser una función (en realidad un objeto complicado con variables, funciones y objetos sub el cual mezclo en medio de una llamada a dojo.mixin), por lo que lo que realmente quiero es conocer el código cuando se crea una instancia, algo así como lo que

function A(x){ 
    this.x = x ; 
} 
var a = new A(function(){/*DO SOMETHING*/); 
console.log(a.toString()); 
//OUTPUT 
"var a = new A(function(){/*DO SOMETHING*/);" 

pero, como la mayoría de ustedes ya saben, todo lo que obtiene es algo así como "Objeto". Casi he encontrado una forma de evitar esto, poniendo la inicialización en una función como tal

function A(x){ 
    this.x = x ; 
} 
function _A(){ 
    var a = new A(function(){/*DO SOMETHING*/); 
} 
console.log(_A.toString()); 
//OUTPUT 
"function _A(){ 
    var a = new A(function(){/*DO SOMETHING*/); 
}" 

pero eso es confuso, y luego tengo que entrar y empezar a analizar la cadena, que no quiero hacer.

EDITAR: La razón por la que pregunto todo esto es por b/c. Quiero hacer código que sea dinámicamente ejecutable y altamente modular. Estoy lidiando con el lienzo. Quiero que el usuario pueda hacer clic en, por ejemplo, un rectángulo, ver su código y modificarlo y luego cargarlo/ejecutarlo. Tengo una serie de reglas, pero básicamente tengo una clase de forma y todo lo que define esa forma (color, transparencia, rellenos, trazos ...) debe pasarse como un parámetro al objeto cosntructor, algo así como:

rect = new Shape({color : 'rgba(0,0,0,1)' , 
    x : 0 , 
    y : 0 , 
    w : 100 , 
    h : 100 , 
    draw : function() {ctx.fillStyle = this.color; 
    ctx.fillRect(this.x,this.y,this.w,this.h); 
    } 
}); 

De esta forma el código es automáticamente modular, no tengo que preocuparme por el color que se define en la parte superior de la página, y luego por la altura que se define en la mitad de la página, y así sucesivamente. Ahora, lo único que necesito es, de alguna manera, pasar como parámetro, toda la representación de cadena anterior de la inicialización. Podría envolverlo en una función y llamar a String en eso, como

function wrapper(){ 
    rect = new Shape({color : 'rgba(0,0,0,1)' , 
     x : 0 , 
     y : 0 , 
     w : 100 , 
     h : 100 , 
     draw : function() {ctx.fillStyle = this.color; 
      ctx.fillRect(this.x,this.y,this.w,this.h); 
     }, 
     code : wrapper.toString() 
     }); 
    } 

, pero entonces hay dos problemas. 1) Tengo que eliminar manualmente function wrapper() y posterior }, así como mover cada línea a la izquierda en una pestaña. 2) no hay garantía de que un usuario recuerde incluir la función de envoltura, ya que es totalmente innecesario para fines de dibujo. Estoy tratando de pensar en una forma en que la envoltura parezca natural, pero no puedo pensar en ninguna. Pero, de nuevo, no he dormido en más de 30 horas.

+1

+1 solo para hacer referencia a Kaiser Sauze ...aunque creo que está deletreado Keyser Söze ;-) –

+0

@Jason: Nunca recuerdo cómo se deletrea, así que cuando les doy mi número a las chicas, voy por Rolo Tomasi ;-) – puk

Respuesta

1

No puedo creer que nadie haya sugerido esto (me disculpo si esta respuesta se encuentra entre las líneas). No pensé en eso porque en el momento del desarrollo, todo mi trabajo era cliente. Todo lo que tengo que hacer es cargar el código una vez con Ajax como javascript. Una vez que se carga y se crea un objeto, lo vuelvo a cargar como una cadena y lo asigno a una variable en el objeto.

17

OK ... Revisando nuevamente ... Creo que eso es lo que quieres ;-).

>>> function A() {this.name ="foo";} 
undefined 
>>> A.toString() 
"function A() {this.name ="foo";}" 
+0

Wow, eso es realmente genial . Usualmente cambio Javascript por ser totalmente inferior a Python, pero en este caso, gana. Desafortunadamente no es lo que quiero. Ahora me doy cuenta de que fue una pregunta estúpida que los objetos b/c no tienen representaciones de cuerdas. Reimpletaré todo como clase o buscaré otra forma de hacerlo. Gracias sin embargo. – puk

+0

también podría simplemente poner la inicialización del objeto dentro de una función y luego llamar a la cadena sobre eso. – puk

+0

Supongo que editaré la pregunta para actualizar a todos los interesados. Además, por alguna razón, cuando lo hago AT yankee no aparece. – puk

1
function dumpObject(obj) 
{  
    var output = "";  
    for (var i in obj) 
    {   
     var msg = i + "= " + obj[i];   
     output += msg + "\n";  
    }  
    return output; 
} 

var myObject = { 
    myName: 'Daniel', 

    get_name: function() 
    { 
     return this.myName; 
    } 
} 

alert(dumpObject(myObject)); 
//this will output: 
// 
// myName= Daniel 
// get_name=function() 
// { 
//  return this.myName; 
// } 

Aquí es mi violín para ello: http://jsfiddle.net/DanielDZC/vXrQf/

+0

No creo que sea eso lo que estoy buscando, quiero el código tal como era, no solo las propiedades. – puk

+0

Eso mostrará funciones, propiedades, etc., pero cada una de ellas por separado. puedes ajustarlo para que cada ciclo agregue cosas a una cadena en lugar de alertarlo. de hecho, déjame cambiarlo ... –

+0

Daniel, gracias por el jsfiddle. Definitivamente aclararon las cosas :) – puk

3

Editar: añadido de impresión legible.

Podría JSON.stringify() el argumento del constructor, si es compatible con JSON. Aquí es una función toString() que se basa en esta idea, pero con una versión ligeramente generalizada de JSON.stringify() que acepte funciones stringifying:

function Shape(x){ 
    this.x = x; 
} 
Shape.prototype.toString = function() { 
    function stringify(data, prefix) { 
     function unicode_escape(c) { 
      var s = c.charCodeAt(0).toString(16); 
      while (s.length < 4) s = "0" + s; 
      return "\\u" + s; 
     } 
     if (!prefix) prefix = ""; 
     switch (typeof data) { 
      case "object": // object, array or null 
       if (data == null) return "null"; 
       var i, pieces = [], before, after; 
       var indent = prefix + " "; 
       if (data instanceof Array) { 
        for (i = 0; i < data.length; i++) 
         pieces.push(stringify(data[i], indent)); 
        before = "[\n"; 
        after = "]"; 
       } 
       else { 
        for (i in data) 
         pieces.push(i + ": " + stringify(data[i], indent)); 
        before = "{\n"; 
        after = "}"; 
       } 
       return before + indent 
         + pieces.join(",\n" + indent) 
         + "\n" + prefix + after; 
      case "string": 
       data = data.replace(/\\/g, "\\\\").replace(/"/g, '\\"') 
          .replace(/\n/g, "\\n").replace(/\r/g, "\\r") 
          .replace(/\t/g, "\\t") 
          .replace(/[\x00-\x19]/g, unicode_escape); 
       return '"' + data + '"'; 
      default: 
       return String(data).replace(/\n/g, "\n" + prefix); 
     } 
    } 
    return "new Shape(" + stringify(this.x) + ")"; 
}; 

var rect = new Shape({color : 'rgba(0,0,0,1)' , 
    x : 0 , 
    y : 0 , 
    w : 100 , 
    h : 100 , 
    draw : function() {ctx.fillStyle = this.color; 
    ctx.fillRect(this.x,this.y,this.w,this.h); 
    } 
}); 
console.log(rect.toString()); 

la salida es:

new Shape({ 
    color: "rgba(0,0,0,1)", 
    x: 0, 
    y: 0, 
    w: 100, 
    h: 100, 
    draw: function() { 
     ctx.fillStyle = this.color; 
     ctx.fillRect(this.x, this.y, this.w, this.h); 
    } 
}) 
+0

wow No esperaba tantas respuestas. Quizás debería explicar por qué hice esta pregunta en primer lugar. Editaré de nuevo. – puk

+0

He editado mi pregunta nuevamente. Explico por qué lo necesito y por qué no solo necesito la estructura del objeto, sino también la estructura del código en sí. Por lo tanto, necesito, por razones estéticas, las pestañas, espacios y nuevos caracteres de línea. De lo contrario, el usuario tecleará algo, lo guardará y luego, cuando lo vuelva a abrir, de repente todo el código se aplanará en una sola línea. – puk

+0

. No hay manera de que pueda recuperar los espacios, pestañas y líneas nuevas originales, a menos que el código se guarda como una cadena en primer lugar (que en realidad puede ser la ruta más fácil de seguir). Edité mi respuesta para mejorar la estética de la salida. Sin embargo, este 'toString()' está realineando de nuevo con mi estilo de sangría (cuatro sangría espacial, sin espacio antes de ':' ...), aunque el código fue ingresado originalmente usando su estilo. Obviamente puede editar 'toString()' para adaptarse a su estilo. –

0

Parece que estás en busca de Reflexión y/o soporte de introspección. No estoy seguro de dónde están los otros motores principales a este respecto, pero el Parser API de SpiderMonkey se mencionó recientemente en un artículo en Extension Introspection with Chrome Privileges.

+0

Me resistí a usar analizadores ya que tengo poca o ninguna experiencia con ellos, pero podría tener que comenzar. Otra cosa que estaba pensando era almacenar cada función como un archivo y luego cargarlas en index.html (o por eficiencia unirlas en un único archivo .js cada vez que se altera uno de los archivos secundarios y solo cargar eso en index.html), luego haga que cada objeto generado por ese archivo tenga en cuenta la ruta del archivo. – puk

+0

¿Hay alguna razón por la que mis carteles AT (@) no aparezcan? Ya no puedo responder a usuarios específicos en forma de @ usuario (@usuario). ¿Cambió la sintaxis o cambié accidentalmente mi configuración? Por ejemplo, intenté comenzar mi comentario anterior con '@ psema4' pero no lo veo allí – puk

+0

gracias por el enlace psema4. Usaré esto para las secciones que no son objeto (es decir, clases y scripts completos) – puk

2

Aquí hay otra solución que podría funcionar (usando el ejemplo de yankee). Sin embargo, ¿no estoy seguro de lo que sucede si A ya existe? Tal vez deberías hacer un "eliminar (A);" antes de guardarlo en el almacenamiento.

// Create A 
// function A() {this.name = "foo";} 

var x = 'function A() {this.name = "foo";}'; // Store function to variable using A.toString(); 

// Save x in storage 

// -- Page reload -- 

// Load and eval x from storage 
eval(x); 

var a = new A(); // Use A 
alert(a.name); 
0

yo no recomendaría el uso de un servidor de producción, sólo para probar y depurar, pero there is a method named toSource() que devuelve el origen de una función como una cadena:

function add(a, b) { 
    return a + b; 
} 
console.log(add.toSource()); 

Salidas:

function add(a, b) { return a + b; } 

Disponible en JS Fiddle: http://jsfiddle.net/IQAndreas/dP453/1/

Nota t hat Mozilla ha marcado este método como no estándar (que si read the details significa "Solo funciona en FireFox").

1

Consulte la siguiente fragmento de código:

function A() { 
 
    this.name = 'Kaiser Sauze'; 
 
} 
 

 
a = new A(); 
 

 
console.log(a.constructor.toString()); 
 

 
// output 
 
// "function A(){ 
 
// this.name = 'Kaiser Sauze'; 
 
// }"

Al hacer new A(), function A se convierte en el constructor del objeto a. Por lo tanto, puede hacer referencia al function A a través de la propiedad constructor del objeto a.

Read more about Javascript constructor on MDN.

Cuestiones relacionadas