basyura's blog

あしたになったらほんきだす。

プライベートなメンバ変数

プライベートメンバについてメモ代わりに適当なサンプルを書いてみました。

CoffeeScriptのプライベートメンバについてのメモ

めんどくさいらしいので確認してみる。

javascript で書いてみる

function Person(name) {
  var name_ = name
  this.get_name = function () {
    return name_;
  }
}

var p1 = new Person("hi");
var p2 = new Person("ho");

print(p1.get_name()); //=> hi
print(p2.get_name()); //=> ho

意図通り。

coffee script で書いてみる

class Person
  name_ = null
  constructor: (name) ->
    name_ = name
  get_name: ->
    return name_

p1 = new Person("hi")
p2 = new Person("ho")

console.log p1.get_name() #=> ho
console.log p2.get_name() #=> ho

Σ( ̄□ ̄) 同じ値!!

coffee -c でコンパイル結果を確認する

(function() {
  var Person, p1, p2;
  Person = (function() {
    var name_;
    name_ = null;
    function Person(name) {
      name_ = name;
    }
    Person.prototype.get_name = function() {
      return name_;
    };
    return Person;
  })();
  p1 = new Person("hi");
  p2 = new Person("ho");
  console.log(p1.get_name());
  console.log(p2.get_name());
}).call(this);
  • コンストラクタ関数 Person(name) 実行時のスコープとは別に name_ が定義してある
  • name_ のスコープは一行上の function 内
  • get_name は prototype に定義してある

意図通りの例だと、コンストラクタ関数 Person(name) が実行される際に name_ と get_name が一緒に評価されてクロージャになる。なので、get_name から name_ が見える。
ただし、インスタンス生成時に get_name が毎回評価され、インスタンスごとに定義されるのでメモリ効率が悪い。

意図しないほうだと java でいうクラス変数の様な扱いになってしまう。
get_name はインスタンス生成時に毎回評価されず、prototype で共有するのでメモリ効率が良い。

coffee script ではできないのか?

引用元にあるように constructor で頑張るみたいだけど、可読性が悪いしトラップにひっかかりそう。
@ 縛りにするか @m_name の様に命名規則を付ける方が失敗が少なそう。

半径 1 クリックで調べた範囲内では。

とはいえ、メンバ変数が外からアクセスできて便利だったことはあっても、困った記憶が特に無いので心配することでも無いのかもしれない。