JavaScript上級プログラム設計の関数表現の再帰は7.1ノートを取る


関数式はJavaScriptの中の一つで、強くて困惑しやすい特性です.第5章で紹介された関数の定義
この方法には二つの種類があります.一つは関数宣言、もう一つは関数式です.関数宣言の文法はこうです.
function functionName(arg0, arg1, arg2) {
//   

}

//  Firefox、Safari、Chrome  Opera   

alert(functionName.name); //"functionName"
まずFunctionキー、そして関数の名前です.これが関数名を指定する方式です.Firefox、Safari、Chrome、Operaは関数に標準ではないname属性を定義しています.この属性を通じて関数に指定された名前にアクセスできます.これ
属性の値は常に、functionキーの後に続く識別子に等しいです.
関数宣言については、関数宣言の昇格という重要な特徴があります.コードを実行する前に関数宣言を先に読み込むという意味です.これは、関数宣言を呼び出し文の後に置くことができるということです.
sayHi();
function sayHi(){
alert("Hi!");
}
この例はエラーが発生しません.コード実行前に関数宣言を読みます.2番目の関数を作成する方法は、関数式を使用します.関数式にはいくつかの異なる文法形式があります.以下は最も一般的な形式です.
var functionName = function(arg0, arg1, arg2){
//   
};


このような形式は、従来の変数割当文のように見えます.すなわち関数を作成し、変数functionNameに値を与えます.
この場合に作成された関数は匿名関数と呼ばれ、functionキーの後ろに識別子がないからです.
(匿名関数はラムダ関数とも呼ばれることがある.)匿名関数のname属性は空の文字列である.
関数式は他の表式と同じです.使う前に値を先に与えなければなりません.以下のコードはエラーを引き起こします.
sayHi(); //  :      
var sayHi = function(){
alert("Hi!");
};
は、関数アップグレードの鍵を理解し、関数宣言と関数表現の違いを理解することである.例えば、以下のコードを実行した結果、
思いがけないことができる.
//     !
if(condition){
function sayHi(){
alert("Hi!");
}
} else {
function sayHi(){
alert("Yo!");
}
}
表面では、上記のコードはconditionがtrueであるときに、sayHi()の定義を使用することを表しています.他のものを使用します.
一つの定義.実際、これはECMAScriptの中で無効な文法です.JavaScriptエンジンはエラーを修正して、それを合に変換します.
の状態です.問題はブラウザがバグを修正しようとするやり方が一致していません.ほとんどのブラウザは第二の宣言を返します.無視します.
conditionFirefoxはconditionがtrueであるときに最初の声明を返します.このような使い方は危険です.
あなたのコードに表示されます.しかし、関数式を使うなら、問題はありません.
//     
var sayHi;
if(condition){
sayHi = function(){
alert("Hi!");
};
} else {
sayHi = function(){
alert("Yo!");
};
}
この例は何の意外もないです.違う関数はconditionによってsayHiに割り当てられます.
関数を作成して変数に値を付けることができます.関数を他の関数の値として返します.第5章の中のあれを覚えています.
createCompriso Function関数ですか?
function createComparisonFunction(propertyName) {
return function(object1, object2){
var value1 = object1[propertyName];
var value2 = object2[propertyName];

if (value1 < value2){
return -1;
} else if (value1 > value2){
return 1;
} else {
return 0;
}
};
}
createComprison Functionは匿名関数を返しました.返した関数は変数に与えられます.
または他の方法で呼び出されます.しかし、createCompriso Function関数の内部では匿名です.関数
値として使用する場合は、匿名関数を使用することができます.しかし、匿名関数の唯一の用途ではない.
7.1再帰
再帰関数は、一つの関数が名前で自身を呼び出した場合に構成されます.
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * factorial(num-1);
}
}
これは古典的な再帰的階乗関数です.この関数は表面的には問題ないようですが、下のコードはエラーを引き起こす可能性があります.
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4)); //  !
以上のコードはまずfactoral関数を変数another Factorialに保存し、factoral変数を設定します.
nullにすると、元の関数を指す参照が一つしか残っていません.ただし、次にanother Factorialを呼び出す場合は、必ず
factoralを実行する必要がありますが、factoralはもう関数ではないので、エラーが発生します.この場合、アーグメンントを使います.
caleeはこの問題を解決できます.
argments.calleeは実行中の関数を指す指針であることを知っていますので、関数を実現するためにそれを使ってもいいです.
の再帰的呼び出し、例えば、
function factorial(num){
if (num <= 1){
return 1;
} else {
return num * arguments.callee(num-1);
}
}
太字コードでは、関数名の代わりにargments.calleeを使うことによって、どのように関数を呼び出してもできないことを確認できます.
問題が起こる.したがって、再帰関数を作成するときは、アーグメンツ.calleeを使うほうが、関数名を使うよりもずっと安全です.
ただし、厳密なモードでは、スクリプトからargments.caleeにアクセスできません.この属性にアクセスするとエラーが発生します.けれども
名前付き関数式を使って同じ結果を達成します.たとえば:
var factorial = (function f(num){
if (num <= 1){
return 1;
} else {
return num * f(num-1);
}
});
以上のコードはf()というネーミング関数式を作成し、変数factorialに値を与えます.関数を
他の変数に値を割り当てましたが、関数の名前fはまだ有効ですので、再帰的に呼び出しても正しく完了します.この方式は厳格なモードと
ハードモードでなくても大丈夫です.