ecmascript javascript ecmascript-6

javascript - ecmascript - ¿Por qué no se izan las clases ES6?



ecmascript 6 (3)

Dado que las clases ES6 son solo un azúcar sintáctico sobre la herencia basada en prototipos existente de JavaScript [1] , (IMO) tendría sentido elevar su definición:

var foo = new Foo(1, 2); //this works function Foo(x, y) { this.x = x; this.y = y; }

Pero lo siguiente no funcionará:

var foo = new Foo(1, 2); //ReferenceError class Foo { constructor(x, y) { this.x = x; this.y = y; } }

¿Por qué no se izan las clases ES6?


¿Por qué no se izan las clases ES6?

En realidad, se izan (el enlace variable está disponible en todo el alcance) al igual que let y const , solo que no se inicializan.

Tendría sentido elevar su definición

No. Nunca es una buena idea usar una clase antes de su definición. Considera el ejemplo

var foo = new Bar(); // this appears to work console.log(foo.x) // but doesn''t function Bar(x) { this.x = x || Bar.defaultX; } Bar.defaultX = 0;

y compararlo con

var foo = new Bar(); // ReferenceError console.log(foo.x); class Bar { constructor (x = Bar.defaultX) { this.x = x; } } Bar.defaultX = 0;

que arroja un error como era de esperar. Este es un problema para las propiedades estáticas, prototipos de mixins, decoradores y todo. También es bastante importante para la subclasificación, que se rompió por completo en ES5 cuando usó una clase con su prototipo no ajustado, pero ahora arroja un error si aún no se ha inicializado una clase extend .


Si bien las clases no izadas (en el sentido de que se comportan como enlaces de let ) pueden considerarse preferibles ya que conducen a un uso más seguro (ver la respuesta de Bergi ), la siguiente explicación que se encuentra en el blog de 2ality parece proporcionar una razón ligeramente más fundamental para esta implementación:

La razón de esta limitación [ no elevación ] es que las clases pueden tener una cláusula extends cuyo valor es una expresión arbitraria. Esa expresión se debe evaluar en la "ubicación" adecuada, su evaluación no se puede izar.


En Javascript, todas las declaraciones (var, let, const, function, function *, class) se izan pero deben declararse en el mismo ámbito .

Como dijiste, "las clases de ES6 son solo un azúcar sintáctico sobre la herencia basada en prototipos existente de JavaScript"

Entonces, ¿entendemos qué es?

Aquí usted declaró una clase que de hecho es "función especial". Supongamos que su función Foo () y la clase Foo están en el ámbito global.

class Foo { constructor(x, y) { this.x = x; this.y = y; } }

El siguiente es el código compilado de su clase Foo.

var Foo = (function () { function Foo(x, y) { this.x = x; this.y = y; } return Foo; }());

Internamente, su clase se convierte en función con el mismo nombre dentro de la función de contenedor (iife) y esa función de contenedor devuelve su función.

Porque el alcance de su función (clase) ha cambiado. e intenta crear un objeto de función en un alcance global que en realidad no existe.

obtienes la función en Foo variable una vez que la compilación llega a eso. para que luego tengas función en var puedes crear objeto de eso.