JSの関数定義方式及び声明の前倒し

2852 ワード

前言
javascriptの関数定義は特殊で、それぞれの特徴が異なるので、JSのいくつかの関数定義方式とそれぞれの長所と短所を紹介し、JSの関数宣言と変数宣言のhoist(前倒し)について簡単に説明します.
関数定義方式
関数生命式
これはjsでよく使われている方式です.
function funcname(a,b){
  //    
}
この関数を呼び出すと、関数が実行されます.
functionコンストラクタ方式
var funcname = new Function ('x', 'y', 'alert(x+y)');
この定義方式の前の二つはパラメータであり、パラメータは任意の複数の文字列であってもよい.三つ目は関数体で、JavaScript文はすべて含められます.文の間はセミコロンで区切られます.パラメータがない場合は、関数体を転送すればいいです.関数には関数名を宣言する文字列がないので匿名関数です.
関数の直接量
var funcname = function(a,b){
  //    
}
違います
3つの方法の違いは、スコープ、効率、ローディング順序から区別されてもよい.まず、機能領域から言えば、関数宣言式と関数の直接量は局所変数を使いますが、Function()コンストラクタは大域変数です.
var y = 'global';
function a(){
  var y = 'local a';
  return y;
}
alert(a());//  'local a'
var b = function(){
  var y = 'local b';
return y;
}
alert(b()) //  'local b'
function c(){
  var y = 'local c';
  return new Function('return y');
}
alert(c()());//  'global',  Function()        y,            。
効率を見ると、Function()のコンストラクタの効率は他の2つの方法より低くなります.特に循環体では、コンストラクタが実行されるたびに再コンパイルされ、新しい関数オブジェクトが生成されます.
最後にロード順序であり、function方式(すなわち関数宣言式)はJavaScriptコンパイル時にロールドメインにロードされ、他の2つの方法はコード実行時にロードされ、定義前に呼び出したらundefinedに戻る.
関数宣言と変数宣言の前倒し
上記の3つの定義方式に対する比較から、関数宣言方式だけで定義されている関数はJSコンパイル時に作用域にロードされます.これはJSにおける声明の前倒しと考えられます.
変数宣言の前倒し:
(function() {
  console.log(a);//undefined
  var a = "Now it's defined!";
  console.log(a);//"Now it's defined!"
})();
Aを定義していないときに出力aがundefinedを提示しましたが、エラーが発生していません.これはJavaScript解析器が作った鬼です.解像器は現在の作用領域で宣言しているすべての変数と関数を作用領域の先頭に置いていますが、変数だけの声明は作用領域の開始前に行われています.
JavaScriptはこのような「奇癖」を持っていますので、多くのコードガイドを見て、変数宣言を作用領域の一番上に置くように提案します.そうすると、いつも注意してください.
関数宣言の前:
第一の場合:
isItHoisted();//"Yes!"
function isItHoisted() {  
    console.log("Yes!");
}
上述のように、JavaScript解釈器は関数宣言の前に使用することができます.つまり、関数宣言は関数名だけではなく、関数の定義も前倒しされました.したがって、上記のコードは正しく実行できます.
第二の場合:
funca();//"Definition hoisted!"
funcb();//    :undefined is not a function
 
function funca() {  
    console.log("Definition hoisted!");
}
var funcb = function () {  
    console.log("Definition not hoisted!");
};
私たちは対比をしました.funca関数は適切に実行されました.第一のタイプに合います.funcb関数変数は「前倒し」されましたが、彼の赋値(つまり関数)は前倒しされていません.この点では、前に述べた変数「前倒し」と完全に一致しています.また、「前倒しされた」変数のデフォルト値はundefinedですので、エラーは「タイプ不一致」です.undefinedは関数ではありません.もちろん呼び出しはできません.
締め括りをつける
上記の説明を通して、次のようにまとめられます.
  • 変数の宣言は、スコープの上部に前倒しされ、割当値は元の場所に保持されています.
  • 関数宣言方式定義関数全体「前倒し」
  • 関数の直接量定義関数の方式は変数が「前倒しされた」だけです.関数は「前倒しされた」
  • がありません.
    ちょうど前に述べた関数で定義された3つの異なる方法の違いと一致しています.
    したがって、みなさんに注意してください.最善の実践として、変数宣言は必ず作用ドメイン/関数の一番上に置く必要があります.(JavaScriptは関数のスコープしかありません.)