最近ちょっとJavascriptに触れていてgetter/setterをいじっていたらMaximum call stack size exceeded Error
にハマったのだが、綺麗にハマりすぎたので記事にしようと思う。
ハマってみる
まずはハマってみることが大切だ。
適当にインスタンスプロパティnumが10を超えたら文字列になる性質を付与してみる。
class beStringUpper10{
constructor(num){
this.num = num;
}
set num(val){
if (val > 10) this.num = String(val);
else this.num = Number(val);
}
}
let hoge = new beStringUpper10(0);
//数字だといいな
hoge.num = 1;
console.log(hoge.num)
//文字列だといいな
unko.num = 11;
console.log(hoge.num)
//Uncaught RangeError: Maximum call stack size exceeded
ええ!なんでっ!と驚く必要はない。
単に
class beStringUpper10{
constructor(num){
this.num = num;
}
//2 numにアクセスしたので呼び出されたセットした関数が呼び出される。
//5 numにアクセスしたので呼び出されたセットした関数が呼び出される。...
set num(val){
//3 11以上は文字列に変換
//4 numにアクセスした。
if (val > 10) this.num = String(val);
//3 それ以外は数値に変換
//4 numにアクセスした。
else this.num = Number(val);
}
}
let hoge = new beStringUpper10(0);
//1 hoge.numにアクセスした。
hoge.num = 1;
console.log(hoge.num)
hoge.num = 11;
console.log(hoge.num)
wow!これじゃあ無限ループになっちゃう!
コールスタックが悲鳴をあげても仕方ないな!
じゃあ_を使ってみる。
class beStringUpper10{
constructor(num){
this._num = num;
}
set num(val){
if (val > 10) this._num = String(val);
else this._num = Number(val);
}
}
let hoge = new beStringUpper10(0);
hoge.num = 11;
console.log(typeof hoge._num);//string
むうこれはめんどくさい...
getを使ってみる。
改造改造...
class beStringUpper10{
constructor(num){
this._num = num;
}
get num(){
return this._num;
}
set num(val){
if (val > 10) this._num = String(val);
else this._num = Number(val);
}
}
let hoge = new beStringUpper10(0);
hoge.num = 11;
console.log(typeof hoge.num);//string
hoge.num = 1;
console.log(typeof hoge.num);//number
hoge.num = 13;
console.log(typeof hoge.num);//string
うむいい感じだ。
最後に
ではまたね~
参照