问题描述
我目前正在试验ECMA6课程。 我目前的课程如下所示
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
}
};
当我现在通过调用let playerObject = new Player(1);
创建一个新的Object时let playerObject = new Player(1);
我收到以下错误
...\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
这与mysql库有什么关系? 为什么错误在同一行中多次? 我只打电话一次。
1楼
你的“现金”制定者称为“现金”制定者,称为“现金”制定者,称为“现金”制定者......
在setter中通过自己的名称访问属性setter会创建一个无限的递归函数调用。
2楼
我知道我迟到了,但我想我可以在这里澄清一两点:
首先,存在隐私问题,这是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();
在这种情况下, this.cash是一个公共属性 ,所以你真的不需要getter和setter方法来处理它,因为你可以用player1.cash来获取它并用player1.cash = newCash设置它; 它正在抛出错误,因为正如其他人所提到的那样,递归地调用getter和setter。
但是,如果您只是将属性重命名为this._cash ,则必须了解这不是私有财产 。 如果您尝试访问player1._cash ,则可以使用与player1.cash相同的方式访问属性值。
那么, 我们如何才能真正实现隐私?
使用ES6 / ES2015有两种主要方法:使用新的原始类型或使用 。 我不会详细介绍该语言的这两个新功能,但我将展示如何在这种情况下实现这一功能。
使用符号:
const CASH = Symbol();
class Player {
constructor () {
this[CASH] = 350;
}
get cash(){
return this[CASH];
}
set cash(cash) {
this[CASH] = cash;
}
}
使用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;
}
}
重要
虽然符号的语法更好,但它需要浏览器的本机支持才能实际工作。 您可以使用转换器编写它,但在引擎盖下,它会将其模拟为旧的ES5标准。 对WeakMaps的本机支持更好,另一方面,此功能只使用GC和对象属性的可枚举选项。 所以,最后,这是你的选择。
3楼
cash表示getter / setter,_cash是'private'属性。
set cash(value) { // line 19
this._cash = value; // line 20
}
请查看以获得清晰的示例。
4楼
你递归地叫你的吸气剂。
它遵循一个可能的选择:
class Player {
constructor(id) {
this.id = id;
this._cash = 350;
}
get cash() {
return this._cash;
}
set cash(value) {
this._cash = value;
}
};
另一个使用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;
}
});
}
};
5楼
Get&Set ES6类为对象属性的getter和setter带来了新的语法。 获取和设置允许我们在读取或写入属性时运行代码。 ES5也有getter和setter,但因为旧的IE浏览器而没有被广泛使用。 ES5 getter和setter没有ES6带给我们的语法。 因此,让我们为name属性创建一个get和set。
来源:
示例 :
// 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'