2012-05-02 16 views
8

Tengo un comportamiento extraño (tal vez no es extraño en absoluto, pero no entiendo por qué) con una matriz de JavaScript que contiene algunos objetos.matriz de Javascript se convierte en una estructura de objeto

Como no soy javascript pro, podría haber una explicación clara de por qué sucede esto, simplemente no lo sé.

Tengo javascript que se ejecuta en un documento. Se hace una matriz de objetos similar a esto:

var myArray = [{"Id":"guid1","Name":"name1"},{"Id":"guid2","Name":"name2"},...]; 

Si imprimo esta matriz en el lugar que fue creado como JSON.stringify (myArray), que consiga lo que esperaba:

[{"Id":"guid1","Name":"name1"},{"Id":"guid2","Name":"name2"},...] 

Sin embargo, si intento acceder a esta matriz desde un documento secundario a este documento (un documento en una ventana abierta por el primer documento), la matriz ya no es una matriz. al hacerlo JSON.stringify (parent.opener.myArray) en el documento niño tendrá como resultado lo siguiente:

{"0":{"Id":"guid1","Name":"name1"},"1":{"Id":"guid2","Name":"name2"},...} 

Y esto no era lo que esperaba - me esperaba conseguir lo mismo que hice en el documento principal

¿Alguien me puede explicar por qué sucede esto y cómo solucionarlo para que la matriz siga siendo una matriz cuando se dirige desde una ventana/documento hijo?

PS. los objetos no se añaden a la matriz como se ha indicado anteriormente, se añaden como esto:

function objTemp() 
{ 
    this.Id = ''; 
    this.Name = ''; 
}; 

var myArray = []; 

var obj = new ObjTemp(); 
obj.Id = 'guid1'; 
obj.Name = 'name1'; 

myArray[myArray.length] = obj; 

Si hay alguna diferencia.

Cualquier ayuda sería muy apreciada, tanto para la fijación de mi problema, sino también para comprender mejor lo que está pasando :)

+0

No me puedo reproducir. ¿En qué navegador lo has probado? ¿Usaste una biblioteca JSON? – Bergi

+0

Estoy probando en IE porque es un requisito. Personalmente, no escogería IE pero no depende de mí. Solo estoy usando json en este ejemplo para codificar mi alerta. No estoy usando ninguna biblioteca json para el código que produce el comportamiento. – Aidal

+0

Hola, gracias por la aceptación. Me alegra saber que mi solución resultó útil. Happy coding :) + 1 para tu pregunta BTW. Aprendí de él, también –

Respuesta

6

La última línea podría estar causando el problema, ¿ha intentado reemplazar myArray[myArray.length] = obj; con myArray.push(obj);? Podría ser que, dado que estás creando un nuevo índice explícitamente, la matriz se convierta en un objeto ... aunque estoy adivinando aquí. ¿Podría agregar el código utilizado por el documento secundario que recupera myArray?

Editar

ignorar el anterior, ya que no hará ninguna diferencia. Sin embargo, sin querer alardear, estaba pensando en la línea correcta. Mi idea era que, al usar únicamente métodos de matriz patentados, el intérprete vería eso como pistas sobre el tipo de myArray. La cosa es: myArrayes una matriz, por lo que se refiere al documento de nivel superior, pero ya que estás pasando la matriz a partir de un documento a otro, esto es lo que sucede:

Una matriz es un objeto, con es su propio prototipo y métodos. Pasándolo a otro documento, está pasando todo el objeto Array (valor y prototipo) como un objeto al documento secundario. Al pasar la variable entre documentos, está creando efectivamente una copia de la variable (la única vez que JavaScript copia los valores de una var). Como una matriz es un objeto, todas sus propiedades (y los métodos/propiedades de prototipo) se copian en una instancia 'anónima' del objeto Object. Algo en el sentido de var copy = new Object(toCopy.constructor(toCopy.valueOf())); está sucediendo ...la forma más fácil alrededor de esto, la OMI, es la rigurosidad de la matriz withing el contexto de los padres, ya que, el intérprete sabe que es una matriz:

//parent document 
function getTheArray(){ return JSON.stringify(myArray);} 
//child document: 
myArray = JSON.parse(parent.getTheArray()); 

En este ejemplo, el var se Stringified en el contexto que sigue tratando a myArray como una verdadera matriz de JavaScript, por lo que la cadena resultante será lo que esperas. Al pasar la cadena codificada JSON de un documento a otro, no se modificará y, por lo tanto, el JSON.parse() le dará una copia exacta de la variable myArray.

Tenga en cuenta que esto es solo otra puñalada salvaje en la oscuridad, pero ahora lo he pensado un poco más. Si me equivoco sobre esto, siéntete libre de corregirme ... Siempre estoy feliz de aprender. Si esto resulta ser cierto, hágamelo saber también, ya que esto, sin duda, probará una trampa para mí tarde o temprano

+0

No, esa sintaxis es perfectamente válida para crear un nuevo miembro de una matriz. Aunque .push() es más descriptivo (y me gusta más), la tarea también funciona e incluso es un poco más rápida. – Bergi

+0

No creo que la matriz no sea válida debido a la forma en que agrego elementos, como también dije en la publicación, si intento alertar a la matriz con cadenas, parece correcta (también conocido como no es un objeto, sino una matriz) . Si hago exactamente lo mismo desde el documento secundario, la matriz ahora es un objeto, no solo si alerté a la var en forma de cadena, sino que el código que se suponía que funcionaba con la matriz arrojaba un error porque, por ejemplo, myArray [0] .Id es nulo (porque no existe de causa). – Aidal

+0

Stringify la matriz en la página principal y luego analizar la cadena en la página secundaria hizo el truco, y gracias por la respuesta bastante completa, aprendí algo también :) – Aidal

1

Consulte el final de este artículo http://www.karmagination.com/blog/2009/07/29/javascript-kung-fu-object-array-and-literals/ para ver un ejemplo de este comportamiento y explicación.

Básicamente se trata de que Array sea un tipo nativo y cada cuadro tenga su propio conjunto de nativos y variables.

Desde el artículo:

// in parent window 
var a = []; 
var b = {}; 
//inside the iframe 
console.log(parent.window.a); // returns array 
console.log(parent.window.b); // returns object 

alert(parent.window.a instanceof Array); // false 
alert(parent.window.b instanceof Object); // false 
alert(parent.window.a.constructor === Array); // false 
alert(parent.window.b.constructor === Object); // false 

Su llamada a JSON.stringify realmente ejecuta la siguiente comprobación (de la fuente json.js), que parece estar fallando para especificar como una matriz:

 // Is the value an array? 
     if (Object.prototype.toString.apply(value) === '[object Array]') { 
      //stringify 
+1

Na, parece exactamente no usar Array.isArray, que funcionaría en una ventana cruzada, sino que usaría instanceof para causar el comportamiento descrito. – Bergi

+0

Oh, sí, parece que es específico del navegador ahora, ya que json2.js se limita a ejecutar la versión nativa del navegador de stringify si hay uno disponible (y debería estar en todos los navegadores modernos) – nvuono

+0

Me refiero al código 'Object.prototype.toString .apply (value) === '[object Array]' 'would * not * fail, a pesar de que así lo diga. – Bergi

Cuestiones relacionadas