ホームページ >ウェブフロントエンド >jsチュートリアル >NetEase JS 面接の質問と Javascript 語彙範囲の説明_JavaScript スキル

NetEase JS 面接の質問と Javascript 語彙範囲の説明_JavaScript スキル

WBOY
WBOYオリジナル
2016-05-16 18:16:401601ブラウズ

呼び出し元のオブジェクトはスコープ チェーンの先頭にあります。ローカル変数 (関数内で var で宣言された変数)、関数パラメーター、および Arguments オブジェクトはすべて関数内でスコープされます。つまり、スコープ チェーンより上位のものはすべて隠蔽されます。同じ名前で。

2010 年 9 月 14 日、私は NetEase の Web エンジニア就職説明会に行き、JS エンジニアのポジションに応募しました。運よく筆記試験を受けられたのですが、運よく筆記試験で落ちてしまいました(笑)。くだらない話はやめて、重大な影響を与える質問を選び、もう一度勉強してください。

おそらく質問は次のとおりです。次のコードの出力を書いて分析してください

コードをコピーしてください コードは次のとおりです:

var tt = 'aa';
alert(tt);警告(tt;怪我。私の答えは - aa と dd、分析です。最初にグローバル変数の結果が出力され、次にローカル変数 tt がグローバル変数によって参照される値を上書きするため、2 回目の出力結果は dd になります。

私がこのように答えているのを見た人は、私が自分自身を教育しようとしていると思うでしょう - その考えは非常に単純です (私もそう思います)!

NetEase さん、この回答にどうして満足できるのでしょうか。

正しい答えは、未定義および dd です。

最初のアラートの結果が未定義なのはなぜですか?わかりやすく説明するには、JavaScript の字句スコープを使用する必要があります。

JavaScript の関数は、「実行されるスコープではなく、定義されているスコープで実行されます。」これは権威あるガイドの抽象的かつ明確な要約です。

JavaScript ロジックは、デフォルトではグローバル スコープで実行されます。たとえば、上記のプログラム セグメントの「var tt='aa';」は、グローバル スコープでグローバル変数を定義します (上記のコード セグメントがそうでない場合)。ある関数チェーンから抜粋)。 test() 関数の内部ロジックは、テスト関数自体のスコープ (局所性) を元のスコープ (グローバル スコープ) チェーンに追加する必要があります。これらの考え方は、ほとんどすべての言語でこのように定義されています。ただし、JavaScript の特別な点は次のとおりです。スコープチェーンとは、関数の定義を関数内にネストできることです (これがクロージャーの基礎です。注: 関数は JS のコードスコープの唯一の形式です)

ネストされた内部関数 外部関数を呼び出すことができる変数(ネストされた関数) およびその他のネストされた関数 (関数はデータの一種です)。ネストされた関数が外部関数内で呼び出された場合、呼び出し元のオブジェクトは変更されません。外部関数の実行後、すべてのデータ (外部関数とネストされた内部関数を含む) がガベージ コレクション メカニズムによって収集されます。これはまだ反映できません。 「クロージング」の本質。入れ子になった関数が「ガベージ コレクション」されている場合でも、Javascript で入れ子になった内部関数への外部呼び出しが許可される状況があります。最も一般的なのは、「関数」で入れ子になった内部関数を含む特定の要素を定義することです。イベントに応じて、ページがロードされると、ネストされた関数 (「特定の関数」) が実行されます (ガベージ コレクションされました)。ただし、イベントがトリガーされると、依然として応答アクションが存在し、応答関数も呼び出される可能性があります。ネストされた関数 (「関数」) で定義された変数の最終値 (ガベージ コレクションではありませんか?)。

クロージャの知識や例については、たくさんの情報が入手可能ですが、説明するつもりはありません。

この記事の焦点は、次の非常に重要な詳細です:

呼び出し元のオブジェクトは、スコープ チェーンのフロント エンドにあります。ローカル変数 (関数内で var で宣言された変数)、関数です。パラメーターと Arguments オブジェクトはすべて関数内のスコープ内にあります。これは、スコープ チェーンより上位にある同じ名前のプロパティを非表示にすることを意味します。

つまり、上記のプログラム部分では、テスト関数内の「var tt='dd'」により、テスト関数が呼び出されたときに「var tt='aa'」が完全に非表示になります。さらに、tt は最初のアラート ステートメントの後に定義されるため、最初のアラートが呼び出された時点では、tt にはまだ値が割り当てられていません。これはより明確かもしれません。つまり、テスト関数を定義するとき、最初のアラート (tt) を定義するときに、tt がスコープ チェーン内の変数であることが記録されますが、その (tt) 値は記録されません。関数の定義が完了すると、tt がスコープに追加されるため、最初のアラート ステートメントはスコープ内で tt を見つけることができます (つまり、関数内で宣言されているが割り当てられていない tt を見つけるのと同じです)値)。

上記のプログラム フラグメントの実行結果は、次のフラグメントの結果と同じです:





コードをコピー


コードは次のとおりです:
var tt = 'aa'; function test(){ alert(tt); >tt = 'dd'; アラート(tt) テスト();
JavaScript の範囲は、C などの言語の考え方では単純に理解できません! C では関数を呼び出す前に関数を宣言または定義する必要がありますが、JavaScript ではその必要がありません。 JavaScript では、最初に関数を呼び出してから、その関数を定義できます (呼び出す前に宣言を行う必要はありません)。関数を呼び出すときに、JavaScript はスコープ チェーンに関数の定義を要求するため (関数は、実行されるスコープではなく、関数が定義されているスコープで実行されます)

たとえば、上記のコードは次のように記述されます。 :
コードをコピーします コードは次のとおりです。

var tt = 'aa'; 🎜>test() ; //最初に呼び出してから、
関数 test(){
alert(tt); //未定義
var tt = 'dd'; //dd
}


上記のコード スニペットは同じ結果を得ることができますが、そのようには書かないことをお勧めします。これは悪い習慣であり、コードの保守は容易ではありません。 。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。