A Day In The Life

とあるプログラマの備忘録

Javascriptでプライベート関数

Javascriptの関数は基本すべてグローバル関数です。

場合によってはプライベート関数が必要なときもあるかと思います。

そんなときは以前紹介した名前空間クロージャを使って実現できます。

var jp = {};
jp.dip = {};
jp.dip.emery = {};
jp.dip.emery.Counter = {};
(function() {
  var value = 0;
  //private
  function changeBy(val) {
    value += val;
  }
 //public
  function getValue() { return value; }
  //public
  function countUp() { return changeBy(1); }
  //public
  function countDown() { return changeBy(-1); }
  //public関数の設定
  var ns = jp.dip.emery.Counter;
  ns.getValue = getValue;
  ns.countUp = countUp;
  ns.countDown = countDown;
})();
:
:
alert(Counter.getValue()); /* 0 と表示される */
Counter.countUp();
Counter.countUp();
alert(Counter.getValue()); /* 2 と表示される */
Counter.countDown();
alert(Counter.getValue()); /* 1 と表示される */

(function() {...})();とすると無名関数がWindowのload時に実行されjp.dip.emery.Counterと関数(getValueなど)が紐づく仕組みになっています。

またローカル変数valueにも注目してください。

この変数はオブジェクト指向プログラミングでいうところのインスタンス変数のような役割をしています。

一見getValue()やcountUp()が実行されるたびに初期化されてしまいそうですが(function() {})();はload時に一度だけしか実行されないので値を保持し続けます。



また上記の例を↓のように短く書くこともできます。

var jp = {};
jp.dip = {};
jp.dip.emery = {};
jp.dip.emery.Counter = (function() {
  var value = 0;
  //private
  function changeBy(val) {
    value += val;
  }
 return {
    getValue: function() { return value; },
    countUp: function() { return changeBy(1); },
    countDown: function() { return changeBy(-1); }
  }
})();
:
:
alert(Counter.getValue()); /* 0 と表示される */
Counter.countUp();
Counter.countUp();
alert(Counter.getValue()); /* 2 と表示される */
Counter.countDown();
alert(Counter.getValue()); /* 1 と表示される */

1つ目の例に比べて少し難解な気もしますが1つ目の例が理解できれば2つ目の例も理解できると思います。

こうしてみるとJavascriptってJava風の関数言語なんだなということがわかりますね。

参考書籍