13

今日、同僚と Javascript のネストされた関数について話し合いました。

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

この例では、c と同様に、b は a の本体の外では到達できないことが試行で指摘されています。ただし、d は - a() の実行後です。ECMAScript v.3 標準でこの動作の正確な定義を探しましたが、探していた正確な言葉遣いが見つかりませんでした。Sec.13 p.71 が述べていないのは、関数宣言ステートメントによって作成された関数オブジェクトがどのオブジェクトにバインドされるかです。何か不足していますか?

4

5 に答える 5

22

これは静的スコープです。関数内のステートメントは、その関数内でスコープされます。

ただし、Javascript には風変わりな動作があります。つまり、varキーワードがないと、グローバル変数が暗示されます。それがあなたのテストで見ているものです。「d」変数は、関数の本体内に記述されているにもかかわらず、暗黙のグローバルであるため使用できます。

また、質問の 2 番目の部分に答えるには: 関数は、変数と同様に、宣言されているスコープに存在します。

補足: グローバル変数、特に暗黙の変数は必要ないでしょう。混乱を防ぎ、すべてをクリーンに保つために、常に var キーワードを使用することをお勧めします。

補足: ECMA 標準は、Javascript に関する回答を見つけるのにおそらく最も役立つ場所ではありませんが、確かに悪いリソースではありません。ブラウザの JavaScript はその標準の単なる実装であることを忘れないでください。そのため、標準ドキュメントは、JavaScript エンジンが構築されたときに実装者が (ほとんど) 従った規則を提供します。気になる実装、つまり主要なブラウザーに関する特定の情報を提供することはできません。特に、主要なブラウザーでの JavaScript の実装がどのように動作するかについて非常に直接的な情報を提供する書籍が 2 冊あります。違いを説明するために、ECMAScript 仕様と Javascript に関する本の両方からの抜粋を以下に示します。私はあなたを思う'

これはECMAScript言語仕様からのものです:

10.2実行コンテキストの入力

関数がそれ自体を再帰的に呼び出している場合でも、すべての関数とコンストラクターの呼び出しは新しい実行コンテキストに入ります。すべての return は実行コンテキストを終了します。スローされた例外は、キャッチされない場合、1 つ以上の実行コンテキストを終了することもあります。

制御が実行コンテキストに入ると、スコープ チェーンが作成および初期化され、変数のインスタンス化が実行され、この値が決定されます。

スコープ チェーンの初期化、変数のインスタンス化、および this 値の決定は、入力されるコードのタイプによって異なります。

以下は、O'Reilly のJavascript: The Definitive Guide (第 5 版)からのものです。

8.8.1 レキシカルスコープ

JavaScript の関数は、動的にスコープされるのではなく、レキシカルにスコープされます。これは、実行元のスコープではなく、定義されているスコープで実行されることを意味します。関数が定義されると、現在のスコープ チェーンが保存され、関数の内部状態の一部になります。...

これらの種類の質問をカバーするために強く推奨されるのは、Douglas Crockford の本です。

JavaScript、良い部分 http://oreilly.com/catalog/covers/9780596517748_cat.gif

Javascript、The Good Partsも O'Reilly から。

于 2008-10-24T21:54:18.327 に答える
4

私が理解しているように、スコープに関する限り、これらは同等です。

function a() { ... }

var a = function() { ... }
于 2008-10-24T21:53:03.273 に答える
2

d は「グローバル」として作成されていますが、実際には window オブジェクトのプロパティとして作成されていることに注意することが重要です。これは、window オブジェクトに既に存在するものをうっかり上書きしてしまったり、実際には変数の作成にまったく失敗したりする可能性があることを意味します。そう:

function a() {
    d = 'Hello World';
}
alert(window.d); // shows 'Hello World'

ただし、次のことはできません。

function a() {
    document = 'something';
}

window.document オブジェクトを上書きできないためです。

with(window)すべての実用的な目的のために、すべてのコードが巨大なブロックで実行されていることをイメージできます。

于 2008-10-24T23:02:19.203 に答える
1

Javascript には 2 つのスコープがあります。グローバルで機能的。「var」キーワードを使用して関数内で変数を宣言すると、その関数と内部関数に対してローカルになります。関数の外で変数を宣言すると、グローバル スコープになります。

最後に、最初に変数を宣言するときに var キーワードを省略すると、javascript は、どこで宣言しても、グローバル変数が必要であると想定します

つまり、関数 a を呼び出しており、関数 a はグローバル変数 d を宣言しています。

于 2008-10-24T23:39:25.230 に答える
0

...

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   d = 'Bound to global object.'
}

varを前に付けなくても、d はグローバルです。d を非公開にするには、次のようにします。

function a() {
   function b() {
      alert('boo')
   }
   var c = 'Bound to local call object.'
   var d = 'Bound to local object.'
}
于 2008-10-24T21:56:57.090 に答える