Javascript学習ノート 関数⑥:スコープと名前空間_基礎知識
前の紹介で、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 と同じように、どこにでもマクロ定義

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











typedef struct は、構造体の使用を簡素化するために構造体型のエイリアスを作成するために C 言語で使用されます。構造体の別名を指定することで、新しいデータ型を既存の構造体に別名付けします。利点としては、可読性の向上、コードの再利用、型チェックなどが挙げられます。注: エイリアスを使用する前に構造体を定義する必要があります。エイリアスはプログラム内で一意であり、宣言されているスコープ内でのみ有効である必要があります。

Java における変数の期待値の例外は、変数の初期化、null 値の使用、およびローカル変数のスコープの認識によって解決できます。

JavaScript クロージャーの利点には、変数スコープの維持、モジュール化コードの有効化、遅延実行、およびイベント処理が含まれますが、欠点としては、メモリ リーク、複雑さの増加、パフォーマンスのオーバーヘッド、およびスコープ チェーンの影響が挙げられます。

C++ の #include プリプロセッサ ディレクティブは、外部ソース ファイルの内容を現在のソース ファイルに挿入し、その内容を現在のソース ファイル内の対応する場所にコピーします。主に、コード内で必要な宣言を含むヘッダー ファイルをインクルードするために使用されます。たとえば、標準入出力関数を組み込むための #include <iostream> などです。

C++ スマート ポインターのライフ サイクル: 作成: スマート ポインターは、メモリが割り当てられるときに作成されます。所有権の譲渡: 移動操作を通じて所有権を譲渡します。リリース: スマート ポインターがスコープ外に出るか、明示的に解放されると、メモリが解放されます。オブジェクトの破壊: ポイントされたオブジェクトが破壊されると、スマート ポインターは無効なポインターになります。

JavaScript では、this のポインティング タイプには、1. グローバル オブジェクト、2. 関数呼び出し、4. イベント ハンドラー、5. アロー関数 (this の外側の継承) が含まれます。さらに、bind()、call()、および apply() メソッドを使用して、これが何を指すかを明示的に設定できます。

できる。 C++ では、ネストされた関数の定義と呼び出しが可能です。外部関数は組み込み関数を定義でき、内部関数はスコープ内で直接呼び出すことができます。ネストされた関数により、カプセル化、再利用性、スコープ制御が強化されます。ただし、内部関数は外部関数のローカル変数に直接アクセスすることはできず、戻り値の型は外部関数の宣言と一致している必要があります。内部関数は自己再帰的ではありません。

Java のクロージャを使用すると、外部関数が終了した場合でも、内部関数が外部スコープの変数にアクセスできるようになります。匿名の内部クラスを通じて実装されると、内部クラスは外部クラスへの参照を保持し、外部変数をアクティブに保ちます。クロージャによりコードの柔軟性が向上しますが、匿名の内部クラスによる外部変数への参照により、それらの変数が存続するため、メモリ リークのリスクに注意する必要があります。
