2009年5月26日火曜日

JavaScript prototypeとメモリの関係

下の例では
Hitoコンストラクタから3つのオブジェクトを作成している
コンストラクタ内ではthisを使い、変数・関数を割り当てている
この場合だと、変数・関数ともにそれぞれ別にメモリ上に割り当てられてしまうことになり
メモリの無駄遣いとなる

function Hito(name) {
this.name = name;
this.hello = function() {
alert('Hello! My name is ' + this.name);
};
}
var saito = new Hito('saito');
var ishii = new Hito('ishii');
var kume = new Hito('kume');
saito.hello();
ishii.hello();
kume.hello();


そこでprototypeを使い
下のように書きかえることで
関数が共用されるようになる。

function Hito(name) {
this.name = name;
};
Hito.prototype.hello = function() {
alert('Hello! My name is ' + this.name);
};
var saito = new Hito('saito');
var ishii = new Hito('ishii');
var kume = new Hito('kume');
saito.hello();
ishii.hello();
kume.hello();

JavaScrit スコープチェイン

JavaScriptクロージャを完全理解!スコープチェインを知る
を参考に勉強

ローカル変数を宣言した場合、JavaScript内部では
管理用のハッシュテーブル(変数オブジェクトと呼ぶ)
に格納される。
グローバル変数の場合はwindowオブジェクトのプロパティに格納される
例えば

var hoge = 100;
alert(window.hoge);

という風にwindow.hogeでグローバル変数にアクセスできる

以下例ではグローバル変数にf()からアクセスできる
実行時、順にf()内の変数オブジェクトを検索しaはないので
次にグローバル変数を探し、アクセスしている。(関数外の変数にアクセスできる)
この変数の探索をスコープチェインという

var a = 0;
function f() {
alert(a);
}
f(); // 0が表示される

JavaScript クロージャ

クロージャー
プログラミング言語において引数以外の変数を実行時の環境ではなく、自身が定義された環境(静的スコープ)において解決する関数のことである。関数とそれを評価する環境のペアであるともいえる。この概念は少なくとも1960年代のSECDマシンまで遡ることができる。
まれに、関数ではなくとも、環境に紐付けられたデータ構造のことをクロージャと呼ぶ場合もある。


JavaScriptでのクロージャー

var cl = function() {
var counter = 0;
return function() {
counter += 1;
return counter;
};
};
var c = new cl();
alert(c()); //1
alert(c()); //2
alert(c()); //3

JavaScript apply呼び出し

第1引数で指定したオブジェクトをthisとし
また、第2引数で指定した配列を引数として
関数を実行する

var human = function(name) {
this.name = name;
}
function func1(pre) {
alert(pre + ' ' + this.name);
}
var h = new human('hoge');
//humanオブジェクトをthisとして['hello']を引数として
//func1を実行
func1.apply(h,['hello']);

JavaScriptスコープ

JavaScriptにおける変数のスコープは
ブロックスコープを持たず
関数内であれば、関数内のどの変数にもアクセスできる。
関数外からはアクセス不可

var func = function() {
var a = 3, b = 1;
var inner = function() {
// var b = 7;とするとbは再定義され外側のbへは影響しない
b = 7; //外側の関数内の変数にアクセス可能
};
alert(b); //1
alert(a); //3
{
var a = 2;
}
alert(a); //2 ブロックスコープはないためaが上書きされる
inner();
alert(b); //7
};
var x = new func();

JavaScriptクラスとコンストラクタ

JavaScriptでクラス的なものを実現させるには
関数リテラルがクラスに相当するもので
関数リテラルをnewで初期化したものがインスタンスとなる

//関数リテラル(クラス)の定義
var animal = function(name) {
//thisは呼び出しものnekoオブジェクトの参照となる
this.name = name;
this.sayName = function() {
alert(this.name);
};
};
//newで初期化、オブジェクトの生成
var neko = new animal('tama');
neko.sayName();

JavaScript関数リテラル

JavaScriptにおいて関数はオブジェクト(Functionオブジェクト)となる

関数オブジェクトの表記方法には何種類かある

1つ目はfunction+関数名+引数()とする表記

function hoge(a) {
}

もう1つは関数リテラルとして表記する方法
変数名 = function+引数とする

var hoge = function(a) {
}


後者は無名関数と呼ばれるもので
前者の表記と比較すると
・関数名を与える必要がない場合、簡潔に書ける
・変数名、関数名の衝突を防げる
などのメリットがある。

また

var hoge = new function (a) {
}

のような書き方も可能