LoginSignup
30
28

More than 5 years have passed since last update.

[JavaScript] クラス&モジュールの安全な書き方

Last updated at Posted at 2015-07-07
【追記】

記事末尾のコメントで指摘されているように、当記事の手法は、メモリ消費や処理速度においては不利な面がありますのでご注意ください。また、次期JavaScript(ES6)では正式に class が導入されます。


JavaScriptのクラスについては色々なサイトで解説されていますが、内部でthisprototypeを使用している形では、次のような危険性があります。

  • thisが外部と共有されるため、thisが自身のインスタンスではなくなることがある(特にメソッド内で外部系からのコールバックを使用している場合)
  • prototypeを使ったメソッドがクラス内のローカル変数を参照している場合、その変数はインスタンス間で共有されるため、想定外の値になることがある(クロージャ効果)

以下、安全な書き方についてまとめてみました。

例)Itemクラス

test.js
// Itemクラス
var Item = function(name) {
    // インスタンスとなるObject
    var self = this;

    // メンバー変数(public)
    self.price = 0;
    // ローカル変数(private的)
    var _name = name;

    // メソッド(public)
    self.showInfo = function() {
        alert(getInfo());
    };
    // ローカル関数(private的)
    function getInfo() {
        return _name + " is " + self.price + "yen";
    }
};

var banana = new Item("Banana");
var orange = new Item("Orange");
banana.price = 100;
orange.price = 200;
banana.showInfo(); // "Banana is 100yen" が表示される
orange.showInfo(); // "Orange is 200yen" が表示される
長所
  • クラス内のローカル変数がインスタンス毎に独立している(prototypeを使っていないため)。
  • クラス内のメソッドで、ajaxなど、コールバックが発生する処理を実行しても安全(自身をselfで参照する限りは)。
短所
  • インスタンス毎にメソッドが保持されるのでメモリ消費の点で不利(prototypeを使っていないため)。prototypeを用いる書き方は「やさしいクラスの作り方」が参考になります。

例)Appleモジュール(シングルトンもどき)

test.js
// Appleモジュール(即時関数を実行して生成)
var Apple = (function() {
    var self = {}; // 自身の本体となるObject

    // メンバー変数(public)
    self.price = 0;
    // ローカル変数(private的)
    var _name = "Apple";

    // メソッド(public)
    self.showInfo = function() {
        alert(getInfo());
    };
    // ローカル関数(private的)
    function getInfo() {
        var info = _name + " is " + self.price + "yen";
        return info;
    }

    return self; // これ忘れないこと
})();

//var apple = new Apple(); // newはできない!
Apple.price = 300;
Apple.showInfo(); // "Apple is 300yen" が表示される

解説

 JavaScript には正式なクラスがありません。そのかわり、new 演算子を使って function を object 化することで、クラスをインスタンス化するような使い方ができます。ただ、new や this の扱いが他言語とはかなり異なるため、上記のような書き方が比較的安全かなと思います。

 Itemクラスのほうは、selfに登録したものだけがpublicな感じでアクセスできます。Appleモジュールは、サイトによっては「モジュールパターン」として説明されています。こちらは即時関数によって object がreturnされるので、new することはできません。

(・o・ゞ いじょー。

参考URL

【javascript】やさしいクラスの作り方
http://qiita.com/varmil/items/99fd6f2a886fdde4b7fa

ちょっと便利なJavascriptオブジェクトの作り方
http://blog.asial.co.jp/1101

Google流 JavaScript におけるクラス定義の実現方法
http://www.yunabe.jp/docs/javascript_class_in_google.html

JavaScript の new 演算子の意味
http://nanto.asablo.jp/blog/2005/10/24/118564

prototype と __proto__
http://d.hatena.ne.jp/cou929_la/20100929/1285770930
※__proto__は環境依存するようですのでご注意ください

Javascriptでプライベートメンバを使うなら、prototypeは諦める
https://sites.google.com/site/jun1sboardgames/programming/javascript-private-members

JavaScript の超便利なメソッド bind で this を制御する
http://foreignkey.jp/archives/763

30
28
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
30
28