Javascript Orientado A Objetos Segun Buzu: los métodos

Hace ya un buen tiempo que dejé inconclusa una serie de artículos sobre Programación Orientada a Objetos en Javascript. Bueno, aquí traigo esta última entrega, y aun que en la anterior prometí que en esta entrega haríamos una librería, creo que eso quedará más bien fuera del contexto ya que dicha librería no usa mucho los conceptos de POO de los que hemos estado hablando. Sin embargo, ya abriré otra serie para ir creando dicha librería. Más que por el gusto de crear la librería, por el gusto de tocar algunos temas en Js que no se tocan mucho.  Bueno, pero eso será en un futuro. Por ahora me limitaré a hablar sobre cuatro tipos de métodos que pueden ser usados especialmente cuando estamos programando basados en constructores do objetos.

Dependiendo de lo que queramos lograr y de la accesibilidad que queramos darle a los métodos de nuestros objetos podemos usar uno de cuatro tipos de métodos: públicos, privado, privilegiados y estáticos. Empecemos analizando de adentro a afuera, es decir, con métodos privados.

Métodos privados:

Lo métodos privados no son accesibles desde fuera del objeto. Como su nombre lo dice, estos métodos son privados. Nos interesa usar métodos privados por ejemplo cuando queremos darle a nuestro objeto una funcionalidad que no nos interesa o que no nos conviene que sea posible acceder desde fuera del objeto. Consideremos el siguiente ejemplo:

Nota: también hay propiedades privadas y son más comunes que los métodos privados.

function miObj(){
    var nombre =  'Nombre Privado';//propiedad privada
   function privada(){//Método privado
       alert('función privada');
    }//fin del método privado
}

En este caso, el método privada() no puede ser accedido desde ningún lugar fuera de miObj();, es decir que:

var obj = new miObj();
obj.privada();//tira un error.

No es valido por que no hay nada que ligue privada() con el exterior. Pero entonces por que querías un método que no se puede llamar desde ningún lado? Una de las razones es para mantenerte organizado y seguir una de las mejores prácticas de la programación. Me refiero a que cada función tiene que tener solo un trabajo. Por ejemplo:

function miObj(){
    function mostrarOpciones(){
       //Codigo para mostrar opciones
    }
    function crearCanvas(){
       //Código para crear canvas
    }
    mostrarOpciones();
    crearCanvas();
}

Esas dos funciones se ejecutan al mismo tiempo por lo que daría igual hacer lo siguiente:

function mi Obj(){
    //Código para mostrar opciones
    //Código para crear canvas
}

Sin embargo, es mucho más fácil y legible una función que tiene un solo objetivo ya que 1) todo el código está relacionado entre sí, y 2) hay menos lineas de código. Además de que al haber más funciones hay más probabilidades de que un error sea identificado con mayor precisión.

Métodos privilegiados.

Hace un rato vimos los métodos privados. Pero si tienes ojo de debugger, seguro que te diste cuenta que también hemos puesto una propiedad privada (nombre). Al igual que el método privado, la propiedad privada no puede ser recuperada desde fuera del objeto. Es decir que si hace:

alert(obj.nombre);

te va a dar como resultado una alerta que dice undefined. No es un error del navegador. Es simplemente que no tienes los permisos necesarios para acceder a esa  propiedad, porque está “encerrada” dentro de las fronteras de miObj(). El uso de propiedades privadas es muy útil cuando quieres establecer valores que no quieres que sean modificados desde fuera del objeto. Por ejemplo, una velocidad que quieres que se mantenga constante cuando realizas una animación, o algún valor que no quieres que sea modificado. Considera el siguiente ejemplo:

function animador(){
    var velocidad =  .1;
}

var animcion = new animador();

En este caso hemos creado un constructor (animador()) que contiene una propiedad privada (velocidad). Esta propiedad la hemos puesto privada por que no queremos que la velocidad de animador pueda ser cambiada usando:

animacion.velocidad = .5;

ya que probablemente eso causaría resultados inesperados.

Pero entonces si no se puede acceder a la propiedad, para que nos sirve? Bueno, en realidad para nada, por lo  que es necesario encontrar una forma de poder acceder a la propiedad. Para eso están los método privilegiados.

Como su nombre lo indica, estos métodos tiene privilegios especiales. Piensa en ellos como si tuvieran su propia puerta para entrar y salid del contexto de su contenedor, en este caso miOBj();

Volvamos a nuestro ejemplo el cual hasta ahora va así:

function miObj(){
    var nombre =  'Nombre Privado';//propiedad privada
    function privada(){//Método privado
       alert('función privada');
    }//fin del método privado
}

var obj = new miObj();

Hagamos uno cambios en miObj():

function miObj(){
var nombre =  ‘Nombre Privado’;//propiedad privada
function privada(){//Método privado
alert(‘función privada’);
}//fin del método privado
//agregamos método privilegiado
this.obtenerNombrePrivado = function(){
return nombre
}
}

El método obtenerNombrePrivado() es privilegiado, lo cual quiere decir que puede acceder a los métodos y propiedades privados declarados dentro de miObjt(). Esto tiene que ver con lo que se conoce como scope. Trataré de explicarlo:

Al ser declarada dentro de miObj(), otenerNombrePrivado() tiene acceso a las variables locales de miObj(), en nuestro caso solo tenemos una variable local (nombre). Esto por que al ejecutarse obtenerNombrePrivado() se ejecuta dentro del contexto y las fronteras de miObj() en donde nombre si existe.

Ahora podemos acceder a nuestra propiedad privada (nombre) sin ningún problema, pero sigue siendo imposible cambiarla:

function miObj(){
    var nombre =  'Nombre Privado';//propiedad privada
    function privada(){//Método privado
       alert('función privada');
    }//fin del método privado
    //agregamos método privilegiado
    this.obtenerNombrePrivado = function(){
       return nombre
    }
}
var obj = newObj();
alert(obj.obtenerNombrePrivado());//regresa Nombre Privado

Cabe aclarar que los métodos privilegiados siguen siendo métodos públicos, razón por la cual se pueden acceder desde fuera del objeto.

Métodos Públicos

Los métodos públicos están disponibles desde fuera del objeto. Es decir que son accesibles. Su uso es prácticamente para poder brindar formas de manipular el objeto o de acceder a sus funciones y ejecutar sus comandos. He visto a muchos que hacen lo siguiente para declarar método públicos:

function otroObj(){
    this.publico1 = function(){
       //código de publico1
    }
    this.publico2 = function(){
       //código de publico2
    }
    this.publico3 = function(){
       //código de publico3
    }
    this.publico4 = function(){
       //código de publico4
    }
}

Esto, aun que parezca correcto, es una forma ineficaz de hacerlo. Tener en cuenta que estos no son métodos privilegiados, es decir que no tiene que acceder a ninguna propiedad privada del objeto.

La razón por la que ésta forma de hacer las cosas no es la mejor es por que con cada copia que hagamos de nuestro objeto, estamos “clonando” todas esa funciones y podemos llegar a sobre cargar la memoria. Una de las grandes bondades de Js, es que es un lenguaje basado en prototipos.

Que es un prototipo?
Un prototipo es la forma en que Js nos brinda la oportunidad de extender un objeto. Es decir, a través de un prototipo podemos agregar funcionalidad a un objeto que de otro modo sería poco posible. Al inicio, la palabra prototipo puede sonar un poco intimidatoria. Sin embargo, no hay nada del otro mundo envuelto en esta palabra.

Creando métodos públicos usando prototipos
Para crear un método público de una forma más eficaz, es necesario usar el prototipo de nuestro objeto:

otroObj.prototype.publico1 = function(){
    //código de público 1
}

De esta manera evitamos clonar publico1 cada vez que creamos una nueva copia de otroObj ya que el prototipo no se clona. El prototipo más bien permanece al alcance de los objetos creados a partir del objeto base (otroObj) pero no está contenido dentro de ellos. Piensa en el prototipo como una caja de herramientas que es compartida por un numero determinado de carpinteros. Sin importar cuantos carpinteros agregues, siempre va a seguir habiendo una caja de herramientas y todos los carpinteros tendrán acceso a ella.

Una vez que actualices el prototipo de un objeto, todos los objetos creados a partir de dicho objeto tendrán acceso al prototipo actualizado y no al prototipo existente al momento de ser creados. Volviendo a nuestra analogía con los carpinteros, supongamos que al principio ponemos un carpinteros y una caja de herramientas. La caja de herramientas contiene un serrucho y un martillo. nuestro carpintero puede hacer uso de cualquiera de ellos. Después ponemos otro carpintero, quien a su vez puede hacer uso tanto del martillo como del serrucho. Después “actualizamos” la caja de herramientas y agregamos una lijadora. Ambos carpinteros siguen teniendo acceso a las tres herramientas aun que la caja solo tuviera dos herramientas cuando los carpinteros fueron agregados. Esa es mas o menos la forma en que trabajan los prototipos.

Una forma de hacer uso del prototipo de un objeto es mediante OLN.

otroObj.prototype = {
    publico1: function(){
       //...
    },
    publico2: function(){
      //...
    }
}

De esa manera podemos organizar los prototipos de una mejor manera y ahorramos algunos cuantos caracteres.

Métodos estáticos

Por último hablemos de uno de los tipos de métodos menos comunes, los métodos estáticos. Los métodos estáticos no son de ayuda en la mayoría de los casos. La razón de esto es por que no pueden ser usados más que por el objeto base.  Estos métodos son más bien de utilidad cuando estamos creando un objeto y no un constructor. Ejemplo:

var obj = new Object();

obj.método1 = fucntion(){...}

pero también se pueden usar cuando se están creando constructores:

function miObj(){
    var nombre =  'Nombre Privado';//propiedad privada
    function privada(){//Método privado
       alert('función privada');
    }//fin del método privado
    //agregamos método privilegiado
    this.obtenerNombrePrivado = function(){
       return nombre
    }
}
miObj.estatico = function(){
 alert('estatico');
}
var obj = newObj();

miObj.estatico();// da una alerta: estatico

obj.estatico();// Causa erro: obj.estatico() is not a function

A diferencia del ejemplo que vimos anteriormente en el que con cada copia del objeto clonabamos todos sus métodos públicos, los métodos estáticos no se copian y pertenecen solo al objeto base. Por lo que en nuestro ejemplo, obj.estatico() nos tira un error ya que no hay ninguna función que se llame estatico() relacionada con obj. Por el contrario, miObj.estatico() funciona perfectamente.

Esto nos puede ser útil en algunas ocasiones, especialmente cuando queremos extender un objeto sin afectar a todos los demás que hayan sido creados a partir del mismo objeto.

Hay más cosas que decir en cuanto a los Métodos de un objeto y todavía se nos a quedado en el teclado conceptos como herencia en Js, pero por ahora me despido esperando que haya sido una buena lectura.

19 thoughts on “Javascript Orientado A Objetos Segun Buzu: los métodos

  1. Que tal Buzu, espero que te encuentres bien.. pasaba a dejartee un mensajito xD.. estan muy buenos todos los articulos que publicas deberias publicar mas segido segun el tiempo los permita🙂

    Saludos, suerte

    • Hola, Gracias por el mensajito ^_^ Algunas veces no publico seguido pro que no se me ocurre, si me sigues en twitter, algunas veces pregunto que les gustaría que explicara por aquí. De hecho dos de mis post recientes han sido las sugerencias que he recibido. Si tienes alguna, avísame y hago todo lo posible por publicar sobre ese tema.

      Saludos.

  2. Estos tutoriales sobre javascript y objetos es lo que estaba buscando hacía tiempo.

    Muy útiles y muy bien explicados.

    Saludos.

  3. También me gusta que explicaras, sin profundizar mucho, cual es el uso más común de los objetos en javascript. Más o menos tengo una idea pero me gustaría saber la opinión de un scriptwriter.🙂

    • Hola, gracias por los comentarios. También por la sugerencia sobre algo más para escribir. Ten por seguro que lo haré.

      Saludos.

  4. Excelente amigo. Yo pensaba escribir al respecto pero ya que veo lo hiciste tu y de forma muy completa creo que mejor en uno de mis post recomiendo tu artículo.

    Éxitos y sigue escribiendo.

  5. Ahora una pregunta, estuve trabajando un poco sobre lo que escribiste y me encontré con lo siguiente:

    Si tengo el siguiente codigo:

    var MiFunction = new function (){
    var funcionPrivada = new function(){
    alert(‘HOLA MUNDO …’);
    }

    };

    MiFuncion.prototype = {
    publico1 : function (){
    funcionPrivada();
    }
    }

    Mas respectivamente, me da un error al tratar de acceder a la funcion privada, no se si estoy mal en conceptos de POO en Javascript, es valido, esto mal o simplemente no se puede realizar ??

    Gracias de antemano.

    • Hola. Este mensaje estaba escondido entre el spam. Apenas hoy lo he visto. Lo que está pasando con tu función es que estas tratando de acceder una función que no existe. Para lograr lo que quieres, puedes hacer lo siguiente:

      var miFuncion = function(){
      var funcionPrivada = function(){
      alert(‘u_u’);
      }
      this.retornarFuncionPrivada = function(){
      funciónPrivada();
      }
      }

      Ahora si puedes llamar a retornarFuncion y esta de ejecutará funcionPrivada. Es un concepto muy útil en varias ocasiones.

  6. Valla buzu, seguia tus mensajes usando el buscador de fdw mas no sabía que tenías un blog. Muy interesante el artículo, un saludo!!

  7. Hola buzu mucho gusto, primeramente déjame felicitarte por tu post es muy bueno y una pregunto-ta tu has trabajado con el KineticJS lo que pasa es que quiero utilizar la librería para dibujar unas estructuras pero utilizando POO con javascript, por ejemplo realizo una función publica el cual me dibuja una estructura con canvas en el KineticJS ahora lo que quiero es hacer otra función publica para que me dibuje otra estructura diferente y cuando la segunda estructura pase cerca del la primera esta se agregue de manera automática y re dibuje la primera estructura a lo cual lo que estaría haciendo es acceder a las propiedades del objeto, pero hasta ahora no he podido hacer eso cuando trato de acceder a las propiedades del objeto me dice que la variable es indefinida y no se cual sera el problema tu no podrás orientarme un poco en ese asunto en verdad te lo agradecería mucho, y de ante mano gracias por la atención me gusto mucho el post

    • Hola David, nunca he usado esa libreria, pero puede ser que el objeto no este definido o que sea un prooblema de scope de las variables.

Comments are closed.