ホームページ  >  記事  >  ウェブフロントエンド  >  jsのブロックレベルスコープと関数スコープの違いは何ですか? (コード解析)

jsのブロックレベルスコープと関数スコープの違いは何ですか? (コード解析)

不言
不言オリジナル
2018-08-15 17:53:153871ブラウズ

この記事でわかることは、JS におけるブロックレベルのスコープと関数スコープの違いについてです。 (コード分析) は一定の参考値がありますので、困っている方は参考にしていただければ幸いです。

なぜブロックスコープが必要なのですか?

ES5 にはグローバル スコープのみがあり、関数スコープはなく、ブロックレベルのスコープもないため、多くの不合理なシナリオが発生します。

最初のシナリオでは、内部変数が外部変数を上書きする可能性があります:

var tmp = new Date();

function f(){
  console.log(tmp);
  if(false){
    var tmp = "hello";
  }
}

f(); // undefined

上記のコードでは、関数 f が実行された後、出力結果は unknown になります。変数 Promotion により、内側の tmp 変数が外側の tmp 変数を上書きするためです。 f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

第二种场景,用来技术的循环变量泄露为全局变量:

var s = "hello";
for(var i=0;i<s.length;i++){
  console.log(s[i]);
}

console.log(i); // 5

上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

ES6的块级作用域

let实际上为JavaScript新增了块级作用域

function f1(){
  let n = 5;
  if(true){
    let n = 10;
  }
  console.log(n); // 5
}

上面的函数有2个代码块,都声明了变量n,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var定义变量n

2 番目のシナリオ、テクノロジーに使用されるループ変数がグローバル変数として漏洩します:

{
    {let insane = "hello"}
    console.log(insance); // 报错
}

上記のコードでは、変数 i はループを制御するためにのみ使用されますが、消えるわけではありませんループ終了後にグローバル変数にリークされます。

ES6 のブロックレベルのスコープ

let は実際に JavaScript に新しいブロックレベルのスコープを追加します

{
    let a = "hello";
    {let a = "hello"}
}

上記の関数には 2 つのコード ブロックがあり、どちらも変数 n、実行すると5が出力されます。これは、外側のコード ブロックが内側のコード ブロックの影響を受けないことを意味します。 <code>var を使用して変数 n を定義すると、最終的な出力値は 10 になります。

外側のスコープは内側のスコープの変数を読み取ることができません:

// IIFE写法
(function(){
  var tmp = ...;
  ...
}());

// 块级作用域写法
{
  let tmp = ...;
  ...
}

内側のスコープは外側のスコープで同じ名前の変数を定義できます:

function f(){
    ...
    swap(var_a,var_b);
    (function swap(a,b){
        var tmp;
        tmp = a;
        a = b;
        b=tmp;
    })(var_a,var_b);
}

ブロックレベルのスコープの出現により、実際に広く使用されるようになりました 即時実行関数式 (IIFE) は不要になりました:

function f(){
    let a,b;
    ...
    {
        let tmp;
        tmp = a;
        a = b;
        b=tmp;
    }
}
ES6 より前では、変数のスコープは関数のスコープでした。ブロックレベルのスコープがなかったため、関数内でローカルに一時変数が必要になることがありました。 IIEF では、コードはカプセル化されており、冗長な一時変数を導入することなく目的の効果が得られます。ブロックスコープの導入後は、当然 IIEF は不要になります。 rrreee
上記のコードのように、tmp は IIFE でカプセル化されているため、上位レベルの関数を汚染することはありません。また、ブロックレベルのスコープでは、それを IIEF にカプセル化する必要はなく、ブロックに直接入れるだけです。レベル。

rrreee

簡単に言うと、匿名関数をすぐに実行する目的は、ブロックレベルのスコープを確立することです。実際のブロックレベルのスコープがあるので、匿名関数をすぐに実行する必要はありません。 関連する推奨事項:

🎜🎜 js でのスコープと関数クロージャーの例の説明🎜🎜🎜🎜🎜PHP{} ブロックレベルのスコープの詳細な説明🎜🎜

以上がjsのブロックレベルスコープと関数スコープの違いは何ですか? (コード解析)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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