Recursos
- 📺 Project Code Rush - The Beginnings of Netscape / Mozilla Documentary
- 📺 Download:The True Story of the Internet: La Guerra de los Navegadores Subtitulada
- Browser Wars: La historia de la guerra de navegadores y la historia de los userAgents
- Wikipedia | Guerra de navegadores
- PC Mag | Browsers: A Brief History
- The Telegraph | Web browsers: a brief history
- A Brief History of Web Browsers and How They Work
- Wikipedia | History of the web browser
Browser Engine
- Activos
- Discontinuados
El Motor JavaScript (JavaScript Engine)
- V8 Engine de Google
- Chakra de Microsoft
- SpiderMonkey de Mozilla
- JavaScriptCore de Apple
- Carakan de Opera (Inactivo)
- Comparativa de Motores
Recursos
Recursos
- How JavaScript works in browser and node?
- HTML5 Rocks! | How Browsers Work: Behind the scenes of modern web browsers
- Philip Roberts: What the heck is the event loop anyway? | JSConf EU
- Behind the scenes of modern web browsers
- Does JavaScript use stack or heap for memory allocation or both?
- How JavaScript works: the rendering engine and tips to optimize its performance
- An overview of the engine, the runtime, and the call stack
- Inside Google’s V8 engine + 5 tips on how to write optimized code
- Memory management + how to handle 4 common memory leaks
- The event loop and the rise of Async programming + 5 ways to better coding with async/await
Recursos
- 📺 Douglas Crockford: The JavaScript Programming Language
- 📺 The Post JavaScript Apocalypse - Douglas Crockford
- 📺 dotJS 2012 - Brian Leroux - WTFJS
- 📺 What the... JavaScript?
// Classic
(function(){})();
// Crockford's favorite
(function(){}());
// Unary versions
+function(){}();
// Facebook version
!function(){}();
// Crazy version
!1%-+~function(){}();
Recursos
- La gestión de argumentos es muy pocos restrictiva
- EL úmero de argumentos es variable, por defecto su valor es siempre
undefined
arguments
no es un array y tendremos que manejarlo con cuidado o convertirlo usandoprototype
function func(arg1, arg2, arg3) {
console.log("arg1:", arg1)
console.log("arg2:", arg2)
console.log("arg3:", arg3)
console.log("Arguments:" arguments)
console.log("Arguments eres una Array?", Array.isArray(arguments))
}
func(2); //arg1: 2
//arg2: undefined
//arg3: undefined
Recursos
function func() {}
var func = function (){}
var obj = {
func(){}
}
var func = new Function('arg1', 'arg2', 'console.log(arg1, arg2)');
function func() {console.log("Soy una función", typeof(func))}
func.metodo = function() {console.log("Soy un método", typeof(func.metodo))}
func.propiedad = "Dato almacenado..."
console.log("Tengo propiedades", typeof(func.propiedad)) //Tengo propiedades string
func.metodo() //Soy un método function
func() //Soy una función function
function funcAsincrona (dato, callback) {
return callback(dato+5);
}
funcAsincrona(5, data => console.log) //10
function funcEspecial () {
console.log("Una sola vez...")
return function () {
console.log("Muchas veces...")
}
}
var nuevaFunc = funcEspecial(); //Una sola vez...
nuevaFunc(); //Muchas veces...
nuevaFunc(); //Muchas veces...
Recursos
Partes
- Caso base: es el caso más simple y determina la salida de la función
- Caso recursivo: vamos reduciendo la causistica y llamando a la propia función
Ejemplo
// Sin recursión
let counter = 100;
while(counter > 0) {
console.log(counter--);
}
// Con recursión
const cuentaAtras = function(value) {
if (value > 0) {
console.log("Valor actual:", value);
cuentaAtras(value - 1);
} else {
console.log("Fin de la historia:", value);
}
};
cuentaAtras(100);
Recursos
- Recursion in Functional JavaScript
- JS-Challenges/recursion-prompts
- Understanding Recursion in JavaScript
- Recursion in JavaScript
- Learn and Understand Recursion in JavaScript
- Stackoverflow | Calling a javascript function recursively
- Programming with JS: Recursion
- ¿Qué es la recursividad o recursión? - Un ejemplo con JavaScript
- Understanding Recursion in JavaScript with Confidence
Global
const global = "Dato global";
function func() {
console.log(global);
}
func(); // Dato global
Local clásico
function func() {
const local = 5;
}
console.log(local); // undefined.
Local con ES6
- Usando
var
el scope se define por la función donde se declaró,function-level scope
- Usando
let
yconst
el scope también se define enif
,while
,for
oswitch
,block-level scope
.
var uno = 1;
var diez = 10;
if (uno === 1) {
let uno = 3; // El alcance es dentro del bloque if
var diez = 5; // El alcance es dentro de la función
console.log(uno); // 3
console.log(diez); // 5
}
console.log(uno); // 1
console.log(diez); // 5
Un closure o clausura es la combinación de una función y el ámbito léxico en el que se declaró dicha función. Es decir los closures o clausuras son funciones que manejan variables independientes. En otras palabras, la función definida en el closure "recuerda" el ámbito en el que se ha creado. MDN
Claves
- Simplemente: la función definida en el closure "recuerda" el ámbito en el que se ha creado
- En resumen nos permite encapsular código pero con acceso a su contexto
- Todo ese contexto que recuerda ataca a la memoria RAM
- No debemos abusar de este hack por temas de rendimiento
- Es muy útil para emular métodos privados entre otras cosas
Ejemplo clásico
function creaSumador(x) {
return function(y) {
return x + y;
};
}
var suma5 = creaSumador(5);
var suma10 = creaSumador(10);
console.log(suma5(2)); // muestra 7
console.log(suma10(2)); // muestra 12
Ejemplo aplicado
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}
var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
Recursos
- JavaScript Closures Demystified
- MDN | Closures
- JavaScript Closure y su funcionamiento
- Stackoverflow | How do JavaScript closures work?
- Understand JavaScript Closures With Ease
- Understanding JavaScript Closures: A Practical Approach
- Understanding JavaScript: Closures
- Understanding JavaScript Closures
- Closures en JavaScript (ES5)
- JavaScript. ¿Para qué sirven los closures?
- Closures in Javascript for beginners
- CSS-Tricks | JavaScript Scope and Closures
- Entendiendo closures en JavaScript
- I never understood JavaScript closures
- Definiendo conceptos: Closure y Scope en JavaScript
- Antes de ejecutar el código, las variables se mueven al inicio del contexto de ejecución
- Declarar una variable en cualquier parte es lo mismo que declararla al inicio
- Las variables pueden usarse antes de ser declaradas
//ES5
(function () {
if(true) {
var ifScope = "data"
}
for(var forScope = 0; forScope < 3; forScope += 1) {
console.log(forScope);
}
console.log("forScope ?", forScope); // 3
console.log("ifScope ?", ifScope); // data
}());
// ES6
(function () {
if(true) {
let ifScope = "data"
}
for(let forScope = 0; forScope < 3; forScope += 1) {
console.log(forScope);
}
console.log("forScope ?", forScope); // Uncaught ReferenceError: forScope is not defined
console.log("ifScope ?", ifScope); // Uncaught ReferenceError: ifScope is not defined
}());
console.log("fn1", fn1()); // Uncaught TypeError: fn1 is not a function
console.log("fn2", fn2()); // 2
//function expression
var fn1 = function() { return 1; };
//function declaration
function fn2() { return 2; }
console.log("fn1", fn1()); // 1
console.log("fn2", fn2()); // 2
Recursos
- Understanding Hoisting in JavaScript
- Bitácora del desarrollador: Hoisting en JavaScript
- JavaScript Scoping and Hoisting
- JavaScript Hoisting Explained
- Diferencia entre let y var en ES6 y TypeScript
La programación defensiva (defensive programming en inglés) es una forma de diseño defensivo aplicada al diseño de software que busca garantizar el comportamiento de todo elemento de una aplicación ante cualquier situación de uso por incorrecta o imprevisible que ésta pueda parecer. En general, esto supone multiplicar las comprobaciones que se realizan en todos los módulos programados, con la consiguiente penalización en carga de procesador, tiempo y aumento en la complejidad del código. Las técnicas de programación defensiva se utilizan especialmente en componentes críticos cuyo mal funcionamiento, ya sea por descuido o por ataque malicioso, podría acarrear consecuencias graves o daños catastróficos. Wikipedia
Recursos
- Wikipedia | Programación defensiva
- The Art of Defensive Programming
- Defensive Programming In JavaScript
- Defensive coding examples
- Defensive JavaScript? Yes, Please!
- Defensive programming: the good, the bad and the ugly
- What is “Defensive Programming”?
- An In-Depth Look at Defensive Programming
Un lenguaje de programación dinámico es un lenguaje de programación en el que las operaciones realizadas en tiempo de compilación pueden realizarse en tiempo de ejecución. Por ejemplo, en JavaScript es posible cambiar el tipo de una variable o agregar nuevas propiedades o métodos a un objeto mientras el programa está en ejecución. MDN
Recursos
Si parece un pato, nada como un pato, y grazna como un pato, entonces probablemente sea un pato.
Conceptos
- Podemos saber si un objeto es una instancia de otra por las propiedades que hereda o no...
typeof
es muy limitado para saber que es algo, especialmento con objetosInstanceof
es útil cuando evaluamos nuestras propias construcciones
El problema de typeof
//@see: http://www.etnassoft.com/2011/02/07/duck-typing-en-javascript-chequeando-los-tipos-de-datos/
console.log( typeof new String( 'Fictizia' ) ); //object
console.log( typeof new Number( 1 ) ); //object
console.log( typeof [ "platano", true, "coche", 4 ] ); //object
console.log( typeof new Array( "platano", true, "coche", 4 ) ); //object
El problema de instanceof
// @see: http://www.etnassoft.com/2011/02/07/duck-typing-en-javascript-chequeando-los-tipos-de-datos/
// construciones propias:
function constructor(){}
function otro_constructor(){}
constructor.prototype = otro_constructor;
console.log( new constructor() instanceof constructor ); // true
console.log( new otro_constructor() instanceof otro_constructor ); // true
console.log( new otro_constructor() instanceof constructor ); // false
// construciones del lenguaje:
console.log( new String( 'Fictizia' ) instanceof String ); // true
console.log( new String( 'Fictizia' ) instanceof Object ); // true
console.log( 'Fictizia' instanceof String ); // false
console.log( 'Fictizia' instanceof Object ); // false
console.log( new Array( 1, true, "banana" ) instanceof Array ); // true
console.log( new Array( 1, true, "banana" ) instanceof Object ); // true
console.log( [ 1, true, "banana" ] instanceof Array ); // true
console.log( [ 1, true, "banana" ] instanceof Object ); // true
Entendiendo la validación
// https://github.com/jashkenas/underscore/blob/master/underscore.js#L1315
function isArray( obj ){
return toString.call( obj ) === '[object Array]';
}
// Aproximación como Duck Typing
function isArray( obj ){
return obj && typeof obj === "object" && "push" in obj;
}
//@see: http://www.etnassoft.com/2011/02/07/duck-typing-en-javascript-chequeando-los-tipos-de-datos/
// Aproximación como Duck Typing en modo paranoico
function isArray( obj ){
return obj &&
typeof obj === "object" &&
"splice" in obj &&
"join" in obj &&
"push" in obj;
}
Recursos
- Wikipedia | Test del pato
- Wikipedia | Duck Typing
- Duck Typing en Javascript Chequeando los tipos de datos
instanceof
considered harmful (or how to write a robustisArray
)- All about types in Javascript – Type detection
- Stackoverflow | Duck Typing in Javascript
- JavaScript and Duck Typing
- Duck Typing in JavaScript
- Using Duck Typing to Avoid Conditionals in JavaScript
- branneman/javascript-duck-typing.js
- JavaScript permite cambiar los tipos de datos de las variables de forma mas o menos automatica (sumar cadena a un numero..)
- Ofrece mucha flexibilidad pero también hace el codigo potencialmente inestable
- Es importnate tener controlado esto cuando manejamos datos externos (Ajax/JSON)
Ejemplo
var txt = "Cadena";
var num = 100;
var bol = false;
var otroNum = "10"
console.log(typeof(txt)) //string
console.log(typeof(num)) //number
console.log(typeof(bol)) //boolean
console.log(typeof(otroNum)) //string
Problema Típico: Ajax/Json
- Inconsistencia de datos
- Inconsistencia en el tipo de datos
[
{
'id': 1,
'name': 'Dr. Evil',
'role': 'Evil Boss',
'external_agency': false,
'security_level': 5
'started_at': 'unknown'
}, {
'id': "N1001",
'name': 'Mr. Hacker',
'role': 501,
'security_level': "TOP SECRET"
'external_agency': "Evil Mega Corp",
'started_at': 125869547
}
];
Solución (Programación defensiva) con tipos primarios
// @see: http://www.etnassoft.com/2016/10/17/tipado-seguro-en-javascript/
//Closure
var typeOf = ( type ) => ( x ) => {
if ( typeof x === type ) return x;
throw new TypeError( "Error: " + type + " expected, " + typeof x + " given." );
};
var str = typeOf( 'string' );
// Correct
console.info( str( 'Hello World' ) ); // Hello World
// Error / Exception
console.info( str( 123 ) ); // Error: string expected, number given
/* --- Ejemplo Real ---*/
function sum ( x, y ) {
return num( x ) + num( y );
}
console.info( sum( 2, 4 ) ); // 6
console.info( sum( 2, '3' ) ); // Error: number expected, string given
Solución (Programación defensiva) con Objetos
//@see: http://www.etnassoft.com/2016/10/17/tipado-seguro-en-javascript/
const objectTypeOf = name => obj => {
let toType = ( {} ).toString.call( obj ).match( /\s([a-z|A-Z]+)/ )[ 1 ].toLowerCase();
if ( toType === name ) return obj;
throw new TypeError( "Error: " + name + " expected, " + toType + " given." );
}
const obj = objectTypeOf( 'object' ),
arr = objectTypeOf( 'array' ),
date = objectTypeOf( 'date' );
// Correct
console.info( obj( {} ) ); // Object {}
console.info( arr( [] ) ); // []
console.info( date( new Date() ) ); // Date { ... }
// Error / Exception
console.info( obj( [] ) ); // Error: object expected, array given.
console.info( arr( {} ) ); // Error: array expected, object given.
console.info( date( '13/11/2016' ) ); // Error: date expected, string given.
/* --- Ejemplo Real ---*/
const map = function( fn, a ) {
return arr( a ).map( func( fn ) );
}
map( String.toUpperCase, [ 'foo', 'bar' ] ); // [ 'FOO', 'BAR' ]
map( String.toUpperCase, 'Hello World' ); // Error: array expected, string given
Recursos
- Tipado seguro en Javascript
- The Shocking Secret About Static Types
- JavaScript’s type system
- Reddit | How do you deal with weak typing?
- Quora | How is Javascript typed?
- Understanding Loose Typing in JavaScript
- Introducing Type Safety To Your JavaScript Project? Think Again
- Wikipedia | Strong and weak typing
- Strong and weak typing
Importante
- Se fuerza a que un elemento cambie su comportamiento y se comporte como otro de forma temporal
- Es dificil recordar todas las reglas
- Jugar con esto es complejo y peligroso, deberias de evitarlo de forma consciente
- Javascript hace mucho juego de coerción por debajo y es necesario controlarlo
- La coercion SOLO aplica a los Tipos primitivos (Primitive Types):
Boolean
,Number
,String
,Null
,Undefined
,Symbol
. - La coercion JAMAS aplica en Objetos ni funciones, a excepción de
null
porqueobject == object
siempre es false
Coerción implicita vs. Explicita
- Explicita es cuando lo gestionamos directaente
Boolean()
,Number()
,String()
,parseloat()
, etc... - Implicita es cuando delegamos esa conversion con operadores como
+
,==
,!=
,-
, etc... ===
NO implica una coerción de tipos ya que valida por tipo primero (comparación estricta)
Solo existen tres tipos de coerciones
+dato
y-dato
fuerza la coercion a númeroalgo + string
oalgo - string
fuerza a coerción de cadena!value
,if(value)
fuerzan a la coerción boolena,Boolean(x)
Ámbitos del Juego
cualquier cosa -> boolean
numbero -> string
string -> number
boolean -> number
null or undefined -> number
null or undefined -> string
Lógica aceptable
- Una cadena que no pueda representar un número será
NaN
- Todo es True, a excepción de las cosas sin valor real (
0
,-0
,false
,null
,undefined
,""
) - Undefined es NaN,
isNaN(undefined)
//Un clasico
Array(16).join( 'hero'-1) + "Batman";
// NaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNNaNBatman
//@see: https://wtfjs.com/
//@see: https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch4.md#edge-cases
console.log('+true:', +true); //1
console.log('-true:', -true); //-1
console.log('true + false:', true + false); // 1
console.log('12 / "6":', 12 / "6"); // 2
console.log('"number" + 15 + 3:', "number" + 15 + 3); //number153
console.log('15 + 3 + "number":', 15 + 3 + "number"); //18number
console.log('[1] > null:', [1] > null); //true
console.log('"foo" + + "bar":', "foo" + + "bar"); //fooNaN
console.log('"true" == true:', "true" == true); //false
console.log('false == "false":', false == "false"); //false
console.log('null == "":', null == ""); //false
console.log('!!"false" == !!"true":', !!"false" == !!"true"); //true
console.log('["x"] == "x":', ["x"] == "x"); //true
console.log('[] + null + 1:', [] + null + 1); //null1
console.log('[1,2,3] == [1,2,3]:', [1,2,3] == [1,2,3]); //false
console.log('{}+[]+{}+[1]:', {}+[]+{}+[1]); //[object Object][object Object]1
console.log('!+[]+[]+![]:', !+[]+[]+![]); //truefalse
console.log('new Date(0) - 0:', new Date(0) - 0); //0
console.log('new Date(0) + 0:',new Date(0) + 0); //Thu Jan 01 1970 01:00:00 GMT+0100 (hora estándar de Europa central)0
Recursos
- Coerción de datos en Javascript
- Coercion en JavaScript
- Understanding JS: Coercion
- JavaScript type coercion explained
- What exactly is Type Coercion in Javascript?
- Understanding Javascript Coercion in 5 Easy Steps
- You Don't Know JS: Types & Grammar. Chapter 4: Coercion
Importante
this
es uno de los conceptos peor entendidos y más odiadosthis
se establece en tiempo de ejecuciónthis
es dinámico y varia constantementethis
es una de las herramientas más potentes del lenguajethis
es extensamente usando en la Programación Orientada a Objetos (POO) en JavaScript
Dominando los Contextos de this
- Window:
console.log( this === window );
function prueba(){
console.log( this === window);
}
prueba();
- Otro Contexto:
var usuario = {
nombre : 'Yo',
apellido : 'Mismo',
nombreCompleto : this.nombre + this.apellido,
metodoNombre: function(){
return this.nombre + " " + this.apellido
},
valorThis: function (){
console.log(this);
}
}
console.log(usuario.nombreCompleto); // ERROR - Undefined -> this=window
console.log(usuario.metodoNombre()); // this=usuario
usuario.valorThis(); // this=usuario
Recursos
- Entendiendo de verdad
this
en Javacript con Jorge Barrachina - MDN | This
- La palabra clave this en JavaScript
- Entendiendo el significado de ‘this’ en JavaScript
- La palabra this y el contexto en Javascript
- Why THIS is so powerful in JavaScript
Usando this
correctamente
var objeto = {
valor: 0,
incrementar: function(incremento){
this.valor += incremento;
}
};
objeto.incrementar(6);
console.log("objeto.valor:", objeto.valor) //6
Empiezan los problemas con this
por el scope
var objeto = {
valor: 0,
incrementar: function(incremento){
function otraFuncion(unValor){
this.valor += unValor;
}
otraFuncion(incremento);
}
};
objeto.incrementar(6);
console.log("objeto.valor:", objeto.valor) //0!!
_self
al rescate
var objeto = {
valor: 0,
incrementar: function(incremento){
var _self = this;
function otraFuncion(unValor){
_self.valor += unValor;
}
otraFuncion(incremento);
}
};
objeto.incrementar(6);
console.log("objeto.valor:", objeto.valor) //6
Recursos
- Nos permite hacer un código muy modular
- Nos permite crear mucho código reutilizable
- Existen tres formas de modificar el contexto
call()
Nos devuelve la ejecución con el contexto cambiado (this), documentaciónapply()
Nos devuelve la ejecución con el contexto cambiado (this), documentaciónbind()
Nos devuelve una nueva funcion con el contexto modificado (this), documentacióncall()
yapply()
se diferencian por como se pasan los argumentos a la función que modificamos
Ejemplo Sencillo
var objeto = {
multiplicador: 2,
sumatorio: function(num1, num2){
return (num1 + num2) * this.multiplicador;
}
};
var objeto_de_cambio = {
multiplicador: 5
};
var resultado = objeto.sumatorio(2,2);
console.log(resultado); // 20
/* -- Tres formas de lograr lo mismo -- */
var resultado_call = objeto.sumatorio.call(objeto_de_cambio, 5, 5);
var resultado_apply = objeto.sumatorio.apply(cambio, [5,5]);
var cambiandoFuncion = objeto.sumatorio.bind(cambio);
console.log(resultado_call); // 50
console.log(resultado_apply); // 50
console.log(cambiandoFuncion(5, 5)); // 50
Ejemplo más real
var usuarios = [{
nombre: "Yo",
apellido: "Mismo",
user: "me"
}, {
nombre: "Doctor",
apellido: "Maligno",
user: "MrEvil"
}];
function nombreCompleto (){
console.log( this.nombre + ' ' + this.apellido + ' (@'+this.user+')' );
}
function premium (isPremium, until) {
var user = '@'+this.user;
console.log( isPremium ? user + " es premium hasta "+ until : user + " NO es premium");
}
nombreCompleto() //Error (window...) // undefined undefined (@undefined)
nombreCompleto.apply(usuarios[1]) // Doctor Maligno (@MrEvil)
premium.apply(usuarios[1], [true, 'Mayo']) // @MrEvil es premium hasta Mayo
premium.call(usuarios[0], true, 'Enero') // @me es premium hasta Enero
premium.call(usuarios[0], false) // @me NO es premium
Las claves
- Puede ser complejo de entender si vienes de lenguajes Orientados a Objetos
- Todo es prototype de algo, incluido el propio core de JavaScript
- Nunca debes modificar metodos de objetos nativos
- La modificación del prototipo se extiende a todo el sistema
Uso de prototype
var elementosDom = document.querySelectorAll('div');
var elementos = Array.prototype.slice.call(elementosDom);
Extensión de objetos nativos
var amigosOriginales = ["Charlie", "Marco", "Oscar"];
amigosOriginales.coincidencias("Jose"); //amigosOriginales.coincidencias is not a function
Array.prototype.coincidencias = function(palabra) {
var coincidencias = 0;
//
for (var i=0; i<this.length; i++) {
if (this[i] == palabra) {
coincidencias++;
}
}
console.warn("Se encontraron "+coincidencias+" coincidencia(s) de la palabra");
};
var amigos = ["Charlie", "Marco", "Luis", "Jose", "Miguel", "Jose", "Luis", "Oscar"];
amigos.coincidencias("Jose"); // Se encontraron 2 coincidencia(s) de la palabra
amigosOriginales.coincidencias("Jose"); // Se encontraron 0 coincidencia(s) de la palabra
Recursos
- Wikipedia | Programación basada en prototipos
- MDN | Herencia y la cadena de prototipos
- MDN | Inheritance in JavaScript
- Decoding the Prototypal Inheritance in JavaScript: Everything you need to know!
- Javascript inheritance behind the scene proto, [[prototype]] and prototype
- Stackoverflow | proto VS. prototype in JavaScript
- JavaScript Prototype Explained By Examples
- Quora | What is the difference between "proto" and "prototype"?
- JavaScript's Pseudo Classical Inheritance diagram
- Master the JavaScript Interview: What’s the Difference Between Class & Prototypal Inheritance?
- Prototypal inheritance
- Understanding JavaScript: Prototype and Inheritance
- Demystifying ES6 Classes And Prototypal Inheritance
- A Definitive Guide to JavaScript Prototypes
Importante saber
- La variables primitivas (Undefined, Null, Boolean, Number y String) se copian por valor.
- Los objetos se copian por referencia (shallow copy), no es una copia real.. solo otra forma de llamarlo
- Para clonar objetos, necesitaremos hacer una recreación completa (deep copy) desde cero.
El problema de los punteros
var primitivo1 = "BANANA";
var primitivo2 = primitivo1;
primitivo2 = "MANDARINA";
console.log(primitivo1); //"BANANA"
console.log(primitivo2); //"MANDARINA"
// ¯\_(ツ)_/¯
var array1 = [1, 2, 3];
var array2 = array1;
array2.push("MANDARINA");
console.log(array1); //[1, 2, 3, "MANDARINA"]
console.log(array2); //[1, 2, 3, "MANDARINA"]
El problema de las estructuras circulares
var kom256 = {
nombre: "Ulises",
rol: "profesor",
curso: "Master de JS y Node",
amigos: []
};
var codingCarlos = {
nombre: "Carlos",
rol: "profesor",
curso: "Master de JS y Node",
amigos: []
};
var josheriff = {
nombre: "José Manuel",
rol: "profesor",
curso: "Curso de JS",
amigos: []
}
codingCarlos.amigos = [kom256, josheriff];
kom256.amigos = [codingCarlos, josheriff];
josheriff.amigos = [kom256, codingCarlos];
Posibles Soluciones
- Iterando propiedades con bucles, las propiedades de tipo objeto sera copiadas por referencia
JSON.parse
ignora funciones y objetos con estructuras circulares- En ES6 con
Object.assign()
, spread operator(...), etc... - Librerias:
$.extend
,_.CloneDeep
,_.Clone
var array1 = [1, 2, 3];
var array2 = JSON.parse(JSON.stringify(array1));
array2.push("MANDARINA");
console.log(array1); //[1, 2, 3]
console.log(array2); //[1, 2, 3, "MANDARINA"]
Recursos
- Clonando objetos en JavaScript
- Copying Objects in JavaScript
- Best way to copy an object in JavaScript?
- What is the most efficient way to deep clone an object in JavaScript?
- How to Copy a JavaScript Object
- Immutable structures and cloning
Recursos
- Wikipedia | Antipatrón de diseño
- Wikipedia | Crisis del software
- Wikipedia | No hay balas de plata
- Wikipedia | Code Smell (Hediondez del código)
- Anti-patrones: la mejor forma de hacer un pésimo sistema de software
- Antipatrones I: Antipatrones de gestión
- Antipatrones II: Antipatrones de gestión de proyectos
- Antipatrones III: Antipatrones generales de diseño de software
La destrucción del Mariner I (1962). 18,5 millones de dólares
El del Mariner I, una sonda espacial que se dirigía a Venus, se desvió de la trayectoria de vuelo prevista poco después del lanzamiento. Desde control se destruyó la sonda a los 293 segundos del despegue. La causa fue una fórmula manuscrita que se programó incorrectamente. El blog de Javier Garzas
La catástrofe del Hartford Coliseum (1978). 70 millones de dólares
Apenas unas horas después de que miles de aficionados abandonaron el Hartford Coliseum, el techo se derrumbó por el peso de la nieve. La causa: calculo incorrecto introducido en el software CAD utilizado para diseñar el coliseo. El blog de Javier Garzas
El gusano de Morris (1988). 100 millones de dólares
El estudiante de posgrado Robert Tappan Morris fue condenado por el primer ataque con “gusanos” a gran escala en Internet. Los costos de limpiar el desastre se cifran en 100 millones de dólares. Morris, es hoy profesor en MIT. El blog de Javier Garzas
Error de cálculo de Intel (1994). 475 millones de dólares
Un profesor de matemáticas descubrió y difundió que había un fallo en el procesador Pentium de Intel. La sustitución de chips costó a Intel 475 millones. El blog de Javier Garzas
Explosión del cohete Arian (1996). 500 millones de dólares
En el 1996, el cohete Ariane 5 de la Agencia Espacial Europea estalló. El Ariane explotó porque un número real de 64 bits (coma flotante) relacionado con la velocidad se convirtió en un entero de 16 bits. El blog de Javier Garzas
Mars Climate Orbiterm (1999). 655 millones de dólares
En 1999 los ingenieros de la NASA perdieron el contacto con la Mars Climate Orbiter en su intento que orbitase en Marte. La causa, un programa calculaba la distancia en unidades inglesas (pulgadas, pies y libras), mientras que otro utilizó unidades métricas. El blog de Javier Garzas
El error en los frenos de los Toyota (2010). 3 billones de dólares
Toyota retiró más de 400.000 de sus vehículos híbridos en 2010, por un problema software, que provocaba un retraso en el sistema anti-bloqueo de frenos. Se estima entre sustituciones y demandas el error le costó a Toyota 3 billones de dólares. El blog de Javier Garzas
Las migraciones por el año 2000. 296,7 billones de dólares
Se esperaba que el bug Y2K paralizase al mundo a la medianoche del 1 de enero 2000, ya que mucho software no había sido previsto para trabajar con el año 2000. El mundo no se acabó, pero se estima que se gastaron 296,7 billones de dólares para mitigar los daños. El blog de Javier Garzas
En territorio nacional
- El Mundo | Un grave error en el web del Ministerio de Vivienda daba acceso a datos personales
- El Confidencial | La gran "chapuza" informática de LexNet en Justicia que ha costado más de 7 millones
- Xakata | Qué ha pasado en LexNet y qué implicaciones tiene su grave fallo de seguridad
- Europa Press | Un fallo informático causa interrupciones en la red de Salud, Hacienda y Desarrollo Rural
Más articulos
- 20 Minutos | Los 10 mas grandes errores de la Informática
- RT | 10 errores informáticos que provocaron catástrofes
- 20 desastres famosos relacionados con el software
- Jaxenter | The top 10 catastrophes in the history of IT
- OpenMind | 5 bugs informáticos que marcaron la historia
Ciclo de vida del Software
Historia de la ingeniería del software
- La era pionera
- De 1955 a 1965: Los orígenes
- De 1965 a 1985: La crisis del software
- De 1985 a 1989: No hay balas de plata
- De 1990 a 1999: Prominencia de Internet
- De 2000 al presente: Metodologías ligeras
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Humo y espejos (smoke and mirrors)
Mostrar cómo será una funcionalidad antes de que esté implementada.
Mala gestión (bad management)
Gestionar un proyecto sin tener suficientes conocimientos sobre la materia.
Software inflado (software bloat)
Permitir que las sucesivas versiones de un sistema exijan cada vez más recursos.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Gran bola de lodo (big ball of mud)
Construir un sistema sin estructura definida.
Inversión de abstracción (abstraction inversion)
No exponer las funcionalidades implementadas que los usuarios necesitan, forzando a que se reimplementen a más alto nivel.
Entrada chapuza (input kludge)
No especificar e implementar el manejo de entradas inválidas.
Carrera de obstáculos (race hazard)
Incapacidad de prever las consecuencias de diferentes sucesiones de eventos.
Botón mágico (magic pushbutton)
Tender, desarrollando interfaces, a programar la lógica de negocio en los métodos de interacción, implementando los resultados de las acciones del usuario en términos no suficientemente abstractos.
Clase Gorda/Objeto todopoderoso
Dotar a una clase/objeto con demasiados atributos y/o métodos, haciéndola responsable de la mayoría de la lógica de negocio.
Objeto todopoderoso (god object)
Concentrar demasiada funcionalidad en una única parte del diseño (clase).
Acoplamiento secuencial (sequential coupling)
Construir una clase que necesita que sus métodos se invoquen en un orden determinado.
Objeto sumidero (object cesspool)
Reutilizar objetos no adecuados realmente para el fin que se persigue.
Emplear objetos cuyo único propósito es pasar la información a terceros objetos.
YAFL (yet another fucking layer, y otra maldita capa más) o 'Código Lasagna'
Añadir capas innecesarias a un programa, biblioteca o framework.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Nomenclatura heroica (heroic naming)
Identificar los miembros de un programa (interfaces, clases, propiedades, métodos...) con nombres que provocan que el conjunto aparente estandarización con la ingeniería del software pero que en realidad oculta una implementación anárquica.
Acumular y disparar (accumulate and fire)
Establecer una colección de variables globales para ser usadas por un conjunto de subrutinas.
Ancla del barco (boat anchor)
Retener partes del sistema que ya no tienen utilidad.
Complejidad no indispensable (accidental complexity)
Dotar de complejidad innecesaria a una solución.
Código espagueti (spaghetti code)
Construir sistemas cuya estructura es difícilmente comprensible, especialmente debido a la escasa utilización de estructuras de programación.
Código ravioli (ravioli code)
Construir sistemas con multitud de objetos muy débilmente conectados.
Descuidar la comprobación de los resultados que produce una subrutina, o bien de la efectividad de un parche o solución a un problema.
Ocurre cuando un software es entregado antes de ser completado o antes de ser completamente probado y al ser expuesto, ya no es posible cambiar sus características, como cuando un flujo de lava se seca por fuera.
Lógica super-booleana (superboolean logic)
Emplear comparaciones o abstracciones de la lógica booleana innecesarias.
Momento del código (code momentum)
Establecer demasiadas restricciones sobre una parte del sistema debido a la asunción de muchas de sus propiedades desde otros lugares del propio sistema.
Números mágicos (magic numbers)
Incluir en los algoritmos números concretos sin explicación aparente.
Ocultación de errores (error hiding)
Capturar un error antes de que se muestre al usuario, y reemplazarlo por un mensaje sin importancia o ningún mensaje en absoluto.
Lógica super-booleana (superboolean logic)
Emplear comparaciones o abstracciones de la lógica booleana innecesarias.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Asumir que nuestra solución técnica favorita puede resolver un problema mucho mayor.
Desarrollo conducido por quien prueba (tester driven development)
Permitir que un proyecto software avance a base de extraer sus nuevos requisitos de los informes de errores.
Desfactorización (de-factoring)
Eliminar funcionalidad y reemplazarla con documentación.
Factor de improbabilidad (improbability factor)
Asumir que es improbable que un error conocido cause verdaderos problemas.
Martillo de oro (golden hammer)
Asumir que nuestra solución favorita es universalmente aplicable, haciendo bueno el refrán a un martillo, todo son clavos.
Optimización prematura (premature optimization)
Realizar optimizaciones sin disponer de la información suficiente para hacerlo con garantías, sacrificando decisiones de diseño.
Programación de copiar y pegar (copy and paste programming)
Programar copiando y modificando código existente en lugar de crear soluciones genéricas.
Programación por permutación (programming by permutation)
Tratar de aproximarse a una solución modificando el código una y otra vez para ver si acaba por funcionar.
Reinventar la rueda (reinventing the wheel)
Enfrentarse a las situaciones buscando soluciones desde cero, sin tener en cuenta otras que puedan existir ya para afrontar los mismos problemas.
Reinventar la rueda cuadrada (reinventing the square wheel)
Crear una solución pobre cuando ya existe una buena.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Infierno de dependencias (dependency hell)
Escenario de problemas producidos por las versiones de otros productos que se necesitan para hacer funcionar un tercero.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Alcance incremental (scope creep)
Permitir que el alcance de un proyecto crezca sin el control adecuado.
Dependencia de proveedor (vendor lock-in)
Construir un sistema que dependa en exceso de un componente proporcionado por un tercero.
Diseño en comité (design by committee)
Contar con muchas opiniones sobre un diseño, pero adolecer de falta de una visión unificada.
Escalada de compromiso (escalation of commitment)
No ser capaz de revocar una decisión a la vista de que no ha sido acertada.
Funcionalitis creciente (creeping featuritis)
Añadir nuevas funcionalidades al sistema en detrimento de su calidad.
Gestión basada en números (management by numbers)
Prestar demasiada atención a criterios de gestión cuantitativos, cuando no son esenciales o difíciles de cumplir.
Gestión de champiñones (mushroom management)
Tratar a los empleados sin miramientos, sin informarles de las decisiones que les afectan (manteniéndolos cubiertos y en la oscuridad, como los champiñones).
Gestión porque lo digo yo (management by perkele)
Aplicar una gestión autoritaria con tolerancia nula ante las disensiones.
Obsolescencia continua (continuous obsolescence)
Destinar desproporcionados esfuerzos a adaptar un sistema a nuevos entornos.
Organización de cuerda de violín (violin string organization)
Mantener una organización afinada y en buen estado, pero sin ninguna flexibilidad.
Parálisis por análisis (analysis paralysis)
Dedicar esfuerzos desproporcionados a la fase de análisis de un proyecto, eternizando el proceso de diseño iterando sobre la búsqueda de mejores soluciones o variantes.
Peligro moral (moral hazard)
Aislar a quien ha tomado una decisión a raíz de las consecuencias de la misma.
Sistema de cañerías (stovepipe)
Tener una organización estructurada de manera que favorece el flujo de información vertical, pero inhibe la comunicación horizontal.
Te lo dije (I told you so)
Permitir que la atención se centre en que la desoída advertencia de un experto se ha demostrado justificada.
Gallina de los huevos de oro (cash cow)
Pecar de autocomplacencia frente a nuevos productos por disponer de un producto legacy muy lucrativo.
📌 Nota: Este es un resumen de la entrada en Wikipedia sobre Antipatrón de diseño
Arrojar al otro lado del muro (thrown over the wall)
Cuando un proyecto involucra a varios grupos de trabajo y va pasando secuencialmente de uno a otro, con escasa o nula comunicación entre ellos.
Billete lobo (wolf ticket)
Declarar compatibilidad con un estándar cuando ésta no existe, o bien cuando el estándar solo incluye recomendaciones no obligatorias que, de hecho, no se siguen.
Fiesta de los bocazas (Blowhard Jamboree)
Cuando se intenta que las decisiones técnicas del proyecto sean las basadas en opiniones de expertos publicadas en prensa.
Callejón sin salida (dead end)
Encontrar un problema que impide continuar trabajando, pero la dirección no permite corregir el problema. El equipo queda estancado.
Caminar por un campo de minas (walking through a mine field)
Trabajar con un componente pobremente probado (usualmente inestable), y por tanto poco confiable.
Chivo expiatorio (scape goat)
Ante circunstancias de crisis en un proyecto se toma la decisión de dirigir las culpas a una persona o a un conjunto de personas concretas sin analizar si verdaderamente la naturaleza del problema se encuentra en las mismas.
Codificación brutal
Presionar a los programadores a trabajar sobre una arquitectura sin diseñar y sin requisitos evidentes.
Comité designado (appointed team)
Crear un comité o grupo de trabajo para resolver un problema y no ocuparse de lograr que el grupo funcione.
Compensación equitativa (egalitarian compensation)
Compensar al personal por el trabajo individual hecho.
Contenedor mágico (magic container)
La implementación de métodos que intentan ser tan flexibles como para adaptar su comportamiento a multitud de circunstancias, sobrepasando el umbral de una mantenibilidad adecuada del mismo.
Culto al carguero (cargo cult)
Consiste en copiar ciertas prácticas que podrían ser consideradas (no siempre) buenas prácticas sin saber muy bien los beneficios o ventajas que proporcionan, provocando esfuerzo innecesario en el proyecto para incorporarlas o problemas.
Cultura del miedo (fear culture))
Ambiente en el que cada empleado tiene miedo de mostrar el resultado de su trabajo por miedo a ser despedido por tener errores.
Cultura del héroe (hero culture)
Se produce cuando una o pocas personas toman la responsabilidad del éxito de todo el equipo o proyecto, a menudo trabajando sobretiempo.
Decisión aritmética (decision by arithmetic)
En lugar de intentar tomar una decisión con los datos disponibles y basado en el conocimiento y experiencia de nuestros colaboradores y el nuestro, se trata de justificar la misma sobre la base de unos factores presuntamente objetivos.
Desarrollo marcado por las herramientas (autogenerated stovepipe)
Preferir una solución generada automáticamente sobre la mejor solución.
Diseñar por diseñar (design for the sake of design)
Realizar un diseño excesivamente complejo sin necesidad real.
Diseño con arquitectura impuesta (architecture as requirement)
Imponer que el diseño considere, obligatoriamente, el uso de herramientas o métodos no necesariamente idóneos.
Diseñadores empíricos (architects don't code)
Incapacidad del grupo de diseño para evaluar la complejidad del objeto diseñado.
El correo electrónico es peligroso (email is dangerous)
Peligro de olvidar que detrás de los emails recibidos hay personas de carne y hueso.
El traje nuevo del emperador (emperor's new clothes)
Temor a señalar los defectos de un producto o proceso que un gerente o manager cree que funciona bien.
El viejo gran duque de York (the grand old Duke of York)
Cuando los arquitectos o analistas no intervienen (uno o los dos), dejando a los programadores (especialistas en la implementación) prácticamente todas las decisiones a nivel e ejecución de las especificaciones del usuario.
Ellos me entendieron (they understood me)
Explicar a programadores o diseñadores junior lo que se espera de ellos muy brevemente, y asumir que entendieron lo que se les pidió.
Entrenar al entrenador (train the trainer)
Contratar una formación sin haber precisado con cierta exactitud la materia sobre la que se desea la misma. Esto puede provocar que la formación no se enfoque de manera adecuada, tratando aspectos que no son necesarios en el proyecto o dejando fuera aspectos fundamentales. Contratar una formación sin tener referencias del formador, ya que lo mismo su nivel de conocimiento no es el adecuado a la naturaleza de la formación a impartir.
La disputa familiar (the feud)
Cuando existiendo un conflicto entre gestores de proyectos no se le busca una solución definitiva al mismo.
La experiencia mata el diseño (architecture by implication)
Descuidar el diseño por confiar excesivamente en la experiencia previa.
Los clientes son tontos (customers are idiots)
Pensar que uno sabe más que el cliente, y por tanto no es necesaria una investigación con el cliente.
Maníaco del control (control freak)
El deseo de control lleva a la microgestión y ésta a su vez a una pérdida importante de la capacidad de autogestión del equipo, ya que todos los pasos se miden milimétricamente.
Máquina de Rube Goldberg (Rube Goldberg machine)
Realizar implementaciones muy complejas para tareas sencillas.
Matar al mensajero (shoot the messenger)
El acto de culpar a una persona que trae malas noticias en vez del autor de las mismas.
Mazorca de maíz (corn cob)
Mantener personas en el proyecto que resultan difíciles, conflictivas o que funcionan de manera absolutamente al margen de lo que es cualquier trabajo en equipo o de un comportamiento solidario y que rompen con la armonía del grupo.
Mecanismos de recompensa discordantes (discordant reward mechanisms)
Un equipo recibe reconocimiento por ser el que más trabajo ejecuta sobre la base de criterios objetivos que no son válidos para medir el nivel de productividad o calidad.
Miedo al éxito (fear of success)
Permitir que las únicas razones de que los trabajos no se completen sean de índole social.
Morir planificando (death by planning)
Invertir más esfuerzo (y tiempo) del necesario para establecer un plan que después puede ser destruido por las propias contingencias del proceso de desarrollo, o cuando no se es flexible ante una planificación inicial, conservándose a lo largo del proyecto pese a que se pueda apreciar que resulta absolutamente irreal.
Navaja suiza (swiss army knife)
Intentar crear un producto que solucione varios problemas poco relacionados entre sí.
No es mi trabajo (Not my job)
No solucionar algún problema evidente argumentando que es problema o fallo de otro.
No inventado aquí (not invented here)
Cuando la organización o uno se niega a utilizar soluciones, metodologías, prácticas, herramientas, etc. externas sólo porque no se nos ocurrió previamente.
Otra reunión más lo resolverá (yet another meeting will solve it)
Ante un problema en la planificación del proyecto, se convocan reuniones para intentar dar una solución al problema. En estas reuniones participan los miembros del equipo de proyecto que tendrán que dejar su trabajo habitual, produciéndose nuevos retrasos.
Programador discordante (net negative producing programmer)
Hay proyectos donde el rendimiento de uno o más miembros del equipo es muy inferior al esperado, hasta el punto de ser su productividad neta en el proyecto negativa (el proyecto mejoraría con el simple hecho de prescindir de estas personas, sin necesidad de sustituirlas por otra)
Proyecto del día de la marmota (ground hog day project)
Discutir los mismos temas en todas las reuniones, sólo para llegar a la conclusión de que "algo debe hacerse".
Prueba incompleta (asynchronous unit testing)
Descuidar en la etapa de pruebas, algunas unidades en todos los casos, o todas las unidades en algunos casos.
Quiero estimaciones ahora (give me estimates now)
Dar estimaciones sin tener suficientes datos para hacerlas.
Requisitos esparcidos por la pared (requirements tossed over the wall)
Existe un desorden general en los requisitos: se encuentran en distinto grado de terminación, no hay priorización de los mismos o es muy general como para poder hacer una ordenación adecuada por ese criterio, etc. Esto normalmente es provocado por una colaboración inadecuada por parte del área usuaria.
Requisitos ocultos (Hidden requirements)
El equipo de proyecto conocedor de la dificultad de implementar un determinado requisito lo obvia dentro del catálogo de requisitos, le asigna una prioridad muy baja o lo engloba dentro de un requisito de mayor nivel quedando difuminado en el mismo. El área usuaria no especifica un requisito o no lo especifica de manera adecuada, solicitando explicaciones a posteriori por la no implementación de ese requisito o por su comportamiento incorrecto.
Somos tontos (we are idiots)
Pensar que el conocimiento interno del problema es peligroso (por riesgo de que sea pobre o equivocado), y pedir validación del cliente para cada característica o decisión mayor.
Tormenta de reproches (blame storming)
En un equipo de proyecto se llega a la conclusión de que la mejor forma de analizar las causas de la no consecución de los objetivos es que se discuta quiénes internamente han tenido la culpa.
Torre de vudú (tower of voodoo)
Se tiene un código que se sabe que funciona (aunque generalmente no se sabe muy bien cómo) y se pretende añadir algún tipo de funcionalidad adicional, en ocasiones no muy cohesionada con la ya implementada y se le coloca un envoltorio (wrapper) proporcionando una nueva interfaz de acceso a ese nuevo componente.
Trampa para osos (bear trap)
Invertir mucho en una herramienta poco adaptada o factible, de manera que después es imposible deshacerse de ella.
Violencia intelectual (intellectual violence)
De manera interna en un equipo de trabajo o en una reunión con el cliente y/o con usuarios se utilizan términos, generalmente técnicos, que no son comprendidos o conocidos por la mayoría de los interlocutores.
Entropía del software
La segunda ley de la termodinámica, en principio, afirma que el desorden de un sistema cerrado no puede reducirse, sólo puede permanecer sin cambios o aumentar. Una medida de este desorden es la entropía. Esta ley también parece plausible para los sistemas de software; Cuando un sistema es modificado, su desorden o entropía, tiende a aumentar. Esto es conocido como entropía del software. Wikipedia | Entropía del software
¡Recuerdalo!
- Código duplicado
- Método/Clase/Objeto/Función grande
- Demasiados parámetros, nunca más de 3
- NO medir la complejidad ciclomática: Anidación en exceso, limitarnos a 2 niveles
- Identificadores cortos o muy largos
- Mala gestión de asincronía (cascadas y callback hell)
- Funciones poco especializadas
- Pesima gestión de los retornos (mucha información, poca flexibildiad, etc...)
Recursos