Javascriptの基礎のおさらい

Javascriptのイロハを見て今まで曖昧にしていたものを理解し直したので、軽くまとめます。

■ 関数の書き方について

// 一般的な関数の書き方
function a() {
  alert("a");
}

// 変数に無名関数を代入して関数とする書き方
var a = function() {
  alert("a");
};

// あんまり覚えなくてよさそうだけど、関数はFunctionクラスなのである
var add = new Function("a", "b", "alert(a + b);");
add(1, 2);

// 関数内に変数を持ち、無名関数を返す関数。
function createCounter() {
  var n = 0;
  return function() {
    n++;
  }
}

オブジェクト指向的な書き方

// 作成したオブジェクトに変数やメソッドを持たせる書き方
var obj = new Object();
obj.v1 = "変数1";
obj.f1 = function() {
  alert("関数1");
};
var obj2 = new Object();
obj2.str = "文字列";
obj.nested = obj2;

// 上記を別の書き方で表したもの。オブジェクトリテラルという書式
var obj = {
  v1: "変数1",
  f1: function() {
    alert("関数1");
  },
  nested: {
    str: "文字列"
  }
};

// クラスっぽい書き方。ただ、クラスではなく、このUgon(num)はコンストラクタ関数と呼ぶ
function Ugon(num) {
  this.num = num;
  this.showName = function() {
    alert('My name is "ugon' + this.num + '".');
  };
}

var ugon105 = new Ugon(105);
var ugon106 = new Ugon(106);
ugon105.showName();
ugon106.showName();

■ プロトタイプについて

// 上記だとugon105, ugon106がそれぞれshowName関数を持ちメモリの無駄
// なのでprototypeを使って関数の定義をひとつにする
// prototypeとはコンストラクタ関数が持つプロパティ。
// 後述のプロトタイプチェーン
function Ugon(num) {
this.num = num;
}
Ugon.prototype.showName = function() {
alert('My name is "ugon' + this.num + '".');
}

■ そのほか

// Ugonにstaticっぽいクラス変数を持たせるには、コンストラクタ作成して後から変数追加。
function Ugon(num) {...}
Ugon.ID = 'ugon';
Ugon.prototype.showName = function() {
  alert('My name is "' + Ugon.ID + this.num + '".');
}

// javascript継承
function Human() {}
Human.prototype.eat = function() {
  alert("eat");
}
function Ugon() {
}
Ugon.prototype = new Human();
var ugon105 = new Ugon();
ugon.eat();

// なぜ new しないと使えない?
// 理解できてない。コンストラクタ関数だから?って理由にならないか。

// 宣言した変数と値・関数が入るところ = 「変数オブジェクト
// グローバルスコープで定義した場合は変数オブジェクトはwindowとなる
var a = 100;
alert(window["a"]);
alert(window.a);
// ローカルスコープで定義した場合は変数オブジェクトは何?
// アクティベーションオブジェクト(見えない変数オブジェクト)が作られる
// スコープチェーンを理解するのに必要

// プロトタイプチェーン
// メンバの参照時に「自身 → 自身のプロトタイプ → そのまたプロトタイプ ... Object.prototype」の順に見ていく

// スコープチェーン = Javascriptにおけるクロージャの仕組みとなる
// 関数実行時にアクティベーションオブジェクトが作られ、
// その中にない変数は上位のアクティベーションオブジェクト、
// 最終的にグローバルオブジェクトまで見ていく
function createCounter() {
  var n = 0;
  // クロージャ作成
  return function() {
    return n++;
  }
}
var counter = createCounter();
counter();
counter();

// createCounterが返す関数が実行されるときに、
// 自分の上位のアクティベーションオブジェクトが持つnを扱える(スコープチェーン)
// 返されたメソッドはnを自身の変数オブジェクトとして持っているため、
// counter()をする度に、counter(関数)が持っているnを更新していく。消えない。