Historial de Cambios en el Motor
Clase 4 de 5 • Taller de Secretos Ocultos de JavaScript: Protección de Clases y Objetos
Contenido del curso
Clase 4 de 5 • Taller de Secretos Ocultos de JavaScript: Protección de Clases y Objetos
Juan Castro
Jesus Espinosa
Luis Paredes
Yefri Enmanuel Encarnación Jiménez
Natalia Villegas
luis carlos rojano vergara
Jorge Méndez Ortega
Andrés Schuster
Brandon Lee Aguero Fernandez
David Ochoa
luis carlos rojano vergara
CRISTIAN DARIO AGUDELO PORRAS
Jean Paul Mamani Coaquira
Andres Eduardo Maneiro Antunez
Felipe Moreno
Brandon Lee Aguero Fernandez
Harold Zurita Simon
Josman Jimenez
Daniel Carmona
diego Marcos
Enrique Aguilera
Mauricio Carrasco
Frandel Corporan Rodríguez
Jorge Humberto Nemogá Pinzón
¡Un reto más, Platzinauta! :muscle:
El manejo de la memoria y la copia o comparación de objetos en JavaScript es un tema con varios niveles de complejidad.
Si es tu primera vez enfrentándote a este tipo de problemas, te recomiendo estos materiales:
Wow. Hicieron su hackathon interactivo y trajeron estudiantes al proceso, súper.
listo mi solucion
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { if (status != newStatus) { history.agragarEvento(propulsionTo, newStatus) status = newStatus; } }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.agragarEvento = (direccion, estado) => history.push({"propulsionTo": direccion, "status": estado}) } }
Excelente! Apoyo para que se sigan haciendo este tipo de clases: son entretenidas, pones en practica tus conocimientos y si te falta algo lo repasas o vas y lo aprendes de verdad excelente!
Cuéntanos qué tipo de ejercicios te gustaría ver en la plataforma?
ejercicios tipo hackathon, que obliguen a explorar los conceptos más avanzados del lenguaje.
esto es muy divertido
// Clase Motor export class Motor { // Constructor de la clase `Motor`. constructor(propulsionTo, history) { // Establece una propiedad llamada `propulsionTo` para el objeto `Motor`. this.propulsionTo = propulsionTo; // Establece una propiedad llamada `history` para el objeto `Motor`. this.history = history; // Establece una propiedad llamada `status` para el objeto `Motor`. this.status = "off"; } // Método que cambia el valor de la propiedad `status` del objeto `Motor` a "on" y agrega un objeto de cambio al historial. turnOn() { this.status = "on"; this.history.addChange(this.propulsionTo, this.status); } // Método que cambia el valor de la propiedad `status` del objeto `Motor` a "off" y agrega un objeto de cambio al historial. turnOff() { this.status = "off"; this.history.addChange(this.propulsionTo, this.status); } } // Clase History export class History { constructor() { // Si la instancia de la clase `History` no existe, crea una nueva y establece una propiedad llamada `history` como un array vacío. if (!History.instance) { History.instance = this; this.history = []; } // Devuelve la instancia existente de la clase `History`. return History.instance; } // Método que agrega un objeto de cambio al historial si el último objeto agregado tiene una propiedad diferente de `propulsionTo` o `status`. addChange(propulsionTo, status) { const lastChange = this.history[this.history.length - 1]; if (!lastChange || lastChange.propulsionTo !== propulsionTo || lastChange.status !== status) { this.history.push({ propulsionTo, status }); } } // Método que devuelve una copia del historial. getFullState() { return this.history.slice(); } }
Gran solución
Spoler . . . . . . . . . . . . . . . . . . . . . . .
Lo hice sencillo, sin ningún tipo de shallow copy o utilizando stringify y parse
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let dir = propulsionTo let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; history.addRecord({propulsionTo:dir, status:status}) }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.addRecord = (record) => { const lastRecord = history[history.length - 1] if (!lastRecord) { history.push(record) console.log("First added") return } const isSamePropulsion = lastRecord.propulsionTo == record.propulsionTo const isSameStatus = lastRecord.status == record.status if (isSamePropulsion && isSameStatus) { console.log("Not added") return } history.push(record) console.log("Added") } } }
Propuesta de solución utilizando JSON.stringify y JSON.parse, para realizar un deep copy, en vez de referenciar a los objetos directamente. Esto permite guardar nuevos objetos en el historial, sin apuntar a los objetos originales.
export class Motor { constructor(propulsionTo, historyInstance) { this.status = "off" this.propulsionTo = propulsionTo; let history = historyInstance; this.getStatus = () => this.status; let setStatus = (newStatus) => { history.addStatus(this, newStatus); this.status = newStatus; }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { this.history = []; this.lastMotor = {} this.addStatus = (motor, status) => { if (Object.is(motor, this.lastMotor) && motor.status === status) { console.log("same as last motor") } else { motor.status = status const newMotor = JSON.parse(JSON.stringify(motor)); this.history.push(newMotor) this.lastMotor = motor; } } this.getFullState = () => this. History; } }
Comparto mi solucion, es realmente satisfactorio lograrlo con tus propios conocimientos. . . . . . . . . . . . . . . . . . . .
class Motor { constructor(propulsionTo, historyInstance) { let status = "" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { if(status !== newStatus){ status = newStatus; mensajeEstadoMotor(propulsionTo, newStatus); } }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); let setHistory = (mensaje) => { history.setFullState(mensaje); }; let mensajeEstadoMotor = (motorName, MotorStatus) => { const mensaje = { "propulsionTo": motorName, "status": MotorStatus, } setHistory(mensaje); }; } } class History { constructor() { let history = []; this.getFullState = () => history; this.setFullState = (mensaje) => { history.push(mensaje) } } }
'
" "" " " " "" " " " " " "
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus history.addRecord(newStatus, propulsionTo) }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => { return history }; this.addRecord = (newStatus, propulsionTo) => { let lastObj = history[history.length - 1] if (lastObj?.propulsionTo === propulsionTo && lastObj?.status === newStatus ) { return false } history.push({ "propulsionTo": propulsionTo, "status": newStatus }) } } }
Spoiler mi Solucion . . . . . . . . . . . . . . . . . . . . . . . .
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; }; this.turnOn = () => { setStatus("on") this.setHistory() }; this.turnOff = () => { setStatus("off") this.setHistory() }; this.setHistory = () => { const lastHistory = history.getFullState() const payload = { propulsionTo: propulsionTo, status: this.getStatus() } const isEqual = JSON.stringify((lastHistory[lastHistory.length - 1])) === JSON.stringify(payload) if (!isEqual) { history.setHistory(payload) } } this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.setHistory = (payload) => { history.push(payload) } } }
Mi solución 👇 . . . . . . . . . . . . . .
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off"; let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; historyInstance.historyEvent = { propulsionTo, status } }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { this.history = []; this.getFullState = () => this.history; } set historyEvent(event) { if (JSON.stringify(this.history.at(-1)) !== JSON.stringify(event)) { this.history.push(event); } } }
Debo decir que tuve problemas con este ejercicio 😕, pero gracias a los aportes logre superarlo 😅.
Solución 😄..
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; }; this.turnOn = () => { setStatus("on"); history.addToHistory(propulsionTo, status); }; this.turnOff = () => { setStatus("off"); history.addToHistory(propulsionTo, status); }; this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.addToHistory = (propulsionTo, status) => { let lastRecord = history[history.length - 1]; let record = { "propulsionTo": propulsionTo, "status": status }; if ( JSON.stringify(record) !== JSON.stringify(lastRecord) ) { history.push(record); } }; } }
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off"; let history = historyInstance; this.getPropulsionTo = () => propulsionTo; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; }; this.turnOn = () => { setStatus("on") history.setFullState({ propulsionTo: this.getPropulsionTo(), status: this.getStatus() }) }; this.turnOff = () => { setStatus("off"); history.setFullState({ propulsionTo: this.getPropulsionTo(), status: this.getStatus() }) } ; this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.setFullState = ({ propulsionTo, status }) => { if (history.length===0||history[history.length-1].propulsionTo!=propulsionTo|| history[history.length-1].status!=status) history.push({ propulsionTo, status }) } } } ```aca mi solucion.
Uff muy buenos pero me hace falta aprender mucho!
:) :) :) :) :) :) :) :) :) :) :) :) :) :) Lo realize con mi propia logica 😅, aunque despues de ver las demas resoluciones, la mia quedo muy grande y engorrosa.
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off"; let fullHistory = []; //validacion de history if (historyInstance instanceof History) { //obteniendo el historial completo fullHistory = historyInstance.getFullState(); } this.getStatus = () => status; function setStatus(newStatus) { //evaluando si el ultimo status es igual al nuevo if ( fullHistory[fullHistory.length - 1]?.propulsionTo !== propulsionTo || fullHistory[fullHistory.length - 1]?.status !== newStatus ) { historyInstance.setHistory({ propulsionTo: propulsionTo, status: newStatus, }); } status = newStatus; } this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { //trabaje con private fields #_history; constructor() { this.#_history = []; this.setHistory = (history) => { this.#_history.push(history); }; this.getFullState = () => this.#_history; } }
. . . . . . . . . . . . . . . . . . . . . .
.
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance; this.getStatus = () => status; let setStatus = (newStatus) => { status = newStatus; historyInstance.add(propulsionTo, status) }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.add = (propulsionTo, status) => { const lastElement = history[history.length - 1] if (lastElement && lastElement.propulsionTo === propulsionTo && lastElement.status === status) return history.push({ propulsionTo, status, }) } } }
Mi solución agregando métodos y validaciones en ambas clases: . . . . . . . . .
export class Motor { constructor(propulsionTo, historyInstance) { let propulsion = propulsionTo; let status = "off"; let history = historyInstance; this.getPropulsion = () => propulsion; this.getStatus = () => status; let setStatus = newStatus => { status = newStatus; }; this.turnOn = () => { if (this.getStatus() !== "on") { setStatus("on"); history.addRecord(this); } }; this.turnOff = () => { if (this.getStatus() !== "off") { setStatus("off"); history.addRecord(this); } }; this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.addRecord = motor => { history.push({ propulsionTo: motor.getPropulsion(), status: motor.getStatus(), }); }; this.getFullState = () => history; } }
Ufff este se me lio mucho mas pero lo consegui, ahora a desenmascarar a ese impostor!!!
export class Motor { constructor(propulsionTo, historyInstance) { let status = "off" let history = historyInstance this.getStatus = () => status; let setStatus = (newStatus) => { if (newStatus !== status) { status = newStatus; history.addStatus({propulsionTo,status}) } }; this.turnOn = () => setStatus("on"); this.turnOff = () => setStatus("off"); this.getHistory = () => history.getFullState(); } } export class History { constructor() { let history = []; this.getFullState = () => history; this.addStatus = (obj) => history.push(obj) } }
Esta es mi solución usando el método structuredClone() en vez de JSON.stringify/parse
También modifique las propiedades y métodos para usarlos como privados o públicos según corresponda.
export class Motor { #STATUS_ON = "on"; #STATUS_OFF = "off"; #id; #status; #history; constructor(id, historyInstance) { this.#id = id; this.#status = this.#STATUS_OFF; this.#history = historyInstance; } getStatus() { return this.#status; } turnOn() { this.#setStatus({ status: this.#STATUS_ON }); this.#saveNewState(); } turnOff() { this.#setStatus({ status: this.#STATUS_OFF }); this.#saveNewState(); } #setStatus({ status }) { this.#status = status; } #saveNewState() { const status = this.getStatus(); const lastState = this.#history.getLastState({ propulsionTo: this.#id, }); if (lastState === undefined || lastState?.status !== status) { this.#history.recordLog({ status, propulsionTo: this.#id }); } // probamos modificar el último state por ser un objeto // if (lastState !== undefined) lastState.status = "ON_FAKE"; } } export class History { #history; constructor() { this.#history = []; } getFullState() { return structuredClone(this.#history); } recordLog({ status, propulsionTo }) { this.#history.push({ status, propulsionTo }); } getLastState({ propulsionTo }) { // structuredClone reeplazaría el JSON.stringify/parse return structuredClone( this.#history.findLast( (state) => state.propulsionTo === propulsionTo ) ); } }