30
abr 13

ECMAScript 5 _.extend

A algunos ya os he comentado los problemas que NC Zakas comenta con el _.extend de underscore y los getters:

var a = {
  init: function() {
    this.list = [];
  },

  get first() {
    return this.list[0];
  }
};

O

var a = {
  init: function() {
    this.list = [];
  }
};

Object.defineProperty(a, 'first', {
  get: function() {
    return this.list[0];
  }
});

Y que si hacemos _.extend(a) va a fallar porque intentará hacer result.first = a.first ejecutando el getter. Pero como aún no hemos llamado al .init() en a porque solo es un prototipo, la propiedad .list es undefined produciendo un error.

Pues bien, yo creía que esto se solucionaba extrayendo el descriptor de la propiedad y usando ese mismo descriptor para copiar la propiedad al nuevo objeto:

function extend(obj) {
  var result = {};
  var properties = Object.keys(obj);

  properties.forEach(function(prop) {
    var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
    Object.defineProperty(result, prop, descriptor);
  });

  return result;
}

Pero he usado esto en la librería de promises y me he dado cuenta que solo hereda las propiedades directas, tanto Object.keys como Object.getOwnPropertyDescriptor solo funcionan si la propiedad está directamente declarada en el objeto y no en ninguno de sus prototipos. Y no hay ninguna forma de decir Object.getPropertyDescriptorFromHimOrHisPrototypes() así que la única forma es recorrer todos los prototipos.

function extend(obj) {
  var result = {};
  var proto = obj;

  while (proto) {
    Object.keys(proto).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(proto, prop);
      Object.defineProperty(result, prop, descriptor);
    });

    proto = Object.getPrototypeOf(proto);
  }

  return result;
}

Pero eso tampoco funciona del todo bien porque las propiedades de los ancestros se impondrían sobre las propiedades propias del objeto. Así que primero hay que empezar por el último prototipo y acabar por el propio objeto

function extend(obj) {
  var result = {};
  var proto = obj;
  var protos = [];

  while (proto) {
    protos.push(proto);
    proto = Object.getPrototypeOf(proto);
  }

  protos.reverse().forEach(function(ancestor) {
    Object.keys(ancestor).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(ancestor, prop);
      Object.defineProperty(result, prop, descriptor);
    });
  });

  return result;
}

Y esto ya funciona, pero le falta un detallito, mediante el property descriptor se puede poner que una propiedad no sea enumerable por lo que no se interará sobre ella con un for .. in .. ni con Object.keys pero si las podemos obtener si utilizamos Object.getOwnPropertyNames (Fuente: MDN). Así que remplazando Object.keys con Object.getOwnPropertyNames esta vez si (espero, rezo, suplico -.-) tenemos una función que crea una copia de todas las propiedades propias y heredadas de un objeto.

function ecma5extend(obj) {
  var proto = obj;
  var protos = [];
  var result = {};

  while (proto) {
    protos.push(proto);
    proto = Object.getPrototypeOf(proto);
  }

  protos.reverse().forEach(function(ancestor) {
    Object.getOwnPropertyNames(ancestor).forEach(function(prop) {
      var descriptor = Object.getOwnPropertyDescriptor(ancestor, prop);
      Object.defineProperty(result, prop, descriptor);
    });
  });

  return result;
}

Como al final el código ha quedado bastante más complejo de lo que me gustaría lo he apuntado en un Gist que podría venirles bien.


18
abr 13

Object.create vs new

JotaEseros! Tengo un dilema existencial que me impide dormir.

Hasta donde sé los constructores hacen más o menos esto

function fakeNew(Ctor) {
  var instance = Object.create(Ctor.prototype);
  instance.constructor();
  return instance;
}

Todo empezó cuando quise hacer polyfill de Object.create(), así podría crear objectos sin usar new, decidí usar la versión sencilla

Object.create = function(proto) {
  function F() { }
  F.prototype = proto;
  return new F();
}

Y empecé a crear un montón de objetos y a prototiparlos, pero como los objetos muchas veces necesitaban inicializar sus propiedades les hice el método .init()

var base = {
  init: function() {
    EmitterMixin.call(this);
    return this;
  }
};

var obj = Object.create(base).init();

Pero claro, tengo que acordarme de devolver this siempre al acabar .init() y muchas veces lo olvidaba o me olvidaba de invocar .init() que es peor. Así que intentando como simplificar la inicialización de un objeto pensé crear una funcioń global que se encargara de invocar a Object.create, llamar a la función inicializadora y devolver this:

function create(proto) {
  var child = Object.create(proto);
  child.init();
  return child;
}

Y me empezaron a dar ganas de reventarme la cabeza contra la pared al darme cuenta que lo que estaba haciendo es prácticamente lo mismo que hace el operador nativo new pero mucho más lento y, en caso de usar el polyfill the Object.create incluso usando new por debajo.

Entonces me pregunto, que beneficios aporta abandonar new? es notablemente más rápido en la mayoría de navegadores y por la naturaleza de javascript solemos necesitar crear una función inicializadora que en el caso de new es el constructor.

Y lo que es más grave aún, he notado que usaba dos tipos diferentes de objetos, unos “abstractos” y otros “instancias” la mayor diferencia es que en las instancias tenía que invocar .init() siempre mientras que los abstractos no era necesario porque solo serían usados para crear otros objetos que los prototiparan. Y es un patrón que he visto mientras usaba new:

function Foo() { }
Foo.prototype.method = function() { ... };

function Bar() { }
// Objeto "abstracto", no se invoca inicializador
Bar.prototype = Object.create(Foo.prototype);
Bar.prototype.other = function() { ... };

// Objeto "instancia"
// se invoca el constructor como inicializador
var obj = new Bar();

Realmente hay es una ventaja abandonar new? estamos seguros que no se trata de una herramienta de alto nivel que simplifica algo que igualmente tendremos que hacer nosotros a mano? Que pros y contras tienen new y Object.create?


04
dic 12

GIT Workflow (Flujo de trabajo) (Parte 2)

Continuando con mi último artículo, llegó la hora de hablar del gran Github Flow:

Github Flow

Y finalmente el artículo que ha inspirado éste. Después de probar el Git Flow (el modelo, no la herramienta) en productos profesionales y a modo de prueba en pequeñas librerías propias y aunque para proyectos grandes donde una release se planea durante semanas va bien, en pequeños proyectos, y en proyectos SaaS no acaba de encajar.

Para empezar en pequeños proyectos no hay necesidad de planificar con antelación una release, un proyecto pequeño necesita mucha actividad y poca burocracia para crecer, por otro lado, en proyectos SaaS (Software as a Serivce), es decir, productos que están disponibles online y todos los usuarios tienen la última versión y reciben los cambios inmediatamente las versiones y releases pierden fuerza. **Porqué retrasar el lanzamiento de una nueva funcionalidad cuando todos los usuarios podrían tenerla mañana sin ningún coste? en un producto clásico las funcionalidades se empaquetan para entregar al usuario la actualización un paquete cerrado y pasar el proceso de actualización la menor cantidad de veces posibles, pero **en un SaaS para el usuario no tiene ningún coste (en esfuerzo) una actualización, simplemente la próxima vez que abra el programa tendrá la funcionalidad.

Un ejemplo de SaaS es Gmail (que estuvo más de 5 años en fase Beta por éste motivo), twitter o github. Y es éste último quién, como no podía ser de otra forma, utiliza un flujo de trabajo de GIT que parece encajar bastante bien con la filosofía SaaS de release constantes. Lo que ellos llaman Github Flow.

Seguir leyendo →


04
dic 12

GIT Workflow (Flujo de trabajo) (Parte 1)

Acabo de leer un artículo creado por los trabajadores de Github que han dado una vuelta de tuerca a lo que sabía de GIT y creo que será muy útil compartirlo, pero primero vamos por partes:

Control de Versiones

Prefiero empezar por lo más básico porque ésto es algo que los programadores damos por hecho pero para alguien empezando puede ser totalmente desconocido. Una de las herramientas más básicas de un programador junto con el editor de texto es un sistema de control de versiones. Se trata básicamente de un programa que registra los cambios que vamos haciendo en los archivos y cuando nosotros se lo ordenamos (hacemos commit) se guarda el estado actual de los archivos, si más adelante seguimos haciendo cambio en los archivos y en lugar de mejorar empeora gracias al sistema de control de versiones podemos revertir los archivos y dejarlos tal y como estaban en el último commit o cualquier commit anterior. Además permite que dos o más personas puedan archivos de un mismo proyecto y cuando ambos envíen sus cambios el sistema hará lo posible por combinarlos (hacer merge), en caso de que el merge no se pueda hacer automático el sistema notifica un conflicto de cambios y nos pide que lo hagamos a mano.

Seguir leyendo →


03
mar 12

Experimento: Privacidad por instancias

Como ya comenté, la privacidad en Javascript es un tema peliagudo, el lenguaje no nos ofrece ninguna herramienta para gestionar la privacidad automáticamente, tenemos que aprovechar el scope de los closures para ocultar información que el usuario de nuestra librería no necesita saber, pero ocultar propiedades de una instancia es mucho más complicado. Hace algunos años me empeñé en buscar una forma de conseguir privacidad por instancias que no fuera mediante el constructor, como ya expliqué en el post anterior.

Seguir leyendo →


26
feb 12

Conceptos Básicos Javascript: Privacidad

Introducción

Uno de los temas más frecuentes cuando uno se inicia en Javascript es la privacidad, principalmente viniendo de lenguajes como Java, C# o C++; donde publican o se ocultan propiedades de los objetos mediante modificadores. Javascript no posee dichos modificadores sino que todas las propiedades de los objetos son públicas lo que puede ser muy confuso para una persona poco diestra en ésta técnica, entre los que me incluyo.

Personalmente cuando diseño un componente (objeto/clase/librería), es porque quiero que ese componente cumpla una funcionalidad, por ejemplo, si yo quiero tener una clase que represente a una impresora necesito enviarle datos y que los imprima; mi prioridad es que dicho componente sea sencillo de utilizar, lo que facilita la reutilización del componente. Por lo que primero imagino cómo me gustaría usarlo:

var impresora = new Impresora();
impresora.encender();
impresora.imprimir(datos);
impresora.apagar();

Como se ve, para cumplir la funcionalidad me basta con tres métodos, pero si yo escribo mi clase impresora con solo tres métodos probablemente duplicaría mucho código, por ejemplo, que .imprimir() y .apagar() deban comprobar si hay papel en la impresora.

Seguir leyendo →


18
ene 12

Javascript Conceptos Básicos: Herencia por prototipos

Llegó la hora de entrar el en tema que realmente confunde a los recién llegados a Javascript, principalmente para quienes vienen de lenguajes que implementan la orientación a objetos mediante clases, que son la gran mayoría.

Orientación a Objetos

Primero deberemos aclarar que significa Programación Orientada a Objetos (POO u OOP en ingés).

Según la Wikipedia, la descripción es:

es un paradigma de programación que usa objetos y sus interacciones, para diseñar aplicaciones y programas informáticos. Está basado en varias técnicas, incluyendo herencia, abstracción, polimorfismo y encapsulamiento.

Como vemos un lenguaje orientado a objetos no necesariamente tiene que implementarse mediante clases, cualquier sistema que proporcione herencia, abstracción, polimorfismo y encapsulamiento es una implementación de orientación a objetos válida. Como ya dijimos, el sistema de clases es el más extendido, utilizado por C++, Java, C#, PHP, Python, ActionScript3, Perl, Objective-C, Ruby, etc… Javascript no tiene clases, utiliza el sistema de herencia por prototipos, veamos la diferencia:

Seguir leyendo →


08
ene 12

Javascript Conceptos Básicos: this, .call() y .apply()

Antes de continuar con el Patrón Promise me gustaría explicar en paralelo Conceptos Básicos de Javascript. Entendiendo que estamos hablando de Javascript como lenguaje y no vamos a hablar sobre conceptos básicos del DOM o como abrir una nueva ventana en el navegador, sino detalles de Javascript puro, tanto en cliente como en servidor.

De dónde sale this

He pensado que sería un buen punto empezar por una curiosidad bastante desconocida para los recién llegados a Javascript: La variable this, también llamado el scope o más correctamente contexto de la función. En los lenguajes basados en clases más extendidos (Java, C++, C#…) encontramos que los métodos de la clase siempre disponen de la variable this que nos permite acceder a nuestra propia instancia sobre la que se está ejecutando el método. Es decir, si tenemos la clase

class MyClass {
  String myField;
  void myMethod() {
    this.myField;
  }
}

Veremos que en myMethod siempre tendremos this apuntando a una variable del tipo MyClass que contendrá un campo myField. En Javascript ésto no es así, en Javascript todo son objetos, incluidas las funciones y métodos, ambos son instancias de Function, y como tales no están ligadas a un objeto en particular. Miremos el código:

function myFunction() {
  console.log(this.name);
}

var objectA = {
  name: "Alice",
  myMethod: myFunction
};

var objectB = {
  name: "Bob",
  myMethod: myFunction
};

Aquí tenemos dos objetos totalmente independientes y ambos tienen la propiedad myMethod apuntado a myFunction a pesar de que no tienen una clase en común más que Object. Entonces cuál es el valor de this en myFunction? No es fijo, cambia según como lo llamemos.

objectA.myMethod()
// Imprime "Alice"

objectB.myMethod()
// Imprime "Bob"

Pruébame

Seguir leyendo →


18
dic 11

Patrón Promise: Implementación (I)

Lo prometido es deuda (bien lo saben las funciones) y he encontrado un momento para empezar a explicar la forma en la que he implementado el patrón Promise en mi caso, no tiene porqué ser la mejor, pero cumple con su cometido.

NOTA: Me gustaría implementarla en Test Driven Development, pero ya es bastante para quien lee y para el que escribe seguir la implementación como para encima añadir TDD, pero no quisiera dejar de recomendarlo.

Primero: Funcionalidad básica

Lo que necesitamos de un objeto Promise es:

  • Crear instancias totalmente independientes
  • Añadirle callbacks que serán llamados cuando se cumpla la promesa
  • Notificarle cuando se ha cumplido la promesa

Seguir leyendo →


09
dic 11

El patrón Promise

PROBLEMA

Recientemente he tenido que implementar un sistema MVC en Javascript para simplificar el desarrollo sobre una plataforma y me he encontrado con el problema de que las llamadas asíncronas a servidor rompían la simpleza del código, tras un análisis identifiqué cuatro problemas:

1 – Ensuciar la API

Todas las llamadas reciben un último argumento que es el callback:

var dir = new Directory('file:///home/user/Desktop');
dir.browse(function(dir, items) {
  // ...
});

Con ésto la API resulta confusa desde el punto de vista de la simpleza y de la semántica. Semánticamente una función recibe la información mínima indispensable para devolver un dato relacionado a lo que se le ha solicitado, como vemos no es el caso en métodos asíncronos:

void Directory.browse(Function callback);
void File.getContent(String encoding, Function callback);
void File.getPermission(Function callback);

Seguir leyendo →