ECMAScript 6の導入声明let
。
ローカル変数として説明されていると聞きましたが、キーワードとどのように動作が異なるのかまだよくわかりませんvar
。
違いは何ですか?let
の代わりに を使用する必要がある場合はいつですかvar
?
ベストアンサー1
スコープルール
主な違いはスコープのルールです。var
キーワードで宣言された変数は、関数本体に直接スコープが設定され (つまり関数スコープ)、変数はで示されるブロックにlet
直接スコープが設定されます(つまりブロックスコープ)。{ }
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar); // Foo Bar
{
var moo = "Mooo"
let baz = "Bazz";
console.log(moo, baz); // Mooo Bazz
}
console.log(moo); // Mooo
console.log(baz); // ReferenceError
}
run();
let
キーワードが言語に導入された理由は、関数スコープがわかりにくく、JavaScript のバグの主な原因の 1 つであったためです。
この例を見てくださいStack Overflow の別の質問:
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
My value: 3
funcs[j]();
匿名関数が同じ変数にバインドされていたため、呼び出されるたびにコンソールに出力されました。
ループから正しい値を取得するには、すぐに呼び出される関数を作成する必要がありましたが、これも面倒でした。
吊り上げ
var
キーワードで宣言された変数は持ち上げられ初期化されたつまり、宣言される前でも囲むスコープ内でアクセスできますが、その値はundefined
宣言文に到達する前になります。
function checkHoisting() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
let
変数は持ち上げられたが初期化されていない定義が評価されるまでは、初期化前にアクセスすると になりますReferenceError
。変数は時間的デッドゾーンブロックの開始から宣言文が処理されるまで。
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
グローバルオブジェクトプロパティの作成
最上位レベルではlet
、 とは異なりvar
、 はグローバル オブジェクトにプロパティを作成しません。
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped but not part of the global object
console.log(window.foo); // Foo
console.log(window.bar); // undefined
再宣言
厳密モードでは、var
同じスコープ内で同じ変数を再宣言できますが、let
SyntaxError が発生します。
'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared