JavaScriptを書いていると、意外なところで副作用を発生させることができてしまいます。
プロパティ参照
たとえば、こんなコードを考えてみます。
const foo = new Foo();
foo.bar;
ここでの2行目は無意味な文にも見えますが、Foo
の中身によってはこれが副作用を持つことがありえます。
class Foo{
get bar(){
alert('副作用');
}
}
ということで、プロパティ参照はその見た目によらず、他のコードを実行可能、ということになります。
文字列展開
これは比較的わかりやすいかもしれませんが、文字列変換に際してはオブジェクトのtoString
メソッドが呼び出されます。
const obj = {
toString() {
alert('副作用');
return '文字列';
}
}
`${obj}`; // 文字列を定義しただけでアラートされる
Proxy
オブジェクト
ES6で追加されたProxy
オブジェクト(MDN)は、意外なところにもフックを仕込めて、副作用を発生させられます。
-
in
演算子によるプロパティチェック -
delete
演算子によるプロパティ削除 -
Object.***
による各種のオブジェクト操作
実運用に与える影響
もちろん、「toString()
が余計な副作用を持つオブジェクト」なんてものは使いづらいので、実用することはないかと思います。とはいえ、考慮しないといけない場面はありえます。
- DOMプロパティの中には、参照するだけで再描画を行うものがありますので、あえて使うにしろ、うっかり使って余計な再描画が入ってしまうパターンにしろ要注意です。
- コードのminifyを行う際も、「元のコードの動作を変えられない」というのは大前提になりますので、
obj.propertyWithVeryLongName
のようなものが大量にあっても、1つにまとめることはありません。自分で変数に受けるなどしたほうがいい場面もあるかもしれません。