関数ではなく変数としての関数宣言


28

関数が次のように宣言されるのをますます見ています

var foo = function() {

    // things
};

私が学んだ方法の代わりに

function foo() {

    // things
}

違いは何ですか?よりよい性能?範囲?この方法を使用する必要がありますか?


javascriptでは、関数がファーストクラスの市民であることは注目に値します。これにより、オブジェクトと同じように動作を渡すことができます。これは、特にコールバックや委任に非常に役立ちます。
クリス・バイ

範囲。「// things」をラップする変数名は、ラップする「// things」と他のJavaScript(ファイル)が含まれる名前の衝突を本質的/うまくいけば防ぎます。別の考え方としては、名前空間「foo」を作成したということです。
レーダーボブ

回答:


25

var foo = function() {} 無名関数を参照する変数を定義します。

function foo() {}名前付き関数を定義しますfoo

どちらも関数パラメータとして名前で渡すことができ、OOPでの使用が意図されている場合はインスタンス化できます。

結局のところ、どちらを使用するかは主に特定のユースケースによって決まります(Javascriptはそのように楽しいです;))。前者を使用する場合は、関数に名前を付けることを強くお勧めします。

var foo = function MY_function() {}。この命名規則は、デバッガーの呼び出しスタックが役に立たないようにするのに役立ちます。


1
function()MYで
間抜けになった

1
@Demian Brecht、およびvar foo = function foo(){...}アプローチはどうですか?
-shabunc

@shabunc:それはどうですか?それは私の答えの最後の段落にリストされています。
デミアンブレヒト

@Demian Brecht、いいえ、実際には最後の段落変数が呼び出されfoo、関数が呼び出されますMY_function
-shabunc

@shabunc:名前は関係ありません。重要なのは、コールスタックの値です。例として、[NAMESPACE] _ [fn name]はMozillaが使用する規則です。プロジェクト全体で規則が一貫している限り、名前自体は重要ではありません。
デミアンブレヒト

13

関数式:

//someFunction(); //wouldn't work when uncommented
var someFunction = function(){ alert('yay'); };

この場合のfunc式は匿名ですが、参照用に変数に割り当てられます。これは、次の点でラベル付き関数ステートメントと異なります。

  • 引き上げることはできません(定義される前に呼び出されます)
  • new someFunction().constructor.name === 'someFunction';//false インスタンスはconstructor.nameのvar名を取得しません。関数への参照がvarに割り当てられますが、関数ではなくvarがvar nameに関連付けられているためです。

ラベル付き関数ステートメントで:

//someFunction(); //works when uncommented
function someFunction(){ alert('yay'); }
  • 巻き上げ作業
  • new someFunction().constructor.name === 'someFunction'; //true 名前は関数に直接結び付けられています。

一般的に言えば、物事が動き回る場合に呼び出しを失敗させたり、1行でメソッドを定義/割り当てたりしない限り、varに式を実行する大きな理由はありません。実際には、内部ファンクとメソッド定義を下部に持つオブジェクトを整理するためにホイストが便利であるため、オブジェクトの実際の動作を取得し、1行のパブリックメソッド定義を(this.同じ名前でファンクを割り当てるだけで)すべて実行できます参照を容易にするためのスポット。コンストラクターIMOには常にラベル付きステートメントを使用するようにしてください。そうすれば、コンストラクターを介してオブジェクトの「タイプ」を識別できます。


8

最初の例は式であり、2番目の例はステートメントです。関数を式として定義すると、定義が発生する場所、割り当てることができるもの、パラメータとして渡すことができる柔軟性などがより柔軟になります。

例えば:

SomeThing('abc', function(a,b) {return a*b;});

対...

function tmp(a,b) { 
    return a*b;
}

SomeThing('abc', tmp);

関数式の構文がないと、より複雑な例は明らかに複雑になります。

見てくださいhttps://stackoverflow.com/questions/111102/how-do-javascript-closures-work


4

主な実際の違いは巻き上げです。例えば:

foo(); // alerts 'hello'
function foo() {alert('hello');}

foo(); // throws an error since foo is undefined
var foo = function() {alert('hello');}

また、これは未定義の動作です

function foo(){
  if (true) {
    function bar(){}
  }
  bar();
}

これは大丈夫です。

function foo(){
  if (true) {
    var bar = function(){}
  }
  bar();
}

7
JSの関数内で関数を定義することには、まったく問題はありません。JSで関数を定義できない場所は多くありません。
エリックReppen

2
@ErikReppen非関数ブロック内(ifステートメント内など)で関数宣言を使用することは絶対にできません。別の関数内で使用できない箇所を見つけることができないようです。
オースティン

@Austin ifステートメント内の関数定義にも問題はありません!
ティム

@オースティン:おそらくあなたはw3schoolsでそれを読んでいますか?;)
デミアンブレヒト

2
@ErikReppen関数式はどこでも使用できます。関数宣言はできません。stackoverflow.com/questions/10069204/…を
オースティン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.