Contenido

Curiosidad en Javascript

11 Mar

+ 21

Esta mañana Jorge Cárdenas me preguntaba si veía algo raro en este código. Y tras mucho buscar y probar no entiendo por que al modificar x[0] modificamos y[0]. ¿Alguna idea? ¿Javascript crea punteros en lugar de instancias de objetos?


var x=new Array('a','b','c');
var y=new Array('d','e','f');

alert( x );     // alert "a,b,c"
alert( y );     // alert "d,e,f"

y=x; // El meollo de la cuestión.

alert( x );     // alert "a,b,c"
alert( y );     // alert "a,b,c"

x[0]='_';

alert( x );     // alert "_,b,c"
alert( y );     // alert "_,b,c"

  • Hola, esto ocurre porque al igual que en java, en javascript se trabaja con la referencia de los objetos, no con su valor.

    cuando tu haces

    y=x;

    no estas diciendo:
    ‘El valor de la variable x, en la posición de memoria 0x0001 se copia en la variable y, en la posición de memoria 0x0002’

    sino que lo que haces es decirle:
    ‘La referencia asignada a la variable y es la misma referencia asignada a la variable x’

    por tanto, cuando modificas x, modificas todas las variables que tienen asignada la misma referencia. No se trata de punteros (en C podriamos hacer aritmetica de punteros, con el valor de la dirección del mismo) pero a este nivel funciona de forma parecida.

    Espero haber resultado de ayuda, un saludo y gracias por tu página que me está resultando muy util.

  • Coincido con Locke, es mas, si haces y[0]=’_’; tambien se modificaria x[0]

  • Esta curioso, entonces quieren decir que al igualar x con y, esta igualdad siempre estara presente

  • jejeje, gracias por postearlo, «soy tú fan!!», «soy tú fan!!»…

    volviendo al tema, jiji, lo que me viene a la cabeza, es que cuanto error-inintencional no habrá en todos los scripts del mundo mundial debido a ésta «pequeña falla»…

    si el mismísimo, el único, el inigua…, ok, ok… Andrés Nieto, no se dió cuenta del error a primera vista, ¿que se espera de todo los demás?… bueno, excusando un poco a andrés, estaría bien señalar que me respondió después de alejarse de los brazos de morfeo [ tal cual doncella, como a eso de las 6:07am ] XD…

    bueno, el caso es de que espero que alguien aporte como copiar «sanamente» un array en javascript,,, osea, sin código adicional, no sé, una función nata…

    de antepie, mil gracias ;)!!

    off-topic :: vieras puesto iim.vxk en vez de jorge cárdenas, google me tiene bien rastreadito así.

  • #4 La verdad es que no me di cuenta, pero ahora que lo veo tampoco lo entiendo… no es muy práctico.

    Osea te quieres hacer una copia de un array para modificarlo y tener el original a salvo… ¿no es posible?

    Se me ocurre que como solución temporal, y que, ojo! no me gusta nada. Se podrían crear los dos arrays a la vez con los mismos datos,… menuda chapuza….

  • Bueno, esto pasa porque cuando nosotros tenemos un arreglo, el valor del arreglo no contiene ningun valor, sino una posicion de memoria.

    Para acceder a los valores reales del arreglo, usamos los subindices [0], [1], etc…

    Al igualar «y» con «x», lo que estas haciendo es asignarle la misma posicion de memoria a las 2 variables, por lo que si modificas una variable, realmente modificaras las 2; esto es algo que javascript heredo de su lenguaje padre C

    Saludos, tienes un blog muy interesante

  • #5, exacto, el código puesto es de ejemplo, pero la cuestión es la misma ::

    – copiar el valor de «x» a «y»
    – mantener a «x» intacto – valor útil –
    – trabajar / modificar con «y»

    … pues sí no?, cualquier «solución» viene siendo chapuza, porque según la lógica de sentido común, al hacer «x=y», se debería estar pasando el valor, no una referencia…

    un lindo parche podría ser ::

    var x=new Array(‘a’,’b’,’c’), k, y=new Array();

    for(k in x) y.push(x[k]);

    no lo he testeado, pero tengo la ligera sensación de que podría pasar lo mismo…

    de antebrazo, muchas gracias a todos por su tiempo 😉

  • #1 y #6, pués si no, tal como nos las olíamos todos, el valor se pasaba por referencia…

    mis respetos para los que crearon el JS y para el lenguaje mismo, pero aveces sólo una cosa pasa por mi mente:: DuMbAsS JaVasCrOPt!¡

  • Es exactamente lo que dice #1. No sé nada de javascript, pero en python es igual:

    >>> x = [‘a’,’b’,’c’]
    >>> y = [‘d’,’e’,’f’]
    >>> x = y
    >>> x.append(‘anieto2k’)
    >>> y
    [‘d’, ‘e’, ‘f’, ‘anieto2k’]

  • A ver que os parece:

    
    Array.prototype.copy = function(nuevo) {
       for (var x=0;x<this .length;x++) nuevo.push(this[x]);
    };
    
    var a = new Array('a','b','c');
    var b = new Array();
    
    alert(a); //a,b,c
    alert(b); // vacio
    
    a.copy(b); // copiamos
    
    alert(a); // a,b,c
    alert(b); // a,b,c
    
    b[0] = '_'; //Reemplazamos
    
    alert(a); // a,b,c
    alert(b); // _,b,c
    
  • bingote!!, éso es lo que buscabamos desde un principio…

    porque!!, porque!!, porque tenemos que hacer «cosas extrañas» para copiar un putísimo lindo array???

    gracias 😉

  • Se llama Paradigma Orientado a Objetos.. 😀

  • Coincido con iim.vkx.. es porque estamos trabajando con objetos.. por mucho que digamos variable (yo el primero) se trata de objetos con un constructor y un destructor. Los valores dentro de la estructura del objeto no deben estar nunca ‘al aire’. A veces se implementa una operación por defecto para la asignación, pero no siempre.

  • Me ha encantado este post.

    Hoy me acostaré con la satisfacción de haber aprendido algo nuevo.


  • var a = [ 1, 2 ];
    var b = [].concat(a);

    Lamentablemente solo nos sirve para arrays unidimensionales 🙁

  • #16 :: jeje, yo también había pensado en el uso de la función concat() de los array-objects, pero no terminaba por convencerme del todo…

  • No me lo puedo creeeer!!! Gracias muchachos!! Me han salvado de otras 9 horas de trabajo infructuoso y rompedero de cabeza. Lo del [].concat() (#16) va perfecto y seguiré trasteando un poco mas lo del prototype.copy que se ve poderoso. Muchas gracias monstruos!

  • me encanta, hace las reflexiones que uno se hace y las contestaciones claras, gracias =)

  • me encontre con este mismo problema, pero encontre otra solucion, aunque la solucion propuesta por aNieto2K es genial… ya existe una funcion para copiar arreglos por valor y no por referencia, usando la funcion slice().
    Ejemplo:

    var a = new Array(‘a’,’b’,’c’);
    var b = new Array();

    document.write(«a : «+a+»»); //a,b,c
    document.write(«b : «+b+»»); // vacio

    b = a.slice() // copiamos

    document.write(«a : «+a+»»); // a,b,c
    document.write(«b : «+b+»»); // a,b,c

    b[0] = ‘_’; //Reemplazamos

    document.write(«a : «+a+»»); // a,b,c
    document.write(«b : «+b+»»); // _,b,c

    saludos

  • De todas formas para arrays multidimensionales tenemos que hacer una chapuza

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.