概要:関数宣言と関数式の違い
sayHi();//正解:関数宣言のリフティング
function sayHi(){
alert("Hi!");
}
sayHi(); //エラー: 関数がまだ存在しない
var sayHi = function(){
alert("Hi!");
};
//間違ったアプローチは、実際にはECMAScriptでは無効な構文であり、JavaScriptエンジンはエラーを修正し、賢明な状態に変換しようとする。エラーを修正しようとする試みは、ブラウザによって一貫していない。ほとんどのブラウザは2番目のステートメントを返し、条件を無視する。つまり、これは危険な使い方なのだ。
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
//次のようにすることができる。
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
}
関数は他の関数の値として返すこともでき、返された関数は変数に代入されたり、他の方法で呼び出されたりします。
再帰
非厳密モードでは、関数への再帰呼び出しは arguments.callee
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); //
//階乗を設定するには2つの方法がある=null,どちらもエラーを報告しない
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});
クロージャ
this "オブジェクトについて
無名関数の実行環境はグローバルなので、thisオブジェクトは通常ウィンドウを指します。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //"The Window"((非厳密モードの場合)
this "の値が予期せず変更される可能性がある特殊なケースがいくつかあります。
var name = "The Window";
var object = {
name: "My Object",
getName: function () {
return this.name;
}
};
object.getName(); //"My Object"
(object.getName)(); //"My Object"
(object.getName = object.getName)(); //"The Window",非制限モードでは
メモリリーク
クロージャがHTML要素をそのスコープ・チェーンに保持している場合、その要素は破壊できないことを意味します。これは次のようになります。
function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
}
上記のコードでは、element要素のイベントハンドラとして動作するクロージャが作成され、その結果、循環参照が作成されます。無名関数はassignHandler()のアクティブオブジェクトへの参照を保持するので、elementの参照カウントを減らす方法はありません。無名関数が存在する限り、element の参照カウントは少なくとも 1 になるため、element が占有するメモリが再利用されることはありません。
これは2つのステップで解決できます。element.idを変数に格納してクロージャ内で参照し、element変数をnullに設定します。
function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;//
element.onclick = function(){
alert(id);
};
element = null;//
}
プライベート変数
特権メソッド:プライベート変数やプライベート関数にアクセスできるパブリックメソッド
function MyObject(){
//プライベート変数とプライベート関数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特権メソッド
this.publicMethod = function (){
privateVariable++;
return privateFunction();
};
}
静的プライベート変数
静的なプライベート変数を作成すると、プロトタイプを使用するためコードの再利用が向上しますが、各インスタンスは独自のプライベート変数を持ちません。
(function(){
var name = "";
Person = function(value){
name = value;
};
Person.prototype.getName = function(){
return name;
};
Person.prototype.setName = function (value){
name = value;
};
})();
var person1 = new Person("Nicholas");
alert(person1.getName()); //"Nicholas"
person1.setName("Greg");
alert(person1.getName()); //"Greg"
var person2 = new Person("Michael");
alert(person1.getName()); //"Michael"
alert(person2.getName()); //"Michael"
モジュールパターン
モジュール・パターンは、ひとつのインスタンスに対してプライベート変数と特権メソッドを作成するためのものです。オブジェクトを作成していくつかのデータで初期化し、 このプライベートデータにアクセスできるメソッドを公開する必要がある場合は、 module パターンを使うことができます。
var singleton = function(){
//プライベート変数とプライベート関数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特権/パブリックメソッドとプロパティ
return {
publicProperty: true,
publicMethod : function(){
privateVariable++;
return privateFunction();
}
};
}();





