JSスコープとスコープチェーンを詳しく解説_基礎知識
(1) 範囲
変数のスコープとは、プログラムのソースコード内で定義された変数の領域です。
1. JS で字句スコープが使用されます
関数内で宣言されていない変数 (関数内で var が省略されている場合もグローバルとみなされます) は、グローバル変数 (グローバル スコープ) と呼ばれます
関数内で宣言された変数は関数スコープを持ち、ローカル変数です
ローカル変数はグローバル変数よりも優先されます
var name="one";
関数テスト(){
var name="two";
console.log(name); //2
}
テスト();
関数内で var を省略すると、実際にはグローバル変数に書き換えられるため、グローバル変数に影響します
var name="one";
関数テスト(){
name="2";
}
テスト();
console.log(name); //2
関数スコープ、つまり関数はスコープの基本単位です。js には if for などの c/c のようなブロックレベルのスコープがありません。
関数テスト(){
for(var i=0;i If(i==5){
var name = "one";
}
}
console.log(名前); // 1 つ
}
test(); //関数レベルのスコープなので、name="one"
にアクセスできます。
もちろん、js では高階関数も使用されており、実際には入れ子関数として理解できます
関数 test1(){
var name = "one";
戻り関数 (){
console.log(名前);
}
}
test1()();
test1()の後、外側の関数が呼び出され、内側の関数が返され、Continue()すると、それに応じて内側の関数が呼び出されて実行されるため、「one」
が出力されます。ネストされた関数にはクロージャが含まれます。これについては後で説明します。ここで、内側の関数は外側の関数で宣言された変数名にアクセスできます。これにはスコープ チェーン メカニズムが関係します。
2. 事前にJSで宣言
js の関数スコープは、関数内で宣言されたすべての変数が関数本体内で常に表示されることを意味します。また、宣言前に変数を使用することもできます。この状況をホイスティング
と呼びます。ヒント: 事前宣言は、JS エンジンのプリコンパイル時に行われます。事前宣言は、コードが実行される前に発生します。
たとえば
var name="one";
関数テスト(){
console.log(name); //未定義
var name="two";
console.log(name); //2
}
テスト();
上記により次のような効果が得られます
var name="one";
関数テスト(){
変数名;
console.log(name); //未定義
name="2";
console.log(name); //2
}
テスト();
var をもう一度削除してみますか?これはグローバル変数になった関数内の名前なので、未定義ではなくなりました
var name="one";
関数テスト(){
console.log(名前); // 1 つ
name="2";
console.log(name); //2
}
テスト();
3. テストにパラメータがある場合は、上記のパラメータが渡されないことに注意してください。
関数テスト(名前){
console.log(名前); // 1 つ
name="2";
console.log(name); //2
}
var name = "one";
テスト(名前);
console.log(name); // 1 つ
前に述べたように、基本型は値によって渡されるため、テストに渡される名前は実際には単なるコピーであり、関数が返された後にこのコピーはクリアされます。
関数内の name="two" がグローバル名を変更するとは考えないでください。これらは 2 つの独立した名前であるためです
(2) スコープチェーン
上記の高度な機能にはスコープ チェーンが含まれます
関数 test1(){
var name = "one";
戻り関数 (){
console.log(名前);
}
}
test1()();
1. 説明するために大きな段落を導入します:
JavaScript コードの各部分 (グローバル コードまたは関数) には、スコープ チェーンが関連付けられています。
このスコープ チェーンは、オブジェクトのリストまたはリンクされたリストであり、このオブジェクトのグループは、このコードの「スコープ内」の変数を定義します。
js が変数 x の値を見つける必要がある場合 (このプロセスは変数解決と呼ばれます)、このオブジェクトに x という名前の属性がある場合、この属性の値は次のようになります。最初のオブジェクトに x という名前の属性がない場合、js はチェーン内の次のオブジェクトの検索を続けます。 2 番目のオブジェクトに x という名前の属性がまだない場合は、引き続き次のオブジェクトの検索が続きます。スコープ チェーン内のオブジェクトに属性 x が含まれていない場合、x はこのコードのスコープ チェーンに存在しないとみなされ、最終的に ReferenceError 例外がスローされます。
2. スコープチェーンの例:
js のトップレベル コード (つまり、関数定義が含まれていないコード) では、スコープ チェーンはグローバル オブジェクトで構成されます。
ネストを含まない関数本体には、スコープ チェーン上に 2 つのオブジェクトがあります。1 つ目は関数パラメータとローカル変数を定義するオブジェクトで、2 つ目はグローバル オブジェクトです。
ネストされた関数本体では、スコープ内に少なくとも 3 つのオブジェクトがあります。
3. スコープチェーン作成ルール:
関数が定義されると (定義されたときに関数が開始されることに注意してください)、実際にはスコープ チェーンが保存されます。
この関数が呼び出されると、そのパラメーターまたはローカル変数を格納するための新しいオブジェクトが作成され、そのオブジェクトがそのスコープ チェーンに追加され、関数呼び出しスコープの新しいより長い表現「チェーン」が作成されます。
入れ子関数の場合は、状況が再び変わります。外部関数が呼び出されるたびに、内部関数が再定義されます。外部関数が呼び出されるたびにスコープ チェーンが異なるためです。内部関数は定義されるたびに微妙に異なる必要があります。内部関数のコードは外部関数が呼び出されるたびに同じであり、このコードに関連付けられたスコープ チェーンも異なります。
(ヒント: 上記の 3 つのポイントをよく理解して、覚えておいてください。自分の言葉で言うのが最善です。そうでないと、面接官が直接「スコープ チェーンについて説明してください。」と質問するため、覚えておく必要があります。 )
スコープチェーンの実際的な例:
var name="one";
関数テスト(){
var name="two";
関数 test1(){
var name="three";
console.log(名前); //3
}
関数 test2(){
console.log(name); // 2 つの
}
test1();
test2();
}
テスト();
上記はネストされた関数です。これに応じて、スコープ チェーンには 3 つのオブジェクトが存在する必要があります
次に、呼び出し時に name の値を見つける必要があります。スコープ チェーンで
test1() が正常に呼び出された場合、順序は test1()->test()-> グローバル オブジェクト ウィンドウです。 name の値 3 が test1() で見つかったので、検索が完了し、
test1() が正常に呼び出された場合、順序は test2()->test()->global object window になります。test2() では name の値が見つからないため、test() で探します。 ) を検索し、name の値が 2 の場合、検索は完了し、が返されます。
別の例としては、面接中に時々間違いを犯したり、騙されたりすることがよくあります。
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">
为什么?
根据作用域链中变量的寻找规则:
b.addEventListener("click",function(){
alert("Button" i);
},false);
这里有一个函数,它是匿名函数,既然是函数,那就在作用域链上具有一个对象,这个函数里边使用到了变量i,它自然会在作用域上寻找它。
查找顺序是 这个匿名函数 -->外部的函数buttonInit() -->全局对象window
匿名函数中找不到i,自然跑到了buttonInit(), ok,在for中找到了,
这时注册事件已经结束了,不要以为它会一个一个把i放下来,因为函数作用域之内的变量对作用域内是一直可见的,就是说会保持到最后的状态
当匿名函数要使用i的时候,注册事件完了,i已经变成了4,所以都是Button4
那怎么解决呢?
给它传值进去吧,每次循环时,再使用一个匿名函数,把for里边的i传进去,匿名函数的规则如代码
http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
http://www.w3.org/1999/xhtml">
这样就可以 Button1..2..3了
4.上述就是作用域链的基本描述,另外,with语句可用于临时拓展作用域链(不推荐使用with)
语法形如:
with(object)
statement
这个with语句,将object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态
简单用法:
比如给表单中各个项的值value赋值
一般可以我们直接这样
var f = document.forms[0];
f.name.value = "";
f.age.value = "";
f.email.value = "";
After introducing with (because using with will cause a series of problems, so let’s use the form above)
with(document.forms[0]){
f.name.value = "";
f.age.value = "";
f.email.value = "";
}
In addition, if an object o has an x attribute, o.x = 1;
Then use
with(o){
x = 2;
}
can be converted into o.x = 2;
If o does not define attribute x, its function is just equivalent to x = 2; a global variable.
Because with provides a shortcut to read the attributes of o, but it cannot create attributes that o itself does not have.
The above is the entire content of this article. I hope it will be helpful to everyone learning javascript.

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

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

Vue では、let と var の間で変数を宣言するときのスコープに違いがあります。 スコープ: var にはグローバル スコープがあり、let にはブロック レベルのスコープがあります。ブロックレベルのスコープ: var はブロックレベルのスコープを作成しません。let はブロックレベルのスコープを作成します。再宣言: var は同じスコープ内の変数の再宣言を許可しますが、let は許可しません。

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