26. Clases

Versión para imprimir.

En esta lección se introduce el concepto clase.

A. class

Hormiga reina
class Cl1 {
 static saluda() {
  console.log(
   `Hola. Soy ${Cl1.nombre}.`)
 }
}
Cl1.nombre = "vl"
Cl1.seguidores = 3000
Cl1.saluda()

Salida

Hola. Soy vl.

Depúralo en JavaScript Tutor.

B. Prueba de escritorio con un objeto

Versión para imprimir.

class Cl01 {
 constructor(b) {
  this.a = b
 }
 mensaje(c) {
  console.log(c + this.a)
 }
}
const a = new Cl01(4)
a.mensaje(2)

Salida

6

1. class Cl01

Código

1 class Cl01 {
    constructor(b) {
     this.a = b
    }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a = new Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11

Heap

1
1: class
name Cl01

Explicación

  1. Se crea un registro de activación para el script.
  2. Se crea la clase Cl01 en el Heap.
  3. En el registro de activación del script se crea la referencia Cl01 que apunta a la clase Cl01.

2. new

Código

1 class Cl01 {
    constructor(b) {
     this.a = b
    }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11

Heap

1
1: class
name Cl01
2
2: Cl01

Explicación

3. Cl01(4)

Código

1 class Cl01 {
    constructor(b) {
     this.a = b
    }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new3Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela

Heap

1
1: class
name Cl01
2
2: Cl01

Expresiones

3new Cl01(4)
  2   Cl01(4)

Explicación

  1. Se invoca el constructor.
  2. Se congela el registro de Script en el stack.
  3. En expresiones se indica el paso de parámetros. En vez de new se sustituye el id del objeto creado, que en este caso es 2.

4. constructor(b)

Código

1 class Cl01 {
4  constructor(b) {
     this.a = b
    }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new3Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4

Heap

1
1: class
name Cl01
2
2: Cl01

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)

Explicación

  1. Se crea el registro de activación para el constructor de Cl01.
  2. Se realiza el paso de parámetros.
    • El resultado de new, que en este caso es 2, se pasa a this.
    • El primer parámetro de la invocación, que es 4, se pasa al primer parámetro del constructor, que es b.

5. this.a = b

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
    }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new3Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4

Explicación

  • Se asigna el valor de la variable b en el registro de activación, a la variable a en el objeto apuntado por this.

6. }

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new3Cl01(4)
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4

Explicación

7. new Cl01(4) → 2

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
   const a =2new3Cl01(4)72
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4

Explicación

8. a = 2

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
8 const a =2new3Cl01(4)72
   a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4

Explicación

9. a.mensaje(2)

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
    mensaje(c) {
     console.log(c + this.a)
    }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)

Explicación

  1. Se invoca el método a.mensaje.
  2. Se congela el registro de Script en el stack.
  3. En expresiones se indica el paso de parámetros. Se sustituye el valor de a, que en este caso es la referencia 2.

10. mensaje(c) {

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
10 mensaje(c) {
     console.log(c + this.a)
    }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela
10
Cl01.mensaje
10 this 10 2
10 c 10 2

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)
10this.mensaje(c)

Explicación

  1. Se crea el registro de activación para Cl01.mensaje.
  2. Se realiza el paso de parámetros.
    1. El valor de a, que en este caso es la referencia 2, se pasa a this.
    2. El primer parámetro de la invocación, que es 2, se pasa al primer parámetro del constructor, que es c.

11. c + this.a

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
10 mensaje(c) {
     console.log(11c + this.a)
    }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela
10
Cl01.mensaje
10 this 10 2
10 c 10 2

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)
10this.mensaje(c)
11c + this.a
   2 + 4
     6

Explicación

12. console.log(c + this.a)

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
10 mensaje(c) {
12  console.log(11c + this.a)
    }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela
10
Cl01.mensaje
10 this 10 2
10 c 10 2

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Consola

12 6

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)
10this.mensaje(c)
11c + this.a
   2 + 4
     6

Explicación

13. }

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
10 mensaje(c) {
12  console.log(11c + this.a)
13 }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela
10
Cl01.mensaje
10 this 10 2
10 c 10 2
13 X

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Consola

12 6

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)
10this.mensaje(c)
11c + this.a
   2 + 4
     6

Explicación

14. Descongela y termina

Código

1 class Cl01 {
4  constructor(b) {
5   this.a = b
6  }
10 mensaje(c) {
12  console.log(11c + this.a)
13 }
   }
8 const a =2new3Cl01(4)72
9 a.mensaje(2)14

Stack

1
Script
1Cl01 11
3congela
4
Cl01 (constructor)
4 this 4 2
4 b 4 4
6 X devuelve 2.
7 descongela 3 con 2
8a 82
9congela
10
Cl01.mensaje
10 this 10 2
10 c 10 2
13 X
14 descongela 9
14 X

Heap

1
1: class
name Cl01
2
2: Cl01
5a 54

Consola

12 6

Expresiones

3new Cl01(4)
  2   Cl01(4)
4this Cl01(b)
5this.a = b
   2  .a = 4
9a.mensaje(2)
  2.mensaje(2)
10this.mensaje(c)
11c + this.a
   2 + 4
     6

Explicación

  1. Descongela el último registro de activación congelado en el stack.

  2. Como no hay más instrucciones, Elimina el registro de activación y termina el programa.

15. Depura con JavaScript Tutor

C. Clases e instancias

class Cl2 {
 static saludaClase() {
  console.log(
   `Hola. Clase ${Cl2.nombre}.`)
 }
 saludaInstancia() {
  console.log(
   `Hola. Instancia ${this.nom}`)
 }
}
Cl2.nombre = "QK"
const t1 = new Cl2()
t1.nom = "qkita1"
const t2 = new Cl2()
t2.nom = "qkita2"
Cl2.saludaClase()
t1.saludaInstancia()
t2.saludaInstancia()

Salida

Hola. Clase QK.
Hola. Instancia qkita1
Hola. Instancia qkita2

Depúralo en JavaScript Tutor.

D. Getters y setters

En JavaScript por el momento todos los miembros de una clase son públicos, pero se pueden usar convenciones para indicar niveles de acceso.

Como hay varias convenciones, usaremos las del compilador de TypeScript, que Visual Studio Code puede usar para validar el acceso.

@public

Es el valor predefinido e indica que el miembro puede usarse desde cualquier parte del código.

@private
_miembro

El miembro solo debe usarse dentro de la clase que lo define.

@protected

El miembro solo debe usarse dentro de la clase que lo define y subclases.

Ejemplo

class ClX {
 constructor() {
  /** @private */
  this._nombre = ""
 }
 get nombre() {
  return (this._nombre)
 }
 set nombre(nombre) {
  this._nombre = nombre
 }
 /** @public */
 get juega() {
  return (`${this.nombre} juega`)
 }
}
const tt1 = new ClX()
tt1.nombre = "pp"
console.log(tt1.nombre)
console.log(tt1.juega)

Salida

pp
pp juega

E. Resumen