2017-03-13 16 views
1

John ResigのLearning Advanced Javascriptを読むと、完全に理解できない2つのスライドが出てきました。匿名と名前の付いた関数を参照するプロパティ

スライド#13 - 無名関数であるプロパティを参照します。 2番目のアサートは失敗します。

var ninja = { 
    yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
    } 
}; 
assert(ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either."); // PASS 

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
    samurai.yell(4); 
} catch(e){ 
    assert(false, "Uh, this isn't good! Where'd ninja.yell go?"); // FAIL 
} 

スライド#14 - 定義された機能であるプロパティを参照します。第二の主張は合格する。

var ninja = { 
    yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
    } 
}; 
assert(ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!"); // PASS 

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert(samurai.yell(4) == "hiyaaaa", "The method correctly calls itself."); // PASS 

ここでの唯一の違いは、名前付き関数として定義されたプロパティへの参照も新しいオブジェクトに元のオブジェクト(ninja)を設定した後に残るんなぜyellがスライド14内の名前付き関数であること(または偶数ヌル)?

+0

@Weedoze - いいえ関数の宣言が呼び出されます。関数式はそうではありません。関数の宣言*には名前を付ける必要があります。関数式**には**名前を付けることができます。この質問は、名前付き関数式と無名関数式の違いについてです。関数の宣言は必要ありません。 – Quentin

答えて

1

ここでの唯一の違いは、それが叫ぶあるスライド14

でという名前の関数はありません、それが唯一の違いはありません、また最も重要な違い(それが重要な差異に関連していますが)です。最初のもので

ninja.yellが定義されているか注意してください。

var ninja = { 
    yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^^^^^^^ 
    } 
}; 

それが明示的に自分自身の中ninja.yellを使用しています。したがって、それを呼び出すと、変数ninjaが検索され、yellをプロパティとしてninjaにルックアップしようとします。

var ninja = { 
    yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^ 
    } 
}; 

yellはもはや変数ninja使用して、それだけで自分自身のスコープ内の識別子(名前を経由して機能を与えることによって作成されたものを使用していない:

は、第二の例で定義していることを比較します名前付き関数式)。

ninjaは、最初の例に出てゼロにされたときに理由です:

var ninja = null; 

...最初のものは失敗を開始。 nullyellを検索することはできません。

しかしときninajを1秒(私はジョンは両方のケースでnullを使用しなかった理由を知るが、何でもありません)に置き換えられます。yellは気にしない...

var ninja = {}; 

ninjaを使用していないためです。


サイドノート:ES2015のとおり、yellのどちらのバージョンでは、最初の1が匿名関数式を使用して作成されていても、匿名関数です。 ES2015では、関数はコンテキストに基づいて名前を取得できます。名前を取得する方法の1つは、オブジェクトイニシャライザ内のオブジェクトプロパティに割り当てられることです。ただし、名前が関数内のスコープ内の識別子ではないので、名前付き関数式を使用するときと同じように、この問題は役に立ちません。

+0

よく説明していただきありがとうございます – bflemi3

1

関数式は、関数への参照として評価されます。

foo = function() { ... }; 

ここで、fooの値は、この関数への参照です。あなたは好きな場所にその値をコピーすることができます。関数式命名


自体の内部関数と同じ名前を持つローカル変数を作成します。

foo = function baz() { ... }; 

ここでfooは、グローバルスコープ内の関数への参照です。 bazは、関数のスコープ内の関数への参照です。


任意の変数またはプロパティの値を削除または上書きすることはできますが、その参照のコピーを保持する他の変数またはプロパティには影響しません。

2つのケースの違いは、2番目のリファレンスが別の変数で2番目のリファレンスから始まり、内部でという参照を使用していることです。

関連する問題