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!

Esp8266 con Tira Led WS2812B

Diferencias entre tiras led RGB Multicolor y tiras led SMART(Inteligentes, Direccionables, Digitales, Neopixel…)

 

Con las tiras led RGB controlamos el color de toda la tira a la vez. Si cambiamos el color, cambiara el de toda la tira a la vez.

Con las tiras Direccionables controlamos led por led de la tira independientemente.

Existen varios tipos dentro de los Neopixel: WS2801, WS2811, WS2812B,  WS2813… cada uno con sus particularidades respecto al otro.

 

Componentes Necesarios:

TOTAL: +/-  13€

 

 

 

Controlador

Nos ayudaremos de la libreria de Neopixel de Adafruit.

En Platformio la libreria es la nº28.

Y usaremos su código de ejemplo (tendremos que cambiar solamente el pin de control que pongamos (PIN), y el numero de leds a controlar (NUMPIXELS):

// NeoPixel Ring simple sketch (c) 2013 Shae Erisson
// released under the GPLv3 license to match the rest of the AdaFruit NeoPixel library

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
  #include <avr/power.h>
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1
#define PIN            6

// How many NeoPixels are attached to the Arduino?
#define NUMPIXELS      16

// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
// example for more information on possible values.
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);

int delayval = 500; // delay for half a second

void setup() {
  // This is for Trinket 5V 16MHz, you can remove these three lines if you are not using a Trinket
#if defined (__AVR_ATtiny85__)
  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);
#endif
  // End of trinket special code

  pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {

  // For a set of NeoPixels the first NeoPixel is 0, second is 1, all the way up to the count of pixels minus one.

  for(int i=0;i<NUMPIXELS;i++){

    // pixels.Color takes RGB values, from 0,0,0 up to 255,255,255
    pixels.setPixelColor(i, pixels.Color(0,150,0)); // Moderately bright green color.

    pixels.show(); // This sends the updated pixel color to the hardware.

    delay(delayval); // Delay for a period of time (in milliseconds).

  }
}

 

Efecto Arcoiris:

#include <Adafruit_NeoPixel.h>

// constants won't change. They're used here to
// set pin numbers:
const int ledPin = 4;     // the number of the neopixel strip
const int numLeds = 30;

//Adafruit_NeoPixel pixels = Adafruit_NeoPixel(8, ledPin);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(numLeds, ledPin, NEO_GRB + NEO_KHZ800);


// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
    return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  }
  else if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  else {
    WheelPos -= 170;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

void rainbow(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256; j++) {
    for(i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel((i*1+j) & 255));
    }
    strip.show();
    delay(wait);
  }
}





void setup() {
  strip.begin();
  strip.setBrightness(80); // 1/3 brightness

}

void loop() {
  rainbow(30);
  delay(10);
}

 

Instalación de Tiras Led RGB  no direccionable en escritorio:

Prueba de Tira Led Direccionable:

Enlaces

Como alimentar el Nodemcu –> http://henrysbench.capnfatz.com/henrys-bench/arduino-projects-tips-and-more/powering-the-esp-12e-nodemcu-development-board/

http://novalight.com.mx/seleccion-y-diferencias-tipos-tira-led/

https://www.hackster.io/remnis/controlling-neopixels-with-a-webserver-on-an-esp8266-0381c7

¿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á.