Comprender ECMAScript 6: clase y herencia
Me gustaría compartir con ustedes una serie de artículos sobre ECMAScript 6, compartiendo mi pasión por ella y explicándote cómo puede funcionar para ti. Espero que disfrutéis leyéndolos tanto como yo escribiéndolos.
Primero, trabajo en Microsoft en el motor de renderizado del navegador para proyecto espartano, que es una gran mejora con respecto al motor de Internet Explorer que conocemos (¿y nos encanta?) a lo largo de los años. Mi característica favorita personal es que admite una gran cantidad de ECMAScript 6. Para mí, este es un gran beneficio para escribir aplicaciones grandes para la web. Ahora tenemos casi el 70% de ECMAScript 6 características en Project Spartan hasta ahora según http://kangax.github.io/compat-table/es6/ y ES6 en estado.moderno.IE.
Me encanta JavaScript, pero cuando se trata de trabajar en proyectos grandes como Babylon.js, prefiero Mecanografiado que es ahora alimentando Angular 2 por cierto. La razón es que JavaScript (o también conocido como ECMAScript 5) no tiene todas las funciones de sintaxis a las que estoy acostumbrado en otros lenguajes en los que escribo proyectos grandes. Echo de menos las clases y la herencia, por ejemplo. Entonces, sin más preámbulos, entremos en eso:
Creando una clase
JavaScript es un lenguaje orientado a prototipos y es posible simular clases y herencia con ECMAScript 5. La flexibilidad de las funciones en JavaScript nos permite simular la encapsulación a la que estamos acostumbrados cuando tratamos con clases. El truco que podemos usar para eso es extender el prototipo de un objeto:
var Animal = (function () {
function Animal(name) {
this.name = name;
}
// Methods
Animal.prototype.doSomething = function () {
console.log("I'm a " + this.name);
};
return Animal;
})();
var lion = new Animal("Lion");
lion.doSomething();
Podemos ver aquí que definimos un “clase» con «propiedades» y «métodos”. El constructor está definido por la propia función (función Animal) donde podemos instanciar propiedades. Usando el prototipo podemos definir funciones que serán consideradas como métodos de instancia. Esto funciona, pero se supone que conoce la herencia prototípica y para alguien que viene de un lenguaje basado en clases parece muy confuso. Curiosamente, JavaScript tiene una palabra clave de clase, pero no hace nada. ECMAScript 6 ahora hace que esto funcione y permite un código más corto:
class AnimalES6 {
constructor(name) {
this.name = name;
}
doSomething() {
console.log("I'm a " + this.name);
}
}
var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();
El resultado es el mismo, pero es más fácil de escribir y leer para los desarrolladores que están acostumbrados a escribir clases. No es necesario el prototipo y puede usar la palabra clave «constructor» para definir el constructor. Además, las clases introducen una serie de nuevas semánticas que no están presentes en el equivalente de ECMAScript 5. Por ejemplo, no puede llamar a un constructor sin new o no puede intentar construir métodos con new. Otro cambio es que los métodos no son enumerables. Punto interesante aquí: ambas versiones pueden vivir una al lado de la otra. Al final del día, incluso con las nuevas palabras clave, terminas con una función con un prototipo donde se agregó una función. Un «método» aquí es simplemente una propiedad de función en su objeto. Otra característica central del desarrollo basado en clases, getters y setters, también es compatible con ES6. Esto hace que sea mucho más obvio lo que se supone que debe hacer un método:
class AnimalES6 {
constructor(name) {
this.name = name;
this._age = 0;
}
get age() {
return this._age;
}
set age(value) {
if (value < 0) {
console.log("We do not support undead animals");
}
this._age = value;
}
doSomething() {
console.log("I'm a " + this.name);
}
}
var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();
lionES6.age = 5;
Bastante útil, ¿verdad? Pero podemos ver aquí una advertencia común de JavaScript: el miembro privado «no realmente privado» (_edad). Escribí un artículo hace algunas veces sobre esto tema. Afortunadamente, ahora tenemos una mejor manera de hacer esto con una nueva característica de ECMAScript 6: simbolos:
var ageSymbol = Symbol();
class AnimalES6 {
constructor(name) {
this.name = name;
this[ageSymbol] = 0;
}
get age() {
return this[ageSymbol];
}
set age(value) {
if (value < 0) {
console.log("We do not support undead animals");
}
this[ageSymbol] = value;
}
doSomething() {
console.log("I'm a " + this.name);
}
}
var lionES6 = new AnimalES6("Lion");
lionES6.doSomething();
lionES6.age = 5;
Entonces, ¿qué es un símbolo? Este es un tipo de datos único e inmutable que podría usarse como identificador de propiedades de objetos. Si no tiene el símbolo, no puede acceder a la propiedad. Esto conduce a un acceso de miembro más «privado». O, al menos, menos fácilmente accesible. Los símbolos son útiles para la singularidad del nombre, pero la singularidad no implica privacidad. La singularidad simplemente significa que si necesita una clave que no debe entrar en conflicto con ninguna otra clave, cree un nuevo símbolo. Pero esto no es realmente privado todavía porque gracias a Object.getOwnPropertySymbolslos consumidores intermedios pueden acceder a las propiedades de su símbolo.
Manejo de la herencia
Una vez que tenemos clases, también queremos tener herencia. Es -una vez más- posible simular herencia en ES5, pero fue bastante complejo de hacer. Por ejemplo, aquí lo que es producido por Mecanografiado para simular la herencia:
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
var SwitchBooleanAction = (function (_super) {
__extends(SwitchBooleanAction, _super);
function SwitchBooleanAction(triggerOptions, target, propertyPath, condition) {
_super.call(this, triggerOptions, condition);
this.propertyPath = propertyPath;
this._target = target;
}
SwitchBooleanAction.prototype.execute = function () {
this._target[this._property] = !this._target[this._property];
};
return SwitchBooleanAction;
})(BABYLON.Action);
No es realmente fácil de leer. Pero la alternativa de ECMAScript 6 es mejor:
var legsCountSymbol = Symbol();
class InsectES6 extends AnimalES6 {
constructor(name) {
super(name);
this[legsCountSymbol] = 0;
}
get legsCount() {
return this[legsCountSymbol];
}
set legsCount(value) {
if (value < 0) {
console.log("We do not support nether or interstellar insects");
}
this[legsCountSymbol] = value;
}
doSomething() {
super.doSomething();
console.log("And I have " + this[legsCountSymbol] + " legs!");
}
}
var spiderES6 = new InsectES6("Spider");
spiderES6.legsCount = 8;
spiderES6.doSomething();
Gracias a «extiende” puede especializar una clase en una clase secundaria mientras mantiene la referencia a la clase raíz con el “súper” palabra clave. Con todas estas excelentes adiciones, ahora es posible crear clases y trabajar con herencia sin tener que lidiar con prototipos de magia vudú.
Por qué usar TypeScript es aún más relevante que antes…
Con todas estas nuevas funciones disponibles en nuestros navegadores, creo que es aún más relevante usar TypeScript para generar código JavaScript. En primer lugar, la última versión de TypeScript (1.4) comenzó a agregar soporte para ECMAScript 6 código (con dejar y constante palabras clave) por lo que solo tiene que mantener su código TypeScript existente y habilitar esta nueva opción para comenzar a generar ECMAScript 6 código. Pero si observa detenidamente algunos TypeScript, encontrará que esto se parece a ECMAScript 6 sin los tipos. Así que aprender TypeScript hoy es una gran manera de entender ECMAScript 6 ¡mañana!
Conclusión
Utilizando Mecanografiadopuede tener todo esto ahora en todos los navegadores a medida que su código se convierte en ECMASCript 5. Si desea usar ECMAScript 6 directamente en el navegador, puede actualizar a Windows 10 y probar allí con el motor de renderizado de Project Spartan. Si no desea hacer eso solo para probar algunas funciones nuevas del navegador, también puede acceder a una computadora con Windows 10 con Project Spartan en http:// remoto.moderno.es. Esto también funciona en su caja MacOS o Linux. Por supuesto, Project Spartan no es el único navegador compatible con el estándar abierto ES6. Otros navegadores también están integrados y puede rastrear el nivel de soporte en: http://kangax.github.io/compat-table/es6/ El futuro de JavaScript con ECMAScript 6 es brillante y, sinceramente, no veo la hora de verlo ampliamente compatible con todos los navegadores modernos. Este artículo es parte de la serie de tecnología de desarrollo web de Microsoft. Estamos emocionados de compartir proyecto espartano y es nuevo motor de renderizado contigo. Obtenga máquinas virtuales gratuitas o realice pruebas de forma remota en su dispositivo Mac, iOS, Android o Windows en http:// moderno.ES.
(dpe)
#Comprender #ECMAScript #clase #herencia