オブジェクトを凍結! JavaScript の seal() と freeze()

今回は JavaScript でのオブジェクトの凍結について

こんにちは!江嵜です!

皆さん今日も JavaScript 書いてますか?

今回はあまり日の当たらないところですが、知っておくと役に立つ(かもしれない)オブジェクトの凍結についてお話します!

オブジェクトの凍結とは…?

オブジェクトの凍結とは何でしょうか?
凍結とは、一言で言えば「変更できないようにする」ということですね。

いわゆる変数に対する定数と呼ばれるヤツですね!
Java なんかだと final という修飾子をつけることで実現ができます。

実は JavaScript にも ES6 (最近の仕様)からは変数定義の際に const というものを使用することができまして、

const foo = '文字を入れるよ';
foo = '変更する'; 

みたいにすると、 foo は定数として定義できますので 2 行目の再代入でエラーを発生させることができます。

こういった仕組みがあることで、プログラム内で好きに変更してほしくない値(DB への接続情報とか、ありますよね!)を
保護することが出来る、ということなんですね。

ではオブジェクトではどうする?

ではオブジェクトではどうでしょうか、
次のようにオブジェクトリテラルを用意して試してみると

const foo = {hoge: 'test'};
foo = {hoge: 'changed'}; 

これはエラーになります。

がしかし…

const foo = {hoge: 'test'};
foo.hoge = 'changed!'; 
foo.fuga = 'fuga'
console.log(foo);

これだとどうでしょうか。結果はこちら。

[object Object] {
  fuga: "fuga",
  hoge: "changed!"
}

見事に foo.hoge の値は書き換えられ、新しい fuga という値も追加されてしまいました。
(実際に皆さんも試してみてくださいね。)

じつは、 const では再代入は防げますが、オブジェクトの中身までは保護できないのですね。

オブジェクトの中身も丸っと保護する方法はないのでしょうか…?

seal で保護してみる

実はオブジェクトの中身を保護する方法があります。
それがこちら。

Object.seal(foo);

Object.seal() にオブジェクトを渡してあげることで、そのオブジェクトを保護することができるのです。

試しに先程のコードを実施してみると…

const foo = {hoge: 'test'};
Object.seal(foo);
foo.hoge = 'changed!'; 
foo.fuga = 'fuga'
console.log(foo);
[object Object] {
  hoge: "changed!"
}

foo.fuga の追加を抑止できましたね!
ちなみに、通常ではこのようにただ無視されるだけなのですが、
JavaScript ファイルの先頭に "use strict"; と書いて厳格モードにすればきちんとエラーが出るようになります。

ただ、これだけではちょっとまだ心もとないですね。
Object.seal() はオブジェクトへのプロパティの追加・削除を抑止できますが、変更は止められないのです。
これはこれで便利ですが、すべての変更を抑止したい!という事もありますよね。
そんな時はどうするのでしょうか?

freeze で凍結!

そんなときの為に Object.seal() よりもさらに強いものがあります!
それが Object.freeze() です。
雪だるまつくろー⛄ ドアを開けてー♪ 1

なんとなく予想はついているかと思いますが、試してみましょう。

const foo = {hoge: 'test'};
Object.freeze(foo);
foo.hoge = 'changed!'; 
foo.fuga = 'fuga'
console.log(foo);

結果はこちら

[object Object] {
  hoge: "test"
}

確かにすべての変更を無視していますね!
こちらも普通に使うだけですと変更を無視するだけですが、厳格モードにすればきちんとエラーが出てくれます。

これでオブジェクトの保護もバッチリですね!

これで安全に JavaScript を書きましょう!

ちなみに、同じ系列で Object.preventExtensions() という追加のみを抑制する(変更や削除は許可)というものがありますが、
大体 Object.seal()で事足りるかなと思います。

柔軟性が高いのが JavaScript の良さではありますが、
きっちり守るところは守って、安全に JavaScript 書きましょうね!


  1. 「アナと雪の女王」の英語名は「frozen」だそうですよ!シンプル! 
Takato Ezaki

Takato Ezaki小中高の塾講師からエンジニア

投稿者プロフィール

福岡で Web 系のエンジニアをしています。

中高の理科教師免許を取り、起業に 2 年間トライした後エンジニアの道へ入りました。

化学反応の中では Belousov-Zhabotinsky 反応が大好きです。

この著者の最新の記事

関連記事

コメントは利用できません。

募集中!(o゜▽゜)o

エンジャパン
求む、社長!
follow us in feedly

コッチもヨロシク!





最近のネタ!

  1. 2019-2-18

    第9回ボルダリング部 ~まさかのワールドカップ優勝者登場!?~

    今回は、1月に開催されましたボルダリング部活動の様子をお届けします(`・ω・´)ゞ 今年もB-PU…
  2. 2019-2-18

    GitHub のプランを Pro から Free へダウングレードすると制限がかかる機能全 6 つ紹介

    GitHub のアカウントを Pro から Free へダウングレードしました! こんにちは、江嵜…
  3. 2019-2-12

    第三回リアル脱出ゲーム部~さよなら、僕らのマジックアワー~

    はじめに 2019年初のリアル脱出ゲーム部の活動が02/02(土)にありました! というわけで活…
  4. 2019-2-12

    第4回アウトドア部 ~まさかのみんな初心者!?~

    2019/2/2(土)、アウトドア部の4回目の活動!! 前回終了時点では、真冬だろうし寒いから室内…
  5. 2019-2-11

    target=”_blank” すると飛び先のサイトから情報取れるって知ってました?

    target="_blank" はリンク先を新しいタブで開くときの書き方ですが… こんにちは、江嵜…
ページ上部へ戻る