JavaScript Desmitificado: Objetos

Publicado el 17 febrero 2014 por Codehero @codeheroblog

Historia

Javascript apareció por primera vez al público como parte del explorador Netscape Navigator 2.0 en 1996. Y luego, al año siguiente, fue estandarizado por ECMA International llamándolo ECMAScript.

Lo que conocemos como JavaScript hoy en día es una implementación de la especificación de lenguaje ECMAScript, de la cual cambien derivan lenguajes como ActionScript, JScript, TypeScript, etc.

La especificación de ECMAScript cambia con el tiempo, introduciendo soluciones a viejos problemas y soporte para nuevas tecnologías.

Javascript es un lenguaje de scripting y a la vez orientado a objetos, que aunque su nombre incluye “Java” no tiene nada o poco que ver con el lenguaje Java, de hecho, inicialmente iba a llamarse LifeScript, pero tras los acuerdos entre Sun Microsystems y Netscape decidieron llamarlo JavaScript para mercadearlo como un complemento de scripting del lenguaje Java.

A pesar de que inicialmente fue pensado como un lenguaje de scripting para exploradores hoy podemos ver JavaScript del lado del servidor con Node.js

Entonces, como todo el mundo “sabe” JavaScript no voy a empezar esta serie explicando cosas básicas como crear variables, operaciones, condicionales o ciclos. Vamos directo a lo que nos interesa.


Objetos

El enfoque orientado a objetos de JavaScript es un poco diferente al que podemos ver en otros lenguajes que implementan el paradigma.

Existen tres maneras de hacer una instancia de un objeto en javascript:

  • La forma literal: var x = {};. Con esto creamos un objeto vacío.
  • Utilizando el operador new: var x = new Object();.
  • Utilizando la función create: baz = Object.create(null);.

A continuación explico las diferencias de crear objetos con estas tres formas diferentes.

Objetos literales

La forma literal es permite describir objetos de manera clara y compacta. Puedes describir objetos entre llaves con propiedades separadas por comas. Esta forma no es invocada explícitamente, es solo un atajo para usar el método Object.create().

var card = { name: 'Oscar' }; var card2 = Object.create(Object.prototype, { bar: { name: 'Oscar' } }); console.log(card.bar); // -> Oscar console.log(card2.bar); // -> Oscar

1234567891011 varcard={  name:'Oscar'};varcard2=Objectcreate(Objectprototype,{  bar:{  name:'Oscar'}}); consolelog(cardbar);// -> Oscar consolelog(card2bar);// -> Oscar

Por ser tan simple la forma literal es que el constructor del objeto no puede ser redefinido, de modo que no se puede definir un objeto cuyo prototipo sea diferente al por defecto. Ya explicaré lo que es el prototipo más adelante.

Objetos con operador new

El operador new crea una instancia de un objeto. Este acepta un constructor y una serie de argumentos opcionales.

var Person = function (name) { this.name = name || ''; }; var sinNombre = new Person(); var oscar = new Person('Oscar');

123456 varPerson=function(name){  thisname=name||'';}; varsinNombre=newPerson();varoscar=newPerson('Oscar');

Veamos lo que hace intrínsecamente este operador (new):

  1. Se crea el objeto nuevo.
  2. Se conecta el constructor del nuevo objeto a la función Person.
  3. Se conecta el prototipo del objeto Object con Person.prototype.
  4. Se asigna cualquier argumento pasado a la función al objeto creado.

Este enfoque le da al lenguaje un estilo de “clases” que confunde a mucha gente, porque realmente no existen las clases en Javascript como las conocemos en otros lenguajes como Java, C#, Objective-C. En Javascript hay solo objetos que pueden ser extendidos.

Objetos con Object.create()

Esta forma fue introducida en ECMAScript 5. Basicamente hace lo mismo que la forma con el operador new, solo que esta tiene sintaxis más consistente con el resto del lenguaje, ademas de facilitar la herencia por prototipo.

var Person = { introduce: function(age) { console.log( 'Hola, mi nombre es ' + this.name + ' y tengo ' + age + ' años de edad'); } }; var oscar = Object.create(Person, { 'name': { value: 'Oscar' } }); oscar.introduce(26);

1234567891011121314 varPerson={  introduce:function(age){  consolelog('Hola, mi nombre es '+thisname+' y tengo '+age+' años de edad');   }}; varoscar=Objectcreate(Person,{  'name':{  value:'Oscar'  }});  oscarintroduce(26);

realmente no existen las clases en Javascript como las conocemos en otros lenguajes (…) hay solo objetos que pueden ser extendidos

Extendiendo objetos

JavaScript es un lenguaje muy flexible. Permite agregar funciones y propiedades a objetos de manera dinámica sin mucho esfuerzo.

var Person = function (name) { this.name = name || ''; this.introduce = function() { return 'Hola, mi nombre es ' + this.name; }; }; // Creando una nueva persona var oscar = new Person('Oscar'); // Agregando atributo nuevo oscar.lastname = 'González'; // Agregando una función nueva oscar.introduceFull = function () { return this.introduce() + ' ' + this.lastname; }; console.log(oscar.introduceFull()); // -> "Hola, mi nombre es Oscar González"

123456789101112131415161718192021 varPerson=function(name){    thisname=name||'';    thisintroduce=function(){  return'Hola, mi nombre es '+thisname;  };}; // Creando una nueva personavaroscar=newPerson('Oscar'); // Agregando atributo nuevooscarlastname='González'; // Agregando una función nuevaoscarintroduceFull=function(){  returnthisintroduce()+' '+thislastname;}; consolelog(oscarintroduceFull());// -> "Hola, mi nombre es Oscar González"

Esta es una manera de expresar herencia de objetos. Un tanto extraño porque estamos acostumbrados a herencia de clases.

Prototipos

Los prototipos permiten conectar entre si a los objetos. JavaScript usa una cadena de prototipos, de manera que, cuando intentas hacer una referencia una propiedad, se viaja a través de la cadena hasta alcanzar la en la conexión correcta. Se puede acceder al prototipo de un objeto de la siguiente manera:

  • Person.prototype define el prototipo para un objeto instanciado con el operador new
  • Object.getPrototypeOf(oscar) retorna el prototipo de un objeto
var Person = function (name) { this.name = name || ''; }; var oscar = new Person('Oscar'); var pepe = new Person('Pepe'); // Definiendo una función por el prototipo afecta todas las instancias de un objeto Person.prototype.introduce = function() { return 'Hola, mi nombre es ' + this.name; }; console.log(oscar.introduce()); console.log(pepe.introduce()); // Definir una función con el mismo nombre solo afecta al objeto localmente oscar.introduce = function() { return 'Hola, mi nombre alreves es ' + this.name.split("").reverse().join(""); }; console.log(oscar.introduce()); console.log(pepe.introduce()); // no afecta porque las propiedades locales tienen preferencia Person.prototype.name = 'Jose'; console.log(oscar.introduce()); console.log(pepe.introduce());

1234567891011121314151617181920212223242526272829 varPerson=function(name){    thisname=name||'';}; varoscar=newPerson('Oscar');varpepe=newPerson('Pepe'); // Definiendo una función por el prototipo afecta todas las instancias de un objetoPersonprototypeintroduce=function(){  return'Hola, mi nombre es '+thisname;}; consolelog(oscarintroduce());consolelog(pepeintroduce()); // Definir una función con el mismo nombre solo afecta al objeto localmenteoscarintroduce=function(){  return'Hola, mi nombre alreves es '+thisnamesplit("")reverse()join("");}; consolelog(oscarintroduce());consolelog(pepeintroduce()); // no afecta porque las propiedades locales tienen preferenciaPersonprototypename='Jose'; consolelog(oscarintroduce());consolelog(pepeintroduce());

Propiedades y métodos privados

En ejemplos anteriores hemos visto como se crean propiedades y métodos públicos. Veamos ahora los privados.

var Person = function (name) { // propiedad pública this.name = name || ''; // propiedad privada var lastname = 'González'; // propiedad privada var myName = this.name; // método privado var fullName = function () { return myName + ' ' + lastname; } // método público this.introduce = function() { return 'Hola, mi nombre es ' + fullName(); }; }; var oscar = new Person('Oscar'); console.log(oscar.name); // -> "Oscar" console.log(oscar.introduce());// -> "Hola, mi nombre es Oscar González" console.log(oscar.lastname); // -> undefined console.log(oscar.fullName()); // Error: -> "Object [object Object] has no method 'fullName'"

1234567891011121314151617181920212223242526272829 varPerson=function(name){    // propiedad pública  thisname=name||'';    // propiedad privada  varlastname='González';    // propiedad privada  varmyName=thisname;    // método privado  varfullName=function(){  returnmyName+' '+lastname;  }    // método público  thisintroduce=function(){  return'Hola, mi nombre es '+fullName();  };  }; varoscar=newPerson('Oscar'); consolelog(oscarname);// -> "Oscar"consolelog(oscarintroduce());// -> "Hola, mi nombre es Oscar González"consolelog(oscarlastname);// -> undefinedconsolelog(oscarfullName());// Error: -> "Object [object Object] has no method 'fullName'"


Conclusión

En este tutorial he presentado los fundamentos de los objetos en JavaScript. Por supuesto que todavía se puede decir mucho más sobre el tema, pero pasaríamos días hablando. Con esto es mas que suficiente para estar, como dicen, “up and running” con el paradigma POO en JavaScript.

Dudas o comentarios pueden ser dejados en la sección correspondiente más abajo.

Si te ha gustado esta publicación, ayudamos compartiéndola en tus redes sociales favoritas.

Saludos.