lunes, 23 de julio de 2012

Como desarrollar con Javascript y no morir (ni matar) en el intento – III


En JavaScript el concepto de Objeto representa un papel clave. Si tenemos en cuenta que no existe el concepto de clase que manejamos en otros lenguajes, es el objeto sobre el que recae la responsabilidad de definir el modelo y almacenar el valor de la instancia.

Una vez interiorizado este concepto, (superado el shock…) debemos tener en cuenta que en JavaScript disponemos de cinco tipos primitivos por valor que son: number, string, boolean, null, y undefined. Todo lo demás son objetos (más o menos especializados)

Estos tipos por valor (exceptuando null y undefined) poseen lo que se conoce como primitive wrapper objects. Los objetos wrapper pueden ser creados utilizando los constructores predefinidos Number(), String(), y Boolean()

Veamos este código al respecto:

   1:          //// number (primitivo)
   2:          var n = 100;
   3:          console.log(typeof n); // "number"
   4:          // objeto Number 
   5:          var nobj = new Number(100);
   6:          console.log(typeof nobj); // "object"

Estos objetos exponen una serie de métodos que nos ayudan a trabajar con la naturaleza de los datos a los que representan. Por ejemplo el objeto Number expone métodos como toFixed() o toExponential o el objeto String los métodos substring(), charAt() o toLowerCase().

Como hemos comentado alguna vez JavaScript es muy propenso a interpretar de la mejor manera que pueda el código e intentar hacer que funcione, con resultados algunas veces imprevistos.

¿Que os parece si os digo que estos métodos pueden ser aplicados también sobre los métodos primitivos por valor?

Pues en principio lo menos que os puede parecer es raro… Bueno, lo que esta ocurriendo detrás de la escena es que JavaScript promociona puntualmente el tipo primitivo a su correspondiente objeto, ejecuta el método y a continuación descarta el objeto creado. Lo dicho, buenas intenciones pero si no conocemos este comportamiento, puede provocar más de un dolor de cabeza…

Por ejemplo, como se nos ocurra la idea de aumentar un tipo primitivo, el interprete de JavaScript no nos arrojará ningún error, puesto que desde el punto de vista sintáctico todo está correcto, pero la propiedad incluida lo será sobre el objeto que se descartará automáticamente con lo que mal negocio hemos hecho.

Veamos un código que ilustra este ejemplo:

 
   1:          // string primitivo
   2:          var enterprise = "Plain Concepts";
   3:          // El primitivo es convertido a un objeto con el fin
   4:          // de ejecutar el método split()
   5:          console.log(enterprise.split(' ')[0]); // "Plain"
   6:          // Si intentamos aumentar un tipo primitivo no es un 
   7:          // error
   8:          enterprise.CIF = "XXXXXXXXXX";
   9:          // pero como el objeto es decartado automaticamente después de
  10:          // la promoción, la propiedad se pierde...
  11:          console.log(enterprise.CIF); // "undefined"​​





Este comportamiento, no ocurriría si instanciamos un objeto del tipo concreto (String(), Number(), Boolean()… ), por lo que si estamos pensando en aumentar el objeto creado no es buena idea usar los primitivos. 

También podríamos usar el constructor Object que incluye cierta lógica para crear el tipo derivado apropiado en base al valor recibido. (Una especie de factory)
 
Por ejemplo:
 

   1:           var n = new Object(3);
   2:           console.log(n instanceof Number); // True


 
Esta característica es un arma de doble filo puesto que nos puede llevar a errores o comportamientos inesperados cuando empleamos tipos dinámicos, por lo que en general se desaconseja su empleo siendo mas aconsejable (por sencilla y certera) emplear la notación literal.
 


 

No hay comentarios: