JavaScriptネスト関数


96

私は私が理解していないjavascriptのコードを取得しました:

function dmy(d) {
    function pad2(n) {
        return (n < 10) ? '0' + n : n;
    }

    return pad2(d.getUTCDate()) + '/' +
       pad2(d.getUTCMonth() + 1) + '/' +
       d.getUTCFullYear();
}

function outerFunc(base) {
    var punc = "!";

    //inner function
    function returnString(ext) {
       return base + ext + punc;
    }

    return returnString;
}

関数を別の関数内でどのように定義できますか?my()関数の外部からpad2()を呼び出すことはできますか?

少し光を当ててください。ありがとう


13
関数は関数の内部で作成できます。それは完全に有効です。
0x499602D2 2011

回答:


140

関数は、JavaScriptのもう1つのタイプの変数です(もちろん、多少のニュアンスがあります)。別の関数内で関数を作成すると、変数のスコープを変更するのと同じ方法で関数のスコープが変更されます。これは、グローバルな名前空間全体の汚染を減らすためにクロージャーと併用する場合に特に重要です。

別の関数内で定義された関数は、関数の外部からアクセス可能なオブジェクトにアタッチされていない限り、関数の外部からはアクセスできません。

function foo(doBar)
{
  function bar()
  {
    console.log( 'bar' );
  }

  function baz()
  {
    console.log( 'baz' );
  }

  window.baz = baz;
  if ( doBar ) bar();
}

この例では、baz関数はfooオーバーライドされているため、関数の実行後に使用できますwindow.baz。bar関数は、内部に含まれるスコープ以外のコンテキストでは使用できません。foo関数。

別の例として:

function Fizz(qux)
{
  this.buzz = function(){
    console.log( qux );
  };
}

Fizz機能を実行すると、それが割り当てられますようにコンストラクタとして設計されてbuzz新しく作成されたオブジェクトに関数を。


window.baz = bazとは何ですか?なぜこのラインm?ke bazが利用できるのですか?
Ziyang Zhang

@ZiyangZhang、そのコードブロックの後の段落に説明がありますが、不明確な特定の部分はありましたか?
zzzzBov

35

それは閉鎖と呼ばます。

基本的に、他の関数内で定義された関数は、この関数内でのみアクセスできます。ただし、結果として渡され、この結果が呼び出される場合があります。

これは非常に強力な機能です。あなたはここでより多くの説明を見ることができます:

javascript_closures_for_dummies.html Archive.orgのミラー


13
function x() {}

と同等(または非常に類似)

var x = function() {}

間違えない限り。

だから何もおかしいことはありません。


8
最初の構文はドキュメントの先頭に移動されます。そのため、関数が初期化される前に関数 'x'を呼び出すことが可能です。
トム

10
最初の構文では、名前付き関数を使用してより優れたスタックトレースが得られ、2番目の構文では頭痛の種になります
TheZ

@TheZ私は最近、Chromeがデバッグに関数名の推論を追加したので、一般的なケースで以前と同じ頭痛が発生しないと思います。
jinglesthula

@jinglesthulaはい!Chromeはしばらく前にこの名前の推論を追加し、それは非常に高く評価されています:)
TheZ

10

関数のインスタンス化は、関数の内部と外部で許可されます。これらの関数の内部では、変数と同様に、ネストされた関数はローカルであるため、外部スコープから取得できません。

function foo() {
    function bar() {
        return 1;
    }
    return bar();
}

foobarそれ自体の中で操作します。bar外部スコープで定義されていない限り、外部スコープからはアクセスできません。

したがって、これは機能しません:

function foo() {
    function bar() {
        return 1;
    }
}

bar(); // throws error: bar is not defined

4

関数内で関数を宣言すると、内部関数はそれらが宣言されているスコープでのみ使用できます。または、あなたの場合、pad2dmyスコープます。

に存在するすべての変数dmyはで表示されますがpad2、それ以外の場合は発生しません:D


2

関数内に関数があることは、Javascript(および多くの言語)では完全に正常です。

時間をかけて言語を学習してください。すでに知っているものと類似しているという理由で使用しないでください。Act III:Function the Ultimate(ビデオのダウンロード、スライド、およびトランスクリプトへのリンク)に特に重点を置いて、Javascriptに関するDouglas Crockfordの一連のYUIプレゼンテーションをご覧になることをお勧めします。


0

function foo() {
  function bar() {
    return 1;
  }
}
bar();

エラーをスローします。以来bar内側に定義されているfoobar唯一のアクセスの内側になりますfoo
使用barするには、内部で実行する必要がありますfoo

function foo() {
  function bar() {
    return 1;
  }
  bar();
}

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.