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()
.
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.
123456 varPerson=function(name){ thisname=name||'';}; varsinNombre=newPerson();varoscar=newPerson('Oscar');
Veamos lo que hace intrínsecamente este operador (new):
- Se crea el objeto nuevo.
- Se conecta el constructor del nuevo objeto a la función Person.
- Se conecta el prototipo del objeto Object con Person.prototype.
- 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.
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
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.