es6 では、let キーワードを使用して変数を宣言しますが、宣言された変数は let コマンドが配置されているコード ブロック内でのみ有効です。 Let は「変数の昇格」を引き起こさないため、変数は宣言後に使用する必要があります。そうしないと、エラーが報告されます。 let コマンドがブロックレベルのスコープに存在する限り、それによって宣言された変数はこの領域に「バインド」され、外部の影響を受けなくなります。
このチュートリアルの動作環境: Windows 7 システム、ECMAScript バージョン 6、Dell G3 コンピューター。
ES6 は、変数を宣言するための新しい let
コマンドを追加します。使用方法は var
と似ていますが、宣言された変数は let
コマンドが配置されているコード ブロック内でのみ有効です。
{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1
上記のコードはコード ブロック内にあり、それぞれ let
と var
を持つ 2 つの変数を宣言します。次に、これら 2 つの変数がコード ブロックの外で呼び出され、その結果、let
で宣言された変数はエラーを報告し、var
で宣言された変数は正しい値を返します。これは、let
によって宣言された変数が、それが配置されているコード ブロック内でのみ有効であることを示しています。
for
ループのカウンターは、let
コマンドの使用に非常に適しています。
for (let i = 0; i < 10; i++) {} console.log(i); //ReferenceError: i is not defined
上記のコードでは、カウンター i
は for
ループの本体内でのみ有効であり、ループの外で参照されるとエラーが報告されます。
次のコードで var
を使用する場合、最終出力は 10 になります。
var a = []; for (var i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 10
上記のコードでは、変数 i
は var
によって宣言されており、グローバル スコープで有効です。したがって、ループするたびに、新しい i
値が古い値を上書きし、最終出力は i
の最後のラウンドの値になります。
let
が使用される場合、宣言された変数はブロックレベルのスコープ内でのみ有効であり、最終出力は 6 になります。
var a = []; for (let i = 0; i < 10; i++) { a[i] = function () { console.log(i); }; } a[6](); // 6
上記のコードでは、変数 i
は let
によって宣言されています。現在の i
はこのサイクルでのみ有効であるため、サイクル i
は実際には新しい変数であるため、最終出力は 6 になります。
let
var
のような「変数昇格」現象はありません。したがって、変数は宣言後に使用する必要があります。そうしないと、エラーが報告されます。
console.log(foo); // 输出undefined console.log(bar); // 报错ReferenceError var foo = 2; let bar = 2;
上記のコードでは、変数 foo
が var
コマンドで宣言されており、変数の昇格が発生します。つまり、スクリプトの実行が開始されると、変数 foo
は存在しますが、値がないため、unknown
が出力されます。変数 bar
は let
コマンドで宣言されており、変数の昇格は行われません。これは、変数 bar
が宣言前には存在しないことを意味し、使用するとエラーがスローされます。
let
コマンドがブロックレベルのスコープ内に存在する限り、それによって宣言された変数は「バインド」されます。この領域は外部からの影響を受けなくなります。
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
上記のコードには、グローバル変数 tmp
がありますが、let
はブロックレベルのスコープでローカル変数 tmp
を宣言しています。結果は次のようになります。 Or binding this block-levelscope. そのため、let
が変数を宣言する前に、値を tmp
に代入するとエラーが報告されます。
ES6 では、ブロック内に let
および const
コマンドがある場合、このブロックは最初からこれらのコマンドによって宣言された変数に対してクローズド効果を持つことを明確に規定しています。 。 エリア。宣言前にこれらの変数を使用すると、エラーが発生します。
つまり、コード ブロック内では、let コマンドを使用して宣言されるまで変数は使用できません。文法的には、これは「一時的なデッド ゾーン」(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 が 100% 安全な操作ではなくなったことも意味します。
typeof x; // ReferenceError let x;
x は
let コマンドを使用して宣言されているため、宣言される前は ## の「デッド ゾーン」に属しています。 #x
. を使用している限り、この変数に到達するとエラーが報告されます。したがって、typeof
は実行時に ReferenceError
をスローします。 比較のために、変数がまったく宣言されていない場合、
を使用してもエラーは報告されません。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">typeof undeclared_variable // "undefined"</pre><div class="contentsignin">ログイン後にコピー</div></div>
上記のコードでは、
は存在しない変数名であり、結果は「未定義」になります。したがって、let
より前は、typeof
演算子は 100% 安全であり、エラーを報告することはありませんでした。これはもはや真実ではありません。この設計は、誰もが良いプログラミング習慣を身につけられるようにすることを目的としています。変数は宣言した後に使用する必要があります。使用しないと、エラーが報告されます。 一部の「デッド ゾーン」は隠されており、見つけるのが簡単ではありません。
function bar(x = y, y = 2) { return [x, y]; } bar(); // 报错
上面代码中,调用bar
函数之所以报错(某些实现可能不报错),是因为参数x
默认值等于另一个参数y
,而此时y
还没有声明,属于”死区“。如果y
的默认值是x
,就不会报错,因为此时x
已经声明了。
function bar(x = 2, y = x) { return [x, y]; } bar(); // [2, 2]
ES6规定暂时性死区和let
、const
语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在ES5是很常见的,现在有了这种规定,避免此类错误就很容易了。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
let不允许在相同作用域内,重复声明同一个变量。
// 报错 function () { let a = 10; var a = 1; } // 报错 function () { let a = 10; let a = 1; }
因此,不能在函数内部重新声明参数。
function func(arg) { let arg; // 报错 } function func(arg) { { let arg; // 不报错 } }
ES5只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。
第一种场景,内层变量可能会覆盖外层变量。
var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = "hello world"; } } f(); // undefined
上面代码中,函数f执行后,输出结果为undefined
,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。
第二种场景,用来计数的循环变量泄露为全局变量。
var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); } console.log(i); // 5
上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。
let
实际上为JavaScript新增了块级作用域。
function f1() { let n = 5; if (true) { let n = 10; } console.log(n); // 5 }
上面的函数有两个代码块,都声明了变量n
,运行后输出5。这表示外层代码块不受内层代码块的影响。如果使用var
定义变量n
,最后输出的值就是10。
ES6允许块级作用域的任意嵌套。
{{{{{let insane = 'Hello World'}}}}};
上面代码使用了一个五层的块级作用域。外层作用域无法读取内层作用域的变量。
{{{{ {let insane = 'Hello World'} console.log(insane); // 报错 }}}};
内层作用域可以定义外层作用域的同名变量。
{{{{ let insane = 'Hello World'; {let insane = 'Hello World'} }}}};
块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了。
// IIFE 写法 (function () { var tmp = ...; ... }()); // 块级作用域写法 { let tmp = ...; ... }
【相关推荐:javascript视频教程、编程视频】
以上がES6でのletの使い方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。