que - Clases de JavaScript con getter y setter causan RangeError: Se excedió el tamaño máximo de pila de llamadas
javascript class getters and setters (5)
Las clases Get & Set ES6 traen una nueva sintaxis para los que obtienen y configuran las propiedades de los objetos. Obtener y configurar nos permite ejecutar código en la lectura o escritura de una propiedad. ES5 también tuvo captadores y configuradores, pero no se usó mucho debido a los navegadores IE más antiguos. Los captadores y configuradores de ES5 no tenían una sintaxis tan buena como la que nos ofrece ES6. Así que vamos a crear un obtener y establecer para nuestra propiedad de nombre.
Fuente: JavaScript ES6 Class Syntax
Ejemplo :
// ES6 get and set
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name.toUpperCase();
}
set name(newName) {
this._name = newName; // validation could be checked here such as only allowing non numerical values
}
walk() {
console.log(this._name + '' is walking.'');
}
}
let bob = new Person(''Bob'');
console.log(bob.name); // Outputs ''BOB''
Actualmente estoy experimentando con las clases de ECMA6. Mi clase actual se parece a la siguiente
class Player {
constructor(id) {
this.id = id;
this.cash = 350;
}
get cash() {
return this.cash;
}
set cash(value) { // line 19
this.cash = value; // line 20
}
};
Cuando ahora estoy creando un nuevo Objeto llamando a let playerObject = new Player(1);
Recibo el siguiente error
.../node_modules/mysql/lib/protocol/Parser.js:82
throw err;
^
RangeError: Maximum call stack size exceeded
at Player.cash (player.js:19:11)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
at Player.cash (player.js:20:15)
Press enter to exit
¿Qué tiene esto que ver con la biblioteca mysql? ¿Por qué el error es varias veces en la misma línea? Sólo lo estoy llamando una vez.
Estás llamando recursivamente a tu captador.
Sigue una posible alternativa:
class Player {
constructor(id) {
this.id = id;
this._cash = 350;
}
get cash() {
return this._cash;
}
set cash(value) {
this._cash = value;
}
};
Otro usando Object.defineProperty
:
class Player {
constructor(id) {
this.id = id;
var _cash = 350;
Object.defineProperty(this, ''cash'', {
get: function() {
return _cash;
}
set: function(v) {
_cash = v;
}
});
}
};
Sé que llego tarde, pero creo que puedo aclarar uno o dos puntos aquí:
Primero, está la cuestión de la privacidad , que es una discusión a largo plazo en la comunidad de JavaScript.
class Player {
constructor(id) {
this.cash = 350; // this._cash, alternatively
}
get cash() {
return this.cash;
}
set cash(value) {
this.cash = value;
}
};
let player1 = new Player();
En este caso, this.cash es una propiedad pública , por lo que realmente no necesita un método get y set para manejarlo, porque puede obtenerlo con player1.cash y configurarlo con player1.cash = newCash ; y está lanzando el error porque el getter y el setter están siendo llamados recursivamente, como lo mencionaron otros.
Sin embargo, si simplemente cambia el nombre de la propiedad a this._cash , debe entender que esto NO ES UNA PROPIEDAD PRIVADA . Si intentas acceder a player1._cash , tendrás acceso al valor de la propiedad de la misma manera que lo harás con player1.cash .
Entonces, ¿cómo conseguimos la privacidad poperly implementado?
Hay 2 formas principales de hacer esto con ES6 / ES2015: usando el nuevo Symbol tipo primitivo o usando WeakMaps . No voy a entrar en detalles sobre estas dos nuevas características del lenguaje, pero mostraré cómo se implementaría esto en este caso.
Usando Símbolos:
const CASH = Symbol();
class Player {
constructor () {
this[CASH] = 350;
}
get cash(){
return this[CASH];
}
set cash(cash) {
this[CASH] = cash;
}
}
Usando WeakMaps
let map = new WeakMap();
class Player {
constructor () {
map.set(this, {
cash: 350
});
}
get cash(){
return map.get(this).cash;
}
set cash(cash) {
map.get(this).cash = cash;
}
}
IMPORTANTE
Si bien la sintaxis de los símbolos es mejor, requiere que el navegador funcione de forma nativa para que realmente funcione. Puede escribirlo con un transpiler pero, bajo el capó, se burlará de los antiguos estándares ES5. El soporte nativo para WeakMaps es mejor y, por otro lado, esta característica simplemente juega con el GC y con la opción enumerable de las propiedades de los objetos. Así que, al final, es tu elección.
Su organizador "efectivo" llama al configurador "efectivo", que llama al configurador "efectivo", que llama al configurador "efectivo" ...
El acceso al establecedor de propiedades por su propio nombre dentro del definidor crea una llamada de función recursiva infinita.
el efectivo representa al captador / definidor, _cash es la propiedad ''privada''.
set cash(value) { // line 19
this._cash = value; // line 20
}
Echa un vistazo a esta página para ver un ejemplo claro.