ホームページ  >  記事  >  ウェブフロントエンド  >  Javascript学習ノート 関数⑥:スコープと名前空間_基礎知識

Javascript学習ノート 関数⑥:スコープと名前空間_基礎知識

WBOY
WBOYオリジナル
2016-05-16 16:30:461570ブラウズ

前の紹介で、JavaScript にはブロックレベルのスコープはなく、関数レベルのスコープのみがあることをすでに知っています。

コードをコピーします コードは次のとおりです:

function test() { // スコープ
for(var i = 0; i // カウント
}
console.log(i); // 10
}

JavaScript には明示的な名前空間もありません。つまり、すべてがグローバル スコープで定義されます。変数が参照されるたびに、JavaScript は変数が見つかるまでグローバル スコープ全体を走査します。グローバル スコープ全体を走査しても変数が見つからない場合は、ReferenceError がスローされます。

画像の説明を入力してください

暗黙的なグローバル変数

コードをコピーします コードは次のとおりです:

// スクリプト A
foo = '42';
// スクリプト B
var foo = '42'

上記の 2 つの例は、異なる効果を生み出します。 1 つ目はグローバル スコープで変数 foo を定義し、2 つ目は現在のスコープで変数 foo を定義します。
キーワード var を使用しないと、予期しない影響が生じることに注意する必要があります。

コードをコピーします コードは次のとおりです:

// グローバル スコープ
var foo = 42;
関数 test() {
// ローカルスコープ
foo = 21;
}
テスト();
ふー; // 21

関数テストでは変数 foo の定義に var が使用されていないため、関数外のグローバル変数 foo は上書きされます。大きな問題のようには見えないかもしれませんが、コードが数千行ある場合、これを追跡するのは困難なバグになる可能性があります。

コードをコピーします コードは次のとおりです:

// グローバル スコープ
var items = [/* いくつかのリスト */];
for(var i = 0; i subLoop();
}
関数 subLoop() {
// subLoop
のスコープ for(i = 0; i // 素晴らしいことをやります!
}
}

上記の例では、サブループ関数内の変数 i が外側のグローバル変数 i を上書きするため、外側のループは最初の実行時に停止します。このエラーを回避するには、関数内に var を追加するだけで済みます。そのため、変数を定義するときにキーワード var を忘れずに追加してください。本当に外部グローバル変数に影響を与えたくない場合は除きます。

ローカル変数

JavaScript のローカル変数は 2 つの方法でのみ生成できます。1 つはキーワード var を使用して宣言する方法、もう 1 つは関数の仮パラメータとして生成する方法です。

コードをコピーします コードは次のとおりです:

// グローバル スコープ
var foo = 1;
var bar = 2;
var i = 2;
関数テスト(i) {
// 関数テストのローカル スコープ
i = 5;
var foo = 3;
バー = 4;
}
テスト(10);

このとき、関数 test 内の変数 i と foo はローカル変数であり、bar は外部グローバル変数 bar を上書きします。

吊り上げ

JavaScript は変数宣言をホイストします。これは、var 式と関数宣言の両方がスコープの先頭にホイストされることを意味します。

コードをコピーします コードは次のとおりです:

bar();
var bar = function() {};
var someValue = 42;
テスト();
関数テスト(データ) {
If (偽) {
goo = 1;
} else {
var goo = 2;
}
for(var i = 0; i var e = data[i];
}
}

上記のコードを実行する前に、var 式と関数 test の宣言が先頭に昇格されるため、プログラムは正常に実行され、エラーは報告されません。

コードをコピーします コードは次のとおりです:

// var ステートメントはここに移動されました
var bar, someValue; // デフォルトは '未定義'
// 関数宣言も上に移動しました
関数テスト(データ) {
var goo, i, e; // ブロックスコープが見つからない場合、これらはここに移動されます
If (偽) {
goo = 1;
} else {
goo = 2;
}
for(i = 0; i e = データ[i];
}
}
bar(); // bar がまだ「未定義」であるため、TypeError で失敗します
someValue = 42; // 代入はホイスティングの影響を受けません
bar = function() {};
テスト();

JavaScript にはブロックレベルのスコープがないため、var 式が高度になるだけでなく、if 構造も直感的ではなくなります。
上の例では、 if がグローバル変数 goo を操作しているように見えますが、実際には、変数 goo はプロモートされているため、変更されるのはローカル変数です。
ホイスティングのルールを理解していないと、次のコードは ReferenceError をスローすると思うかもしれません。

コードをコピーします コードは次のとおりです:

// Some importantThing が初期化されているかどうかを確認します
if (!Some importantThing) {
var Some importantThing = {};
}

もちろん、コードが実行される前に var 式が先頭に昇格されているため、上記のコードにはエラーはありません。

コードをコピーします コードは次のとおりです:

var Some importantThing;
// 他のコードがここで Some importantThing を初期化する場合もあれば、そうでない場合もあります
// そこにあることを確認してください
if (!Some importantThing) {
重要なこと = {};
}

@nightire Fan Ge のブログ投稿「JavaScript を理解する (2)」をおすすめします。この記事では改善点について非常に詳しく説明しています。
名前解決の順序

関数スコープ内で foo 変数にアクセスしようとすると、JavaScript は次の順序で検索します:

現在のスコープに var foo の定義があるかどうか。
関数パラメータに foo 変数があるかどうか。
関数自体の名前が foo であるかどうか。
外部ドメインにジャンプして最初の部分から検索します。
ネームスペース

最も一般的な問題の 1 つは名前の競合です。これは、Javascript のグローバル スコープが 1 つだけであることが原因で発生します。しかし、この問題は匿名の外部関数によって解決できます。

コードをコピーします コードは次のとおりです:

(関数() {
// 自己完結型の「名前空間」
window.foo = function() {
// 公開されたクロージャー
};
})(); // 関数をすぐに実行します

上記の例の匿名関数は式とみなされ、実行されます。

コードをコピーします コードは次のとおりです:

( // 括弧内の関数を評価します
function() {}
) // そして関数オブジェクトを返します
() // 評価結果を呼び出します

もちろん、別の方法で関数式を呼び出すこともできます。構造は異なりますが、結果は同じです。

コードをコピーします コードは次のとおりです:

//
を直接呼び出すためのその他のスタイル !function(){}()
関数(){}()
(関数(){}());
// など...

概要

匿名外部関数を使用してコードをスペースにカプセル化することをお勧めします。これにより、名前空間の競合が解決されるだけでなく、プログラムのモジュール化も容易になります。
さらに、グローバル変数の使用は、保守にコストがかかり、エラーが発生しやすいため、推奨されません。

名前空間の型、関数、変数、テンプレートなどはすべてエンティティに属します。
エンティティに共通する主な点は、エンティティに名前を付けることができることです。 (また、ラベルには名前を付けることもできますが、それは実体ではありません。)
名前空間スコープは、ブロック スコープ、クラス スコープ、関数プロトタイプ スコープ、関数スコープ (ラベルにのみ有効) と同様に、スコープの種類の総称です。名前空間内で宣言された名前は、名前空間スコープ内にあります。グローバル名は、暗黙的なグローバル名前空間スコープ内にあるとみなされます。

ネームスペースの役割は確かにスコープですが、同じネームスペースを複数の場所で複数回宣言できますが、それらの内容は最終的に 1 つの名前に結合されます。スペース、std と同じように、どこにでもマクロ定義

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。