Clonado de Objectos en Javascript

Como vimos en otro post, Paso por Valor Paso por Referencia, los elementos que no son tipos primitivos, al igualarlos a otros, se pasa la referencia.

var persona1 = {nombre:"Ruben",edad:25};
var persona2 = {nombre:"Ale",edad:20};
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1 = persona2;
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1.nombre = "Pepe";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

 

¿Entonces como hacemos para copiar solamente el valor de un Objecto a otro en Javascript?

Método 1:

var persona1 = {nombre:"Ruben",edad:25};
var persona2 = {nombre:"Ale",edad:20};
console.log("Persona1:",persona1,"\nPersona2:",persona2);

//persona1 = Object.assign({}, persona2); //Copia tal cual el objeto
persona1 = Object.assign({}, persona2, { nombre:"Juan", edad: 40, pelo:"castaño" }); //Copio el objeto y le pongo propiedades personalizadas
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1.nombre = "Pepe";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

 

Método 2:

var persona1 = {nombre:"Ruben",edad:25};
var persona2 = {nombre:"Ale",edad:20};
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1 = {...persona2};
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1.nombre = "Pepe";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

***Solo para el nivel 1 de copia profunda.

 

Objetos mas complejos (Objetos dentro de Objetos):

var redessociales = {facebook:{
                                cuentapersonal:"ruben@facebook.com",
                                cuentaprofesional:"rubenpro@facebook.com"},
                     instagram:"@ruben"}

var persona1 = {nombre:"Ruben",edad:25};

var persona2 = {nombre:"Ale",
                edad:20,
                social:redessociales,
                getEdad:function(){
                      return this.edad;}
                };
console.log("Persona1:",persona1,"\nPersona2:",persona2);

//persona1 = {...persona2}; //Cualquiera de los dos casos
persona1 = Object.assign({},persona2);
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona2.social.facebook.cuentapersonal = "NUEVACUENTA";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

¿Que ha pasado con el objeto redes sociales dentro del objeto Persona1?

¿Un objeto dentro de otro objeto?

Ha cambiado al cambiar Persona2 … Nos ha copiado la referencia!! No nos vale!

 

Método 3:

var redessociales = {facebook:{
                                cuentapersonal:"ruben@facebook.com",
                                cuentaprofesional:"rubenpro@facebook.com"},
                     instagram:"@ruben"}

var persona1 = {nombre:"Ruben",edad:25};

var persona2 = {nombre:"Ale",
                edad:20,
                social:redessociales,
                getEdad:function(){
                      return this.edad;}
                };
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1 = JSON.parse(JSON.stringify(persona2));
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona2.social.facebook.cuentapersonal = "NUEVACUENTA";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

Perfecto… ya nos copia el valor del objeto redessociales dentro de un nuevo objeto y son independientes uno de otro ….

pero…. ¿la función getEdad() donde esta en Persona1?

JSON.parse y JSON.stringify no copia las funciones…. Tampoco nos vale!!!

 

Método 4: Función Recursiva

function deepClone(object){
    var clone = {};
    for ( var key in object){
        var value = object[key];
        if(typeof(value) != 'object'){
            clone[key] = value;
        }
        else{
            clone[key] = deepClone(value);
        }
    }
    return clone;
}

var redessociales = {facebook:{
                                cuentapersonal:"ruben@facebook.com",
                                cuentaprofesional:"rubenpro@facebook.com"},
                     instagram:"@ruben"}

var persona1 = {nombre:"Ruben",edad:25};

var persona2 = {nombre:"Ale",
                edad:20,
                social:redessociales,
                getEdad:function(){
                      return this.edad;}
                };
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona1 = deepClone(persona2);
console.log("Persona1:",persona1,"\nPersona2:",persona2);

persona2.social.facebook.cuentapersonal = "NUEVACUENTA";
console.log("Persona1:",persona1,"\nPersona2:",persona2);

 

 

Ahora si  hemos conseguido lo que buscabamos, crear un objecto totalmente independiente al otro.

 

**Recordamos: ¿Que es un Objeto en Javascript? Un objecto es un conjunto de pares clave/valor. En otros lenguajes lo llamaras diccionario, hash o array asociativo.

 

Explicación Clonado de Objecto de Carlos Blé:

 

Clonado de Arrays en Javascript

Como vimos en otro post, Paso por Valor Paso por Referencia, los elementos que no son tipos primitivos, al igualarlos a otros, se pasa la referencia.

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = equipo2;
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

¿Entonces como hacemos para copiar solamente el valor de un Array a otro en Javascript?

Método 1: Slice()

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = equipo2.slice();
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

Método 2: Creando un nuevo array y concatenando el viejo en el.

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = [].concat(equipo2);
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

Método 3: La nueva forma de ES6 con el operador Spread:

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = [...equipo2];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

Método 4: Con Array.from:

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = Array.from(equipo2);
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

 

Paso por Referencia y Paso por Valor en Javascript

En Javascript si igualamos una variable a un tipo primitivo, se copia el valor, pero si no es un primitivo, copiamos la referencia del valor.

¿Y que pasa si copiamos la referencia en vez del valor? Que ambos objetos apuntan al mismo sitio, y si modificamos uno, el otro tambien se vera afectado.

 

Ejemplo con primitivos:

var persona1 = "Ruben";
var persona2 = "Ale";
console.log("Persona 1:",persona1,"\nPersona2:",persona2);

persona1 = persona2;
console.log("Persona 1:",persona1,"\nPersona2:",persona2);


persona1 = "Pepe";
console.log("Persona 1:",persona1,"\nPersona2:",persona2);

Vemos que en el segundo paso igualamos persona1 a persona2 y en el tercer paso asignamos a persona1 el valor de Pepe.  ¿Que le pasa al persona2? No se modifica…. lo que por lógica esperamos que pase.

 

Ejemplo con tipos no primitivos:

var equipo1 = ["a","b","c"];
var equipo2 = ["d","e","f"];
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1 = equipo2;
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

equipo1[0] = "X";
console.log("Equipo1:",equipo1,"\nEquipo2:",equipo2);

¿Que ha pasado? …Hacemos lo mismo que antes, pero ahora se modifican ambos arrays…. ¿por qué?…¡Porque se nos ha copiado la referencia no el valor!

¿Que es un Objeto en Javascript?

Es un conjunto de pares clave/valor. En otros lenguajes lo llamaras diccionario, hash o array asociativo. Puedes usar cualquier numero de claves con un nombre dado, siempre que sea un string, y cada string estara asociado con un valor. Estos valores pueden ser de cualquier tipo, tanto primitivos como functions u otros objetos.

 

Algo importante sobre los objetos es que, si bien los primitivos se pasan por valor, los objetos se pasan por referencia.

 

Primitivos se pasan por valor. Si copiamos una variable primitiva dentro de otra, copiamos el valor solamente, no están unidas por ningún sitio. Podemos cambiar ambas independientemente de la otra.

 

Objetos se pasan por referencia. No estamos copiando el objeto, sigue habiendo un solo objeto, lo que estamos copiando es la referencia, el puntero, el cursor… Si modificamos uno, el otro también lo hará.

 

 

 

 

 

 

 

Métodos de Arrays en Javascript

sort(): ordena los elementos de un array localmente y devuelve el array. Si se omite la funcion dentro del sort,  el array es ordenado atendiendo a la posición del valor Unicode de cada carácter, según la conversión a string de cada elemento.

var puntos = [1, 10, 2, 21]; 
puntos.sort(); // [1, 10, 2, 21]
// Tenga en cuenta que 10 viene antes que 2
// porque '10' viene antes que '2' según la posición del valor Unicode.

Con la compareFunction:

var arr = [ 40, 1, 5, 200 ];
arr.sort((a,b)=>a-b);  // [ 1, 5, 40, 200 ]
var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic' },
  { name: 'Zeros', value: 37 }
];
items.sort(function (a, b) {
  if (a.name > b.name) {
    return 1;
  }
  if (a.name < b.name) {
    return -1;
  }
  // a must be equal to b
  return 0;
});

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/sort

 

reduce(): El método reduce() aplica una función a un acumulador y a cada valor de un array (de izquierda a derecha) para reducirlo a un único valor.

[0,1,2,3,4].reduce(function(valorAnterior, valorActual, indice, vector){
  return valorAnterior + valorActual;
}, 10); //El 10 es el valor inicial

// Primera llamada
valorAnterior = 10, valorActual = 0, indice = 0

// Segunda llamada
valorAnterior = 10, valorActual = 1, indice = 1

// Tercera llamada
valorAnterior = 11, valorActual = 2, indice = 2

// Cuarta llamada
valorAnterior = 13, valorActual = 3, indice = 3

// Quinta llamada
valorAnterior = 16, valorActual = 4, indice = 4

// el array sobre el que se llama a reduce siempre es el objeto [0,1,2,3,4] 

// Valor Devuelto: 20

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/reduce

 

some():  verifica si algún elemento de un array cumple con el test implementado por la función brindada.

function isBiggerThan10(element, index, array) {
  return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10);  // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true


[2, 5, 8, 1, 4].some(elem => elem > 10);  // false
[12, 5, 8, 1, 4].some(elem => elem > 10); // true

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/some

 

every(): verifica si todos los elementos en el arreglo pasan la prueba implementada por la función dada.

function esSuficientementeGrande(elemento, indice, arrreglo) {
  return elemento >= 10;
}
[12, 5, 8, 130, 44].every(esSuficientementeGrande);   // false
[12, 54, 18, 130, 44].every(esSuficientementeGrande); // true


[12, 5, 8, 130, 44].every(elem => elem >= 10); // false
[12, 54, 18, 130, 44].every(elem => elem >= 10); // true

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/every

 

find():  devuelve el valor del primer elemento del array que cumple la función de prueba proporcionada. En cualquier otro caso se devuelve undefined.

var array1 = [5, 12, 8, 130, 44];

var found = array1.find(function(element) {
  return element > 10;
});

console.log(found);
// expected output: 12

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/find

 

findIndex(): devuelve el índice del primer elemento de un array que cumpla con la función de prueba proporcionada. En caso contrario devuelve -1.

var array1 = [5, 12, 8, 130, 44];

function findFirstLargeNumber(element) {
  return element > 13;
}

console.log(array1.findIndex(findFirstLargeNumber));
// expected output: 3

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/findIndex

 

splice(): cambia el contenido de un array eliminando elementos existentes y/o agregando nuevos elementos.

array.splice(indiceDondeEmpezar,elementosAEliminar,elementosAInsertar);


//Eliminar 0 elementos desde el índice 2 e insertar "drum"
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2, 0, 'drum');

// myFish is ["angel", "clown", "drum", "mandarin", "sturgeon"] 
// removed is [], no elements removed


//------------------

//Eliminar 1 elemento desde el índice 3
var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
var removed = myFish.splice(3, 1);

// removed is ["mandarin"]
// myFish is ["angel", "clown", "drum", "sturgeon"]


//-----------------

//Eliminar 1 elemento desde el índice 2 e insertar "trumpet"
var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, 'trumpet');

// myFish is ["angel", "clown", "trumpet", "sturgeon"]
// removed is ["drum"]


https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array/splice

 

Diferencias entre == y === en Javascript

===   y    !===

Son operadores de comparación ESTRICTA. Significa que si los operandos tienen TIPOS DIFERENTES,  no son iguales.

l1==="1" // false
1!=="1" // true
null === undefined // false

 

==   y    !==

Son operadores de comparación RELAJADA. Significa que si los operandos tienen TIPOS DIFERENTES,  Javascript trata de convertirlos para que fueran comparables.

1=="1" // true
1!="1" // false
null == undefined // true

 

null === undefined // false
null == undefined // true

null === false // false
null == false //false

Detalles del operador ==

La comparación x == y, donde x e y son valores, regresa true o false. Esta comparación se realiza de la siguiente manera:

  1. Si Type(x) y Type(y) son los mismos,
    1. Si Type(x) es Undefined, regresa true.
    2. Si Type(x) es Null, regresa true.
    3. Si Type(x) es Number,
      1. Si x es NaN, regresa false.
      2. Si y es NaN, regresa false.
      3. Si x es el mismo valor de Number que y, regresa true.
      4. Si x es +0 e y es −0, regresa true.
      5. Si x es -0 e y es +0, regresa true.
      6. Regresa false.
    4. Si Type(x) es String, regresa true si x e y son exactamente la misma secuencia de caracteres (con la misma longitud y los mismos caracteres en las posiciones correspondientes). En el caso contrario, regresa false.
    5. Si Type(x) es Boolean, regresa true, si x e y ambos son true o ambos son false. En el caso contrario, regresa false.
    6. Regresa true si x e y refieren al mismo objeto. En el caso contrario, regresa false.
  2. Si x es null e y es undefined, regresa true.
  3. Si x es undefined e y es null, regresa true.
  4. Si Type(x) es Number y Type(y) es String,
    regresa el resultado de la comparación x == ToNumber(y).
  5. Si Type(x) es String y Type(y) es Number,
    regresa el resultado de la comparación ToNumber(x) == y.
  6. Si Type(x) es Boolean, regresa el resultado de la comparación ToNumber(x) == y.
  7. Si Type(y) es Boolean, regresa el resultado de la comparación x == ToNumber(y).
  8. Si Type(x) es String o Number, y Type(y) es Object,
    regresa el resultado de la comparación x == ToPrimitive(y).
  9. Si Type(x) es Object y Type(y) es String o Number,
    regresa el resultado de la comparación ToPrimitive(x) == y.
  10. Regresa false.

 

https://es.stackoverflow.com/questions/331/diferencias-entre-y-comparaciones-en-javascript