ホームページ >ウェブフロントエンド >フロントエンドQ&A >es6 でラップされた変数はブロック内としてカウントされますか?
es6 if でラップされた変数計算ブロック内。 es6 には新しいブロックレベルのスコープがあります。「{ }」で囲まれたコードはブロックレベルのスコープです。「{}」、if ステートメント、および関数の for ループ内のコードはすべてブロックレベルのスコープに属します。レベルのスコープであり、ブロック内で計算されます。 ES6 では、ブロック レベルのスコープを任意にネストすることができます。外側のスコープは内側のスコープの変数を読み取ることはできませんが、内側のスコープは外側のスコープと同じ名前の変数を定義できます。
このチュートリアルの動作環境: Windows 7 システム、ECMAScript バージョン 6、Dell G3 コンピューター。
ブロックレベル スコープは ES6
で追加されました。ブロックのスコープは { }
でラップされており、if
ステートメントと for
ステートメントの { }
もブロックに属します。範囲。
関数内の {}、if ステートメント、および for ループもブロックレベルのスコープに属し、let と const で定義された変数はスコープ内でのみ有効です。
最初のシナリオ: 内部変数が外部変数を上書きする
var time = new Date() function fx () { console.log(time) // undefined if (false) { var time = 'hello' } } fx()
{ var a = 1 console.log(a) // 1 } console.log(a) // 1 // 通过var定义的变量可以跨块作用域访问到。
2 番目のシナリオ: カウントに使用されるループ変数は、グローバル変数
for
にリークされます。ループ内で var
で定義された変数は、外部スコープ
for (var i = 0; i < 3; i++) { } for (let j = 0; j < 3; j++) { } // 3 console.log(i); // Uncaught ReferenceError: j is not defined console.log(j);
if
ステートメントの var
で定義された変数は、外部スコープ
if(true)## でアクセスできます。 # と
if (false)の違い
代入文が実行されるので
a 出力
3
の代入ステートメントは実行されませんが、宣言された変数
var b はプロモートされます。スコープの最上位レベルであるため、
unknown
if (true) { var a = 3 } if (false) { var b = 3 } // 3 console.log(a); // undefined console.log(b); if (true) { let c = 3 } // Uncaught ReferenceError: c is not defined console.log(c);
function fxFn () { // 这是一个块级作用域 let fx = 'fx is a great girl' if (true) { // 这是一个块级作用域 let fx = 'fx is 18 years old' } console.log(fx) // fx is a great girl } fxFn() // 块级作用域之间相互不影响ES6 では、ブロックレベルのスコープを任意にネストできます。
{{{{ { let fnn = 'Hello' } console.log(fnn); // 报错 }}}};
上記のコードは 5 レベルのブロックレベルのスコープを使用しており、各レベルは個別のスコープです。第 4 レベルのスコープは、第 5 レベルのスコープの内部変数を読み取ることができません。
内部スコープでは、外部スコープと同じ名前の変数を定義できます。{{{{ let fnn = 'Hello'; { let fnn = 'Hello' } }}}};
) は実際には不要になります。 <pre class="brush:php;toolbar:false">// IIFE 写法
(function () {
var tmp = '...';
// ...
}());
// 块级作用域写法
{
let tmp = '...';
// ...
}</pre>
では、関数はトップレベルでのみ使用できると規定されていますスコープと関数 スコープ内で宣言されていますが、ブロックレベルのスコープ内では宣言できません。 <pre class="brush:php;toolbar:false">// 情况一
if (true) {
function f() {}
}
// 情况二
try {
function f() {}
} catch(e) {
// ...
}</pre>
上記の 2 つの関数宣言は、
によれば不正です。 ただし、ブラウザはこの要件に準拠していません。古いコードとの互換性を保つために、ブラウザはブロック レベルのスコープでの関数の宣言を引き続きサポートしています。したがって、上記の 2 つの状況は実際にはエラーを報告せずに実行できます。
ではブロックレベルのスコープが導入され、関数をブロックレベルのスコープで宣言できるようになりました。 ES6
は、ブロック レベルのスコープ内では関数宣言ステートメントが let
のように動作し、ブロック レベルのスコープ外では参照できないことを規定しています。 <pre class="brush:php;toolbar:false">function f() { console.log('I am outside!'); }
(function () {
if (false) {
// 重复声明一次函数f
function f() { console.log('I am inside!'); }
}
f();
}());</pre>
上記のコードを
で実行すると、関数 ## が if## 内で宣言されているため、「
I am inside!」というメッセージが表示されます。 # #f
が関数の先頭に昇格し、実際に実行されるコードは次のようになります。 <pre class="brush:php;toolbar:false">// ES5 环境
function f() { console.log('I am outside!'); }
(function () {
function f() { console.log('I am inside!'); }
if (false) {
}
f();
}());</pre>
ES6
はまったく異なります。理論的には、「
」となります。ブロックレベルのスコープで宣言された関数は let
に似ているため、スコープ外では効果がありません。 ただし、実際に
ES6 ブラウザで上記のコードを実行すると、エラーが報告されます。これはなぜでしょうか?
// 浏览器的 ES6 环境 function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }()); // Uncaught TypeError: f is not a function
ES6
ブラウザでエラーを報告します。 ブロックレベルのスコープで宣言された関数の処理規則が変更されると、明らかに古いコードに大きな影響を与えることがわかりました。結果として生じる非互換性の問題を軽減するために、ES6 では、ブラウザ実装が上記の規制に準拠せず、独自の動作を行うことを規定しています。
に処理させます。 これら 3 つのルールに従って、ブラウザの
ES6
環境では、ブロックレベルのスコープで宣言された関数は、
で宣言された変数と同様に動作します。上記の例で実際に動作するコードは以下の通りです。 <pre class="brush:php;toolbar:false">// 浏览器的 ES6 环境
function f() { console.log('I am outside!'); }
(function () {
var f = undefined;
if (false) {
function f() { console.log('I am inside!'); }
}
f();
}());
// Uncaught TypeError: f is not a function</pre>
環境によって引き起こされる動作があまりにも異なることを考慮すると、ブロックレベルのスコープで関数を宣言することは避けるべきです。本当に必要な場合は、関数宣言文ではなく関数式として記述する必要があります。 <pre class="brush:php;toolbar:false">// 块级作用域内部的函数声明语句,建议不要使用
{
let a = 'secret';
function f() {
return a;
}
}
// 块级作用域内部,优先使用函数表达式
{
let a = 'secret';
let f = function () {
return a;
};
}</pre>
<h2>
<a id="ES6__213"></a><strong>ES6 的块级作用域必须有大括号</strong>
</h2>
<p>如果没有大括号,<code>JavaScript
引擎就认为不存在块级作用域。
// 第一种写法,报错 if (true) let x = 1; // 第二种写法,不报错 if (true) { let x = 1; }
上面代码中,第一种写法没有大括号,所以不存在块级作用域,而let只能出现在当前作用域的顶层,所以报错。第二种写法有大括号,所以块级作用域成立。
函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。
// 不报错 'use strict'; if (true) { function f() {} } // 报错 'use strict'; if (true) function f() {}
【推荐学习:javascript视频教程】
以上がes6 でラップされた変数はブロック内としてカウントされますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。