6

John Resig の Secrets of JS ninja スライドをフォローしていて、はっきりと理解できないものを見つけました。次のコードは、名前付き関数式を定義します。

var ninja = function myNinja(){
  console.log(myNinja); // function myNinja() {...}
};
myNinja; // undefined

ご覧のとおり、現在のスコープ (グローバルであると仮定) ではninja、名前付き関数への参照を保持する変数ですmyNinjaninjavariable はスコープ内でアクセス可能です - これは明らかですが、スコープ内ではmyNinjaアクセスできません (ただし、独自の関数内ではアクセス可能です)。どうして?

関数を定義する場合 (関数式ではなく関数宣言を使用):

function Cheese() {
  console.log(Cheese);
}

その後、現在のスコープでアクセスできます。これがそのように機能することは知っていますが、誰かがその理由を説明できますか?

4

4 に答える 4

4

John Resig は、彼の著書The Secrets of the JavaScript Ninjaで、この概念について素晴らしい説明をしています。

http://jsninja.com/

以下、本からの引用です。

4.2.4. インラインの名前付き関数

 <script type="text/javascript">
  var ninja = function myNinja(){ 
      assert(ninja == myNinja, "this is named two things at once!"); 
  };
  ninja(); 
  assert(typeof myNinja == "undefined",
    "But myNinja isn't defined outside of the function."); 
 </script>

このリストは、インライン関数に関する最も重要な点を示しています。インライン関数には名前を付けることができますが、それらの名前は関数自体の中でのみ表示されます。

第 3 章で説明したスコープ規則を覚えていますか? インライン関数名は変数名のように機能し、そのスコープは宣言されている関数に限定されます。

3.2.1. スコーピングと機能

変数の宣言は、ブロックの入れ子に関係なく、宣言のポイントから変数が宣言されている関数の最後までの範囲内にあります。

この概念について詳しく知りたい場合は、この本が役に立ちます。

于 2013-07-03T12:04:09.840 に答える
1

何故ですか?

関数式は、評価されるたびに新しい関数オブジェクトを作成します。その結果で何が起こるかは、最初は無関係です。しかし…</p>

var ninja;
// myNinja; - what would you expect it to be here?
for (var i=0; i<5; i++)
    ninja = function myNinja(){
        console.log(myNinja);
    };
// myNinja; - *which one* would you expect it to be here?
ninja();

への呼び出しninja()は明らかで、最後にその変数に割り当てられた関数を参照します。そして、myNinja現在関数オブジェクトをconsole.log参照しています-それは独自のスコープにあります。

しかし、myNinja識別子は関数自体の外ではあいまいです。

対照的に、関数宣言は巻き上げられ、スコープ全体からアクセスできます。その識別子は、スコープの初期化で一度作成される単一の関数オブジェクトを一意に参照します。

于 2013-07-03T12:24:38.760 に答える
0

単純に関数 (cheese) を定義するときに、現在のスコープを伝えると想像してください。「この関数を知ってもらいたいのですが、その名前は Cheese です。var ninja を使用すると、ninja スコープを処理して、それを伝えることになります。基本的には同じですので、新しい関数 (myNinja) は現在の (ninja) スコープでのみ認識されます...

于 2013-07-03T11:29:31.933 に答える
0

Name は関数オブジェクトのプロパティです。デバッガーで Function インスタンスを調べると、nameその上にプロパティが表示されます。グローバル スコープで定義された関数の場合、 の値は、それが参照されるオブジェクトnameのプロパティの名前として自動的に使用され ます。window

インライン関数の場合、関数が参照されるプロパティの名前を定義しています。nameJS エンジンは、Function インスタンスのプロパティを使用する必要はありません。

于 2013-07-03T12:48:45.740 に答える