[ES6の新機能・(1)]新しいコマンドで変数を宣言させてconstします。愚かな変数にならないでください!

はじめに:ES5のvar宣言変数の欠点

ES5は、実際には、変数を宣言する2つの方法を提供します。varコマンドとfunctionコマンドです。functionコマンドを使用して関数を宣言する方法についてはここでは説明しませんvar主にコマンドを比較します。

以前、JSの概要varコマンド宣言変数には3つの主要な特性があることを詳しく説明しました

  • 変数は繰り返し宣言できます。
  • 変数宣言が促進されます。
  • ブロックレベルのスコープはありません。

これらの3つの特性により、JSコードの記述は少し「ランダム」に見え、十分に標準化されていません。また、そのような文法ロジックも直感に反します。2つの例を挙げてください。

  1. 内側の変数は同じ名前の外側の変数
    カバーします。以下ではvar、グローバル変数宣言しnumて値1割り当て、次にshow関数スコープのifコードブロックでnum変数再宣言し、値2を割り当てます。
var num = 1;

function show() {
    
    
  console.log(num);
  if (false) {
    
    
    var num = 2;
  }
}

show();


——————OUTPUT——————
undefined

最終的なshow関数実行の出力結果はundefinedです。
これは、var宣言された変数にブロックレベルのスコープがなく、2番目の再宣言numが関数の先頭に昇格し、同じ名前の外部グローバル変数をカバーするためです。この場合、出力結果はである必要がありますundefined(3つの特性すべてが1つの例に反映されています)

  1. さまざまなループ構造でカウントに使用されるループ変数は、グローバル変数としてリークされます。
    ループ構造を使用する場合、ループ制御変数(i、j、kなど)を宣言しますが、ループが終了した後は消えません。 、グローバル変数にリークしました。
for (var i = 0; i < 3; i++) {
    
    
  //...
}
console.log(i);


——————OUTPUT——————
2

より良いアプローチは、それがループ制御内でのみ有効であり、ループの終了後に自動的に失敗し、コードの他の部分の実行に影響を与えないことを期待することです。現時点では、ES6で新しいletコマンドを使用する必要があります。

1.基本を構築してみましょう

1.1letの基本的な使用法

letコマンドは、ES6標準で変数を宣言するために使用される新しいコマンドです。その使命はvarコマンドを置き換えることです。その使用法は似てvarいますがvar、設計上の欠陥を補います。

2つの最も基本的な違いは、letコマンドが現在のコードブロックをブロックレベルのスコープとして宣言でき(以降の章で詳しく説明します)、letコマンドによって宣言された変数は現在のコードブロックでのみ有効であるということです。
(コードブロックは中括弧のペアになっています{}

{
    
    
  let a = 1;
  var b = 2;
}

a // ReferenceError: a is not defined.
b // 2

コードブロック外の変数にアクセスするaと、未定義のエラーが報告varされbますが、定義済みの変数を使用しても引き続きアクセスできます。

これで、このletコマンドを使用して、この記事の冒頭にある2番目の問題であるループ変数リークの問題を解決できます。forループカウンターのステートメントi使用しますlet

for (let i = 0; i < 3; i++) {
    
    
  //...
}
console.log(i);


——————OUTPUT——————
// ReferenceError: i is not defined

現時点でi、変数にアクセスできません。


❀少し拡大(1)❀

ループでletコマンドを使用するときに注意すべきもう1つのポイントがあります。変数i、ループ内で毎回再宣言されます

まず、var宣言されたループ変数の使用法を確認し、i各ループにタイマー関数を追加して、このループ変数を出力しますi

for(var i = 0; i < 3; i++) {
    
    
    setTimeout(function() {
    
    
        console.log(i);
    }, 1000);
}


——————OUTPUT——————
3
3
3

forループ全体のループ変数はi常に同じ変数であり、最後にループ終了変数iに値2が割り当てられるため、3つの3が出力されます。次に、letコマンドに変更して、もう一度出力します。

for(let i = 0; i < 3; i++) {
    
    
    setTimeout(function() {
    
    
        console.log(i);
    }, 1000);
}


——————OUTPUT——————
0
1
2

出力結果は、timer関数を使用しない場合と同じであることがわかります。これは、変数iループ内で毎回再宣言されるためです。通常のロジックに従って出力される理由は、JavaScriptエンジンが前のループラウンドの値を記憶するためです。 、このラウンドの変数を初期化するとき、i計算は前のラウンドに基づいて実行されます。


❀少し拡大(2)❀

forループ自体には、別の特別な機能があります。ループ変数を設定する部分は親スコープであり、ループ本体の内部は別の子スコープです。

for (let i = 0; i < 3; i++) {
    
    
  let i = 'zevin';
  console.log(i);
}


——————OUTPUT——————
zevin
zevin
zevin

3回出力されましたzevinこれは、ループ本体内の変数iとループ変数iが同じスコープ内になく、独自の個別のスコープを持っていることを示しています


1.2constの基本的な使用法

constこのコマンドは、読み取り専用定数を宣言するために使用されます。宣言の最初に割り当てる必要があり、宣言後に変更することはできません。

const PI;
// SyntaxError: Missing initializer in const declaration

const PI = 3.1415926;
PI = 3.14;
// TypeError: Assignment to constant variable.

❀展開❀

constコマンドの本質

constコマンドが実際に保証するのは、変数の値を変更できないということではなく、変数が指すメモリアドレスに格納されているデータを変更できないということです。

基本的なタイプの単純なデータ(数値、文字列、ブール値)の場合、変数が指すメモリアドレスには値自体が格納されるため、変更できない変数の値と同等です。

const obj = {
    
    };

// 可以添加属性
obj.name = 'zevin';
console.log(obj.name);
// zevin

// 让obj指向另一个对象就会报错
foo = {
    
    }; 
// TypeError: "obj" is read-only

参照データタイプ(主に配列、オブジェクト)の場合、変数が指すメモリアドレスは参照アドレスを保存しますが、参照アドレスは変更できません。配列、オブジェクト自体については、引き続き追加または削除できます。素子。


2.ES6変数宣言の新しい仕様

声明ES5するvarコマンドではなく、規範的なJS言語を向上させるために、状況を改善するために、ES6は、次の4つの新しい変数宣言規範を提案し、letそしてconstコマンドが適用されます。

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

ES5にはグローバルスコープと関数スコープしかありません。最後に、ブロックレベルのスコープがES6に追加されました。使用letまたはconstブロックレベルのアクションコマンドの変数は、ドメインが有効である唯一の文で宣言されました。

{
    
    
    let a = 1;
    if(true){
    
    
        const a = 2;
    };
    console.log(a);
}


——————OUTPUT——————
1

コードブロックは{}、相互に影響を与えることなく任意にネストできる1対の中括弧基づいています

{
    
    {
    
    {
    
    {
    
    
  {
    
     const name = 'zevin' }
  console.log(name); 
  // 报错
}}}};

上記のコードは、5レベルのブロックレベルのスコープを使用しています。各スコープは個別のスコープです。第4レベルのスコープは、第5レベルのスコープの内部変数を読み取ることができません。

2.2可変プロモーションはありません

varコマンドによって宣言された変数は、ドキュメントの先頭または関数の先頭にプロモートされます。つまり、変数は宣言の前に使用でき、値はundefinedです。そして、行動ES6で固定文法、letおよびconst変数コマンドがそれ以外の場合はエラー、使用後の文で宣言しなければなりません。

console.log(a);
console.log(b);
console.log(c);

var a = 1;
let b = 2;
const c = 3;


——————OUTPUT——————
undefined
ReferenceError: Cannot access 'b' before initialization
ReferenceError: Cannot access 'c' before initialization

2.3一時的なデッドゾーン

ES6は、ブロックが存在しletconstコマンドを実行する場合、これらのコマンドの変数宣言を最初からブロックして、閉じたスコープを形成することを明確にします。これらの変数が宣言の前に使用されている場合、エラーが報告されます。これは文法的に「一時的なデッドゾーン」(略してTDZ)と呼ばれます。

if (true) {
    
    
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

上記のコードでは、letコマンドが変数を宣言する前にtmp、すべてが変数tmpの「デッドゾーン」に属してます


❀展開❀

「一時的なデッドゾーン」の出現は、typeofエラーを報告することのない操作ではなくなったことも意味します。

typeof a; // undefined
typeof b; // ReferenceError
const b = 1;

変数を宣言bするconst前の変数の使用bは、その変数のエラーを使用する限り、「デッドゾーン」に属します。したがって、typeofオペレーターはReferenceErrorエラーをスローします。

ただし、変数がまったく宣言されていない場合(variable atypeof使用してもエラーは報告されませんundefined


2.4重複した宣言は許可されていません

ES6では、同じスコープ内で同じ変数を複数宣言することはできません。

if(true){
    
    
    var a = 1;
    let a = 2;
    const a = 3;
}
// SyntaxError: Identifier 'a' has already been declared

したがって、同様に、仮パラメータと同じ名前の変数を関数使用letまたはconstコマンドすることはできませんが、使用するvarことはできます。

function func(num) {
    
    
  let num = 1;
  console.log(num);
}
func() 
// SyntaxError: Identifier 'num' has already been declared
function func(num) {
    
    
  var num = 1;
  console.log(num);
}
func() 
// 1

異なるブロックレベルのスコープは相互に影響を与えないため、異なるブロックレベルのスコープで同じ名前の変数を定義できます。したがって、次のコードはエラーを報告しません。

function func(num) {
    
    
    var num = 1;
    if(true){
    
    
        let num = 2;
    }else{
    
    
        const num =3;
    }
  }
  func()

3.拡張機能:ES6で変数を宣言する6つの方法

ES5 ES6
var
関数
聞かせて
constの
インポート
クラス

ES6は、実際には、4つの新しい変数宣言メソッドです。このペーパーでは、letコマンドとconstコマンドを紹介し、続いてコマンドとコマンドを再度紹介しimportますclassES5のvarコマンドおよびfunctionコマンドと組み合わせて、ES6で変数を宣言する6つの方法があります。

おすすめ

転載: blog.csdn.net/JZevin/article/details/108369123