ホームページ >ウェブフロントエンド >フロントエンドQ&A >es6 でラップされた変数はブロック内としてカウントされますか?

es6 でラップされた変数はブロック内としてカウントされますか?

青灯夜游
青灯夜游オリジナル
2022-11-21 16:21:581431ブラウズ

es6 if でラップされた変数計算ブロック内。 es6 には新しいブロックレベルのスコープがあります。「{ }」で囲まれたコードはブロックレベルのスコープです。「{}」、if ステートメント、および関数の for ループ内のコードはすべてブロックレベルのスコープに属します。レベルのスコープであり、ブロック内で計算されます。 ES6 では、ブロック レベルのスコープを任意にネストすることができます。外側のスコープは内側のスコープの変数を読み取ることはできませんが、内側のスコープは外側のスコープと同じ名前の変数を定義できます。

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) の違い

  • if(true) 代入文が実行されるので a 出力 3
  • if(false) の代入ステートメントは実行されませんが、宣言された変数 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);

## ブロックレベルのスコープが出力されます (ES6 では、ブロックを実装するための let 変数と const 変数が提供されています) -levelscopescope)
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'
      }
    }}}};
  • ブロックレベルのスコープの出現により、広く使用されている匿名即時実行関数式 (匿名
IIFE

) は実際には不要になります。 <pre class="brush:php;toolbar:false">// IIFE 写法 (function () {   var tmp = '...';   // ... }());   // 块级作用域写法 {   let tmp = '...';   // ... }</pre>

ブロックレベルのスコープと関数の宣言

ES5

では、関数はトップレベルでのみ使用できると規定されていますスコープと関数 スコープ内で宣言されていますが、ブロックレベルのスコープ内では宣言できません。 <pre class="brush:php;toolbar:false">// 情况一 if (true) {   function f() {} }   // 情况二 try {   function f() {} } catch(e) {   // ... }</pre>上記の 2 つの関数宣言は、

ES5

によれば不正です。 ただし、ブラウザはこの要件に準拠していません。古いコードとの互換性を保つために、ブラウザはブロック レベルのスコープでの関数の宣言を引き続きサポートしています。したがって、上記の 2 つの状況は実際にはエラーを報告せずに実行できます。

ES6

ではブロックレベルのスコープが導入され、関数をブロックレベルのスコープで宣言できるようになりました。 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>上記のコードを

ES5

で実行すると、関数 ## が 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 では、ブラウザ実装が上記の規制に準拠せず、独自の動作を行うことを規定しています。

関数をブロック レベルのスコープで宣言できるようにします。

関数宣言は
    var
  • と似ています。つまり、グローバル スコープまたは関数スコープの先頭に昇格されます。
  • 同時に、関数宣言も、それが配置されているブロックレベルのスコープの先頭にプロモートされます。
  • 上記の 3 つのルールは、
  • ES6
  • のブラウザ実装にのみ有効であることに注意してください。他の環境での実装は準拠する必要はありません。ブロックレベルの関数宣言は引き続き次のようにみなされる必要があります。

に処理させます。 これら 3 つのルールに従って、ブラウザの ES6 環境では、ブロックレベルのスコープで宣言された関数は、

var

で宣言された変数と同様に動作します。上記の例で実際に動作するコードは以下の通りです。 <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 サイトの他の関連記事を参照してください。

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