1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
|
---
title: Clases
slug: Web/JavaScript/Reference/Classes
tags:
- Classes
- ECMAScript 2015
- Herencia
- Intermedio
- JavaScript
- NeedsContent
- NeedsTranslation
- Reference
- TopicStub
translation_of: Web/JavaScript/Reference/Classes
original_slug: Web/JavaScript/Referencia/Classes
---
<div>{{JsSidebar("Classes")}}</div>
<p>Las clases de javascript, introducidas en ECMAScript 2015, son una mejora sintáctica sobre la herencia basada en prototipos de JavaScript. La sintaxis de las clases <strong>no</strong> introduce un nuevo modelo de herencia orientada a objetos en JavaScript. Las clases de JavaScript proveen una sintaxis mucho más clara y simple para crear objetos y lidiar con la herencia.</p>
<h2 id="Definiendo_clases">Definiendo clases</h2>
<p>Las clases son "<a href="/en-US/docs/Web/JavaScript/Reference/Functions">funciones</a> especiales", como las <a href="/en-US/docs/Web/JavaScript/Reference/Operators/function">expresiones de funciones</a> y <a href="/en-US/docs/Web/JavaScript/Reference/Statements/function">declaraciones de funciones</a>, la sintaxis de una clase tiene dos componentes: <a href="/en-US/docs/Web/JavaScript/Reference/Operators/class">expresiones de clases</a> y <a href="/en-US/docs/Web/JavaScript/Reference/Statements/class">declaraciones de clases</a>.</p>
<h3 id="Declaración_de_clases">Declaración de clases</h3>
<p>Una manera de definir una clase es mediante una <strong>declaración de clase</strong><em>. </em>Para declarar una clase, se utiliza la palabra reservada <code>class</code> y un nombre para la clase "Rectangulo".</p>
<pre class="brush: js notranslate">class Rectangulo {
constructor(alto, ancho) {
this.alto = alto;
this.ancho = ancho;
}
}</pre>
<h4 id="Alojamiento">Alojamiento</h4>
<p>Una importante diferencia entre las <strong>declaraciones de funciones</strong><em> y </em>las <strong>declaraciones de clases</strong> es que las <strong>declaraciones de funciones</strong><em> </em>son alojadas y las <strong>declaraciones de clases</strong><em> </em>no lo son. En primer lugar necesitas declarar tu clase y luego acceder a ella, de otro modo el ejemplo de código siguiente arrojará un {{jsxref("ReferenceError")}}:</p>
<pre class="brush: js example-bad notranslate">const p = new Rectangle(); // ReferenceError
class Rectangle {}
</pre>
<h3 id="Expresiones_de_clases">Expresiones de clases</h3>
<p>Una <strong>expresión de clase</strong> es otra manera de definir una clase. Las expresiones de clase pueden ser nombradas o anónimas. El nombre dado a la <strong>expresión de clase</strong> nombrada es local dentro del cuerpo de la misma.</p>
<pre class="notranslate">// Anonima
let Rectangulo = class {
constructor(alto, ancho) {
this.alto = alto;
this.ancho = ancho;
}
};
console.log(Rectangulo.name);
// output: "Rectangulo"
// Nombrada
let Rectangulo = class Rectangulo2 {
constructor(alto, ancho) {
this.alto = alto;
this.ancho = ancho;
}
};
console.log(Rectangulo.name);
// output: "Rectangulo2"
</pre>
<div class="blockIndicator note">
<p><strong>Nota:</strong> Las <strong>expresiones</strong> de clase están sujetas a las mismas restricciones de elevación que se describen en la sección {{anch("Class declarations")}}.</p>
</div>
<h2 id="Cuerpo_de_la_clase_y_definición_de_métodos">Cuerpo de la clase y definición de métodos</h2>
<p>El contenido<em> </em>de una <strong>clase </strong>es la parte que se encuentra entre las llaves <code>{}</code>. Este es el lugar se definen los <strong>miembros de clase,</strong> como los <strong>métodos </strong>o <strong>constructores.</strong></p>
<h3 id="Modo_estricto">Modo estricto</h3>
<p>El cuerpo de las <em>declaraciones de clase</em> y las <em>expresiones de clase</em> son ejecutadas en <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode">modo estricto.</a> En otras palabras, el código escrito aquí está sujeto a una sintaxis más estricta para aumentar el rendimiento, se arrojarán algunos errores silenciosos y algunas palabras clave están reservadas para versiones futuras de ECMAScript.</p>
<h3 id="Constructor">Constructor</h3>
<p>El método <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/constructor">constructor</a></code> es un método especial para crear e inicializar un objeto creado con una <code>clase</code>. Solo puede haber un método especial con el nombre "constructor" en una clase. Si esta contiene mas de una ocurrencia del método <code><strong>constructor, </strong></code>se arrojará un <em>Error </em>{{jsxref("SyntaxError")}}</p>
<p>Un <strong>constructor</strong> puede usar la <em>palabra reservada</em> <strong><code>super </code></strong>para llamar al <strong>constructor </strong>de una <em>superclase</em></p>
<h3 id="Métodos_prototipo">Métodos prototipo</h3>
<p>Vea también <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions">métodos definidos</a>.</p>
<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">class Rectangulo {
constructor (alto, ancho) {
this.alto = alto;
this.ancho = ancho;
}
// Getter
get area() {
return this.calcArea();
}
// Método
calcArea () {
return this.alto * this.ancho;
}
}
const cuadrado = new Rectangulo(10, 10);
console.log(cuadrado.area); // 100</code></pre>
<div class="syntaxbox"></div>
<h3 id="Métodos_estáticos">Métodos estáticos</h3>
<p>La <em>palabra clave</em> <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/static">static</a></code> define un método estático para una clase. Los métodos estáticos son llamados sin instanciar su clase y <strong>no</strong> pueden ser llamados mediante una instancia de clase. Los métodos estáticos son a menudo usados para crear funciones de utilidad para una aplicación.</p>
<pre class="brush: js notranslate">class Punto {
constructor ( x , y ){
this.x = x;
this.y = y;
}
static distancia ( a , b) {
const dx = a.x - b.x;
const dy = a.y - b.y;
return Math.sqrt ( dx * dx + dy * dy );
}
}
const p1 = new Punto(5, 5);
const p2 = new Punto(10, 10);
console.log (Punto.distancia(p1, p2)); // 7.0710678118654755</pre>
<h3 id="Boxing_con_prototipos_y_métodos_estáticos">"Boxing" con prototipos y métodos estáticos</h3>
<p>Cuando un método estático o método del prototipo es llamado sin un valor para "this" (o con "this" como booleano, cadena, número, undefined o null), entonces el valor de "this" será <strong>undefined</strong> dentro de la funciona llamada. <em>Autoboxing </em>no ocurrirá. El comportamiento será igual inclusive si se escribe el código en modo no estricto.</p>
<pre class="notranslate"><code>class Animal {
hablar() {
return this;
}
static comer() {
return this;
}
}
let obj = new Animal();
obj.hablar(); // Animal {}
let hablar = obj.hablar;
hablar(); // undefined
Animal.comer() // class Animal
let comer = Animal.comer;
comer(); // undefined</code></pre>
<p>Si se escribe el código del cuadro superior usando clases función tradicionales, entonces autoboxing ocurrirara porque tomará valor de "this" sobre la función que es llamada.</p>
<pre class="notranslate"><code>function Animal() { }
Animal.prototype.hablar = function(){
return this;
}
Animal.comer = function() {
return this;
}
let obj = new Animal();
let hablar = obj.hablar;
hablar(); // global object
let hablar = Animal.hablar;
hablar(); // global object</code></pre>
<h2 id="Subclases_con_extends">Subclases con <code>extends</code></h2>
<p>La palabra clave <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/extends">extends</a></code> es usada en <em>declaraciones de clase</em> o <em>expresiones de clase</em> para crear una clase hija.</p>
<pre class="brush: js notranslate"><code>class Animal {
constructor(nombre) {
this.nombre = nombre;
}
hablar() {
console.log(this.nombre + ' hace un ruido.');
}
}
class Perro extends Animal {
hablar() {
console.log(this.nombre + ' ladra.');
}
}</code></pre>
<p>También se pueden extender las clases tradicionales basadas en funciones:</p>
<pre class="brush: js notranslate">function Animal (nombre) {
this.nombre = nombre;
}
Animal.prototype.hablar = function () {
console.log(this.nombre + 'hace un ruido.');
}
class Perro extends Animal {
hablar() {
super.hablar();
console.log(this.nombre + ' ladra.');
}
}
var p = new Perro('Mitzie');
p.hablar();</pre>
<p>Fijarse que las clases no pueden extender objectos regulares (literales). Si se quiere heredar de un objecto regular, se debe user {{jsxref("Object.setPrototypeOf()")}}::</p>
<pre class="notranslate"><code>var Animal = {
hablar() {
console.log(this.nombre + ' hace ruido.');
},
comer() {
console.log(this.nombre + ' se alimenta.');
}
};
class Perro {
constructor(nombre) {
this.nombre = nombre;
}
hablar() {
console.log(this.nombre + ' ladra.');
}
}
// Solo adjunta los métodos aún no definidos
Object.setPrototypeOf(Perro.prototype, Animal);
var d = new Perro('Mitzie');
d.hablar(); // Mitzie ladra.
d.comer(); // Mitzie se alimenta.</code></pre>
<h2 id="Especies">Especies</h2>
<p>Quizás se quiera devolver objetos {{jsxref("Array")}} derivados de la clase array MyArray. El patron <em>species</em> permite sobreescribir constructores por defecto.</p>
<p>Por ejemplo, cuando se usan metodos del tipo {{jsxref("Array.map", "map()")}} que devuelven el constructor por defecto, se quiere que esos métodos devuelvan un objeto padre Array, en vez de MyArray. El símbolo {{jsxref("Symbol.species")}} permite hacer:</p>
<pre class="brush: js notranslate"><code>class MyArray extends Array {
// Sobreescribe species sobre el constructor padre Array
static get [Symbol.species]() { return Array; }
}
var a = new MyArray(1,2,3);
var mapped = a.map(x => x * x);
console.log(mapped instanceof MyArray); // false
console.log(mapped instanceof Array); // true</code>
</pre>
<h2 id="Llamadas_a_súperclases_con_super">Llamadas a súperclases con <code>super</code></h2>
<p>La palabra clave <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/super">super</a></code> es usada para llamar funciones del objeto padre.</p>
<pre class="notranslate"><code>class Gato {
constructor(nombre) {
this.nombre = nombre;
}
hablar() {
console.log(this.nombre + ' hace ruido.');
}
}
class Leon extends Gato {
hablar() {
super.hablar();
console.log(this.nombre + ' maulla.');
}
}</code></pre>
<h2 id="Mix-ins">Mix-ins</h2>
<p>Subclases abstractas or <em>mix-ins</em> son plantillas de clases. Una clase ECMAScript solo puede tener una clase padre, con lo cual la herencia multiple no es posible. La funcionalidad debe ser proporcionada por la clase padre.</p>
<p>Una función con una clase padre como entrada y una subclase extendiendo la clase padre como salida puede ser usado para implementar mix-ins en EMCAScript:</p>
<pre class="brush: js notranslate"><code>var calculatorMixin = Base => class extends Base {
calc() { }
};
var randomizerMixin = Base => class extends Base {
randomize() { }
};</code></pre>
<p>Una clase que use este método puede ser escrita tal que así:</p>
<pre class="brush: js notranslate"><code>class Foo { }
class Bar extends calculatorMixin(randomizerMixin(Foo)) { }</code></pre>
<h2 id="Especificaciones">Especificaciones</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-class-definitions', 'Class definitions')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td>Initial definition.</td>
</tr>
</tbody>
</table>
<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2>
<p>{{CompatibilityTable}}</p>
<div id="compat-desktop">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Chrome</th>
<th>Firefox (Gecko)</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatChrome(42.0)}}</td>
<td>Available in the Nightly channel only (since February 2015)</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
</tr>
</tbody>
</table>
</div>
<div id="compat-mobile">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Android</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Mobile</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
<th>Chrome for Android</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatNo}}</td>
<td>Available in the Nightly channel only (since February 2015)</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatUnknown}}</td>
<td>{{CompatChrome(42.0)}}</td>
</tr>
</tbody>
</table>
</div>
<h2 id="Ver_también">Ver también</h2>
<ul>
<li><a href="/es/docs/Web/JavaScript/Referencia/Funciones">Funciones</a></li>
<li>{{jsxref("Statements/class", "class declaration")}}</li>
<li>{{jsxref("Operators/class", "class expression")}}</li>
<li>{{jsxref("Operators/super", "super")}}</li>
</ul>
|