スコープ
JS には 2 種類のスコープがあります: グローバル スコープ|ローカル スコープ
Lizi 1
console.log(name); //undefined var name = '波妞'; var like = '宗介' console.log(name); //波妞 function fun(){ console.log(name); //波妞 console.log(eat) //ReferenceError: eat is not defined (function(){ console.log(like) //宗介 var eat = '肉' })() } fun();
[関連コースの推奨事項: JavaScript ビデオ チュートリアル ]
1. 名前はグローバルに定義され、グローバルにアクセスできるため、(2) 印刷は可能です。正しく出力される;
2. 関数 fun では、name 属性が定義されていない場合、その親スコープで見つかるため、(3) も正しく出力できます。
3. 内部環境はスコープ チェーンを通じてすべての外部環境にアクセスできますが、外部環境は内部環境の変数や関数にはアクセスできません。 一方向透過性と同様に、これはスコープ チェーンであるため、(4) は不可能ですが、(5) は可能です。
次に、なぜ最初の出力が「ReferenceError: name is not generated」ではなく「unknown」なのかという疑問が生じます。原理は単純に、JS の 変数プロモーションです。
変数プロモーション: JS がコードを解析すると、すべての宣言がスコープの前に進みます
Chestnut 2
console.log(name); //undefined var name = '波妞'; console.log(name); //波妞 function fun(){ console.log(name) //undefined console.log(like) //undefined var name = '大西瓜'; var like = '宗介' } fun();
は
var name; console.log(name); //undefined name = '波妞'; console.log(name); //波妞 function fun(){ var name; var like; console.log(name) //undefined console.log(like) //undefined name = '大西瓜'; like = '宗介' console.log(name) //大西瓜 console.log(like) //宗介 } fun();
と同等です。 注: は現在のスコープに進みます。
Chestnut 3
printName(); //printName is not a function var printName = function(){ console.log('波妞') } printName(); //波妞
は
var printName; printName(); //printName is not a function printName = function(){ console.log('波妞') } printName(); //波妞
と同等です。こうすると分かりやすくなります。関数式は次のとおりです。宣言すると単なる変数です
栗 4
{ var name = '波妞'; } console.log(name) //波妞 (function(){ var name = '波妞'; })() console.log(name) //ReferenceError: name is not defined { let name = '波妞'; } console.log(name) //ReferenceError: name is not defined
上記の栗からも分かるように、JS で var で宣言した変数は、速攻で宣言することはできません。のスコープは中括弧の開始スコープと終了スコープです。ES5 にはブロック レベルのスコープはありませんが、本質的には関数スコープです。ES6 で let および const 定義が導入されて初めて、ブロック レベルのスコープがありました。範囲。
栗 5
function p1() { console.log(1); } function p2() { console.log(2); } (function () { if (false) { function p1() { console.log(3); } }else{ function p2(){ console.log(4) } } p2(); p1() })(); //4 //TypeError: print is not a function
これは非常に古典的な栗です、事前に宣言されていますが、判定条件が no であるため、関数本体は実行されませんでした。そのため、「TypeError: print は関数ではありません」が表示されます。 while、switch、for
#closure
#関数とその状態への参照、つまり字句環境 (字句環境) にも同じことが当てはまります。 ) 一緒にクロージャを形成します。)つまり、クロージャを使用すると、内部関数から外部関数のスコープにアクセスできるようになります。 JavaScript では、関数は作成されるたびにクロージャを生成します。上記の定義は MDN からのもので、簡単に言うと、クロージャとは、別の関数のスコープ内の変数にアクセスする権利を持つ関数を指します。
,//举个例子
function makeFunc() {
var name = "波妞";
function displayName() {
console.log(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
この例では、myFunc は、makeFunc の実行時に作成される displayName 関数インスタンスへの参照であり、displayName インスタンスは引き続きアクセスできます。スコープ内のその字句変数は名前にアクセスできます。したがって、myFunc が呼び出された場合でも、name にはアクセスでき、その値 'Ponyo' が console.log に渡されます。クロージャを作成する最も一般的な方法は、関数内に別の関数を作成することです
//例二
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
//释放对闭包的引用
add5 = null;
add10 = null;
add5 と add10 は両方ともクロージャです。これらは同じ関数定義を共有しますが、異なる語彙環境を保存します。 add5 のコンテキストでは、x は 5 です。そして、add10 では、x は 10 です。
クロージャのスコープ チェーンには、それ自体のスコープに加えて、それを含む関数のスコープとグローバル スコープが含まれます。Chestnut 2 では、arr 配列内に無名関数があり、無名関数の中に無名関数が存在しますが、一番内側の無名関数でアクセスした num は、上位の無名関数でメモリに保存されるので、毎回 i の値にアクセスします。 この記事は js チュートリアル 列からのものです。ぜひ学習してください。 以上がjsのスコープとクロージャの詳しい説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。//栗子1
function arrFun1(){
var arr = [];
for(var i = 0 ; i < 10 ; i++){
arr[i] = function(){
return i
}
}
return arr
}
console.log(arrFun1()[9]()); //10
console.log(arrFun1()[1]()); //10
//栗子2
function arrFun2(){
var arr = [];
for(var i = 0 ; i < 10 ; i++){
arr[i] = function(num){
return function(){
return num
};
}(i)
}
return arr
}
console.log(arrFun2()[9]()); //9
console.log(arrFun2()[1]()); //1