DE .NET, SQLSERVER Y MÁS, APRENDE CONMIGO!✔

Desarrollo de todo tipo de aplicaciones y Administración de Base de datos con Tecnología Microsoft


UNETE

Herencia en JavaScript

0

 



Prototipos

Pero claro, con esto solo definimos un único objeto, con sus atributos y métodos. Pero, ¿qué pasa si queremos crear una “clase” de la que poder instanciar objetos? Como hemos dicho antes, en Javascript no hay clases, sino prototipos: objetos de los que se copian otros objetos. Así que lo que haremos es crear un objeto del que poder copiar sus propiedades. Para esto Javascript tiene un gran truco: hace que cualquier función pueda ser instanciada como un nuevo objeto usando la palabra clave “new”.

1

// Una simple función

2

function Saludator() {

 

3

    alert("Saludos factory!!")

4

}

 

5

// Y una simple llamada

6

Saludator()

A simple vista no es más que una función, ¡y es verdad que lo es! pues podemos llamar a Saludator() como una función de toda la vida. Pero eso no quita que sea también una factoría y que con ella podamos crear nuevos objetos:

1

// Una función... pero también un prototipo!

2

function Saludator() {

 

3

    alert("Saludos factory!!")

4

}

 

5

// Un nuevo objeto a partir de su "clase" prototipo

6

var saludo = new Saludator()

Pero claro, con este ejemplo tan sumamente sencillo no se aprecia que hemos creado un nuevo objeto. Así que vamos a añadirle un par de propiedades y métodos (recordemos que solo tenemos que declararlas con el prefijo this).

01

function Saludator(nom) {

02

    alert("Saludos factory!!")

 

03

    this.nombre = nom+"s"

04

    this.saluda = function() {

 

05

        alert("hola "+this.nombre)

06

    }

 

07

}

08

var obj1 = new Saludator("mundo")

 

09

var obj2 = new Saludator("gente")

10

obj1.saluda() // "hola mundos"

 

11

obj2.saluda() // "hola gentes"

En este ejemplo ya vemos cosas nuevas:
– Que la función Saludator() es el constructor del objeto, y podemos pasarle parámetros que posteriormente podemos usar en los atributos del objeto.
– Que dentro de la función saluda sigue siendo necesario usar this.nombre para acceder al atributo nombre.

Por cierto, podemos crear nuestros prototipos usando funciones como expresiones, y no como declaraciones. El siguiente código es completamente equivalente al anterior:

1

var Saludator = function(nom) {

2

    alert("Saludos factory!!")

 

3

    this.nombre = nom+"s"

4

    this.saluda = function() {

 

5

        alert("hola "+this.nombre)

6

    }

 

7

}

Es necesario señalar que las funciones que servirán para crear objetos se suelen nombrar con la primera letra en mayúscula. Esto es así para evitar que se confundan con funciones normales o variables.

Herencia

Como hemos dicho antes, la herencia basada en clases no existe en Javascript, sino que es herencia basada en prototipos. Esto significa que no hay una jerarquía de clases real (con su extends, acceso super, etc.), sino que cada “clase” tiene un objeto de referencia (como si fuera su clase padre) donde consultar atributos y métodos en caso de que nuestra clase no los encuentre. Podemos intentar simular una jerarquía (ojo, simular) usando estos objetos de referencia, llamados prototipos, con una propiedad especial que tienen todas las “clases” llamada prototype. Esta propiedad es asignable y su labor consiste en guardar un objeto. Veámoslo con un ejemplo:

01

var Saludator = function(nom) {

02

    this.nombre = nom

 

03

    this.saluda = function() {

04

        alert("hola "+this.nombre)

 

05

    }

06

}

 

07

// Añade un objeto al prototipo

08

Saludator.prototype = {

 

09

    apellido: "cruel",

10

    despide: function() {

 

11

        alert("adios "+this.nombre+" "+this.apellido)

12

    }

 

13

}

14

var obj1 = new Saludator("mundo")

 

15

obj1.despide() // "adios mundo cruel"

Con esto lo que hacemos es asignar a la variable estática prototype en la clase Saludator un simple objeto con un atributo apellido y un método despide. Cuando invocamos a obj1.despide(), Javascript primero consulta en la propia clase Saludator y busca ese método; al no encontrarlo, consulta en el objeto prototype, donde si lo encuentra, por lo que lo ejecuta. Dentro de este método, se accede a this.nombre y this.apellido y sucede lo mismo: primero Javascript mira en la clase Saludator, donde solo encuentra el atributo nombre. Sin embargo, para encontrar el atributo apellido debe consultar en el objeto prototype.

Todas las clases tienen por defecto un objeto prototype vacío, como si al crearlas se hiciera prototype = {}. Por esta razón, podemos acceder a esta variable y asignarle los atributos de uno en uno. El siguiente ejemplo es completamente equivalente al anterior:

01

var Saludator = function(nom) {

02

    this.nombre = nom

 

03

}

04

// Añade nuevas propiedades al prototipo

 

05

Saludator.prototype.apellido = "cruel"

06

Saludator.prototype.despide = function() {

 

07

    alert("adios "+this.nombre+" "+this.apellido)

08

}

 

09

 

10

var obj1 = new Saludator("mundo")

 

11

obj1.despide() // "adios mundo cruel"

El problema de la herencia basada en prototipos es que la “clase padre” no es una clase, sino un objeto que se crea una única vez y que sirve de referencia para todas las instancias de la clase. Además, en una herencia basada en clases como la de Java, los constructores de las clases padre se heredan automáticamente (aunque no se invocan al instanciar nuevos objetos), pero en una de prototipos no. Así que para poder heredar e invocar constructores en Javascript tenemos que hacerlo a mano. Primero debemos crear una referencia al constructor de la clase padre y después llamarlo explícitamente:

01

var Saludator = function(nom) {

02

    this.nombre = nom

 

03

    this.saluda = function() {

04

        alert("hola "+this.nombre)

 

05

    }

06

}

 

07

var SubSaludator = function(nom, ape) {

08

    // Primero se añade una referencia al constructor padre,

 

09

    // y después se llama explícitamente.

10

    this.superConstructor = Saludator

 

11

    this.superConstructor(nom)

12

     

 

13

    this.apellido = ape

14

    this.despide = function() {

 

15

        alert("adios "+this.nombre+" "+this.apellido)

16

    }

 

17

}

18

SubSaludator.prototype = new Saludator()

 

19

 

20

var obj1 = new SubSaludator("mundo", "cruel")

 

21

var obj2 = new SubSaludator("gente", "cruel")

22

 

 

23

obj1.saluda()  // "hola mundo"

24

obj2.saluda()  // "hola gente"

 

25

obj1.despide() // "adios mundo cruel"

26

obj2.despide() // "adios gente cruel"

Finalmente decir que podemos acceder al atributo prototype en todas clases, incluso en las clases del sistema, como String o Date. El siguiente código añade un nuevo método capitalize() a la clase de sistema String:

1

String.prototype.capitalize = function() {

2

    return this.charAt(0).toUpperCase() + this.substr(1).toLowerCase();

 

3

}

4

 

 

5

alert("hola".capitalize())

DEMOSTRACIÓN

En el espacio de nombre del proyecto creado anteriormente damos click derecho y seleccionamos Add à New Items


En la siguiente ventana seleccionamos la Opción “Pagina HTML” y colocamos como nombre del archivo “Encapsulacion.html”, para luego presionar el botón Add.



Empezamos a declarar nuestro Objeto llamado “Persona”

Al ejecutar en nuestro navegador:


Sobrescribimos la función usando los prototipos

Y el resultado es el siguiente


Ahora crearemos una clase de nombre “Estudiante” que herede de “Persona” a través de los prototipos, el código completo quedaría de la siguiente manera:



Y terminamos nuestro ejemplo viendo los resultados en la consola del navegador














Tal vez te interesen estas entradas

No hay comentarios