ES 6新特性のletとconstコマンド
28807 ワード
ES 6新特性のletとconstコマンド
1、letコマンド
ES 6は、変数を宣言するためにletコマンドを追加しました.その使い方はvarに似ていますが、宣言された変数はletコマンドがあるコードブロック内でのみ有効です.変数アップ が存在しません.
letはvarのように「変数アップ」現象が発生しません.したがって、変数は宣言後に必ず使用されます.そうでないとエラーが発生します.
consolone.log(foo)//.undefined consoline.logs(bar)を出力します./エラーReferenceError var foo=2;let bar=2
上記のコードの中で、変数fooはvarコマンドで宣言しています.すなわち、スクリプトが起動すると変数fooは既に存在しますが、値がないので、undefinedを出力します.変数barはletコマンドで宣言します.変数のアップグレードは発生しません.これは声明の前に変数barが存在しないという意味です.これを使うとエラーが発生します.一時性死区 ブロックレベルのスコープ内にletコマンドが存在する限り、その宣言した変数は「バインディング」(binding)という領域になり、外部の影響を受けなくなる.
ES 6は、ブロック内にletとconstコマンドが存在する場合、このブロックがこれらのコマンドに対して宣言する変数は、最初から閉鎖作用領域を形成することを明確に規定している.宣言する前にこれらの変数を使うと、エラーが発生します.つまり、コードブロック内では、letコマンドを使用して変数を宣言する前に、この変数は使用できません.これは文法的には「一時的なデッドゾーン」と呼ばれています.
いくつかの「デッドゾーン」は比較的に隠れています.見つけにくいです.
ES 6は、一時的なデッドエリアとlet、constステートメントに変数のアップグレードがないことを規定しています.主に運行時のエラーを減らすために、変数宣言前にこの変数を使用することを防止して、予想外の行動を招いています.このようなエラーはES 5でよく見られます.このような規定があるので、このような間違いを避けるのは容易です.
つまり、一時的なデッドゾーンの本質は、現在のスコープに入ると、使用する変数が既に存在しますが、取得できないのは、宣言変数の行のコードが現れるまで、その変数を取得して使用することができます.重複した声明は許されない.
letは同じスコープ内で同じ変数を繰り返し宣言することができません. ブロック級作用領域 なぜブロックレベルのスコープが必要ですか?ES 5はグローバルスコープと関数スコープだけで、ブロックレベルのスコープがないため、多くの不合理なシーンをもたらします.
第一のシーンでは、内層変数が外層変数をカバーする場合があります.
第二のシーンでは、計数するための循環変数が大域変数として漏洩されます.
ES 6のブロックレベルのスコープは実際にJavaScriptのためにブロックレベルのスコープを追加しました. do表現 本質的には、ブロックレベルのスコープは、ステートメントであり、複数の動作を一緒にカプセル化し、リターン値がない.
ブロックレベルのスコープを式に変えるという提案があります.つまり、値を返すことができます.ブロックレベルのスコープの前にdoを加えて、do表現にします.
constは読み取り専用の定数を宣言します.一度宣言したら定数の値は変更できません.
const宣言の変数は値を変更してはいけません.これは、constが変数を宣言すると、すぐに初期化しなければならないことを意味しています.今後の割り当てには残してはいけません.
constのスコープはletコマンドと同じです.声明があるブロックレベルのスコープ内でのみ有効です.
const声明の定数は、letと同様に重複して声明してはならない.
本当に対象を凍結したいなら、Object.freeze方法を使うべきです.
オブジェクト自体を凍結するだけでなく、オブジェクトの属性も凍結されます.以下はオブジェクトを完全に凍結する関数です.
1、letコマンド
ES 6は、変数を宣言するためにletコマンドを追加しました.その使い方はvarに似ていますが、宣言された変数はletコマンドがあるコードブロック内でのみ有効です.
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
letはvarのように「変数アップ」現象が発生しません.したがって、変数は宣言後に必ず使用されます.そうでないとエラーが発生します.
consolone.log(foo)//.undefined consoline.logs(bar)を出力します./エラーReferenceError var foo=2;let bar=2
上記のコードの中で、変数fooはvarコマンドで宣言しています.すなわち、スクリプトが起動すると変数fooは既に存在しますが、値がないので、undefinedを出力します.変数barはletコマンドで宣言します.変数のアップグレードは発生しません.これは声明の前に変数barが存在しないという意味です.これを使うとエラーが発生します.
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
上のコードには、グローバル変数tmpがありますが、ブロックレベルのスコープ内のletはまた、局所変数tmpを宣言しています.このブロックレベルのスコープを結合させるため、letが変数を宣言する前に、tmp割当値に対してエラーが発生します.ES 6は、ブロック内にletとconstコマンドが存在する場合、このブロックがこれらのコマンドに対して宣言する変数は、最初から閉鎖作用領域を形成することを明確に規定している.宣言する前にこれらの変数を使うと、エラーが発生します.つまり、コードブロック内では、letコマンドを使用して変数を宣言する前に、この変数は使用できません.これは文法的には「一時的なデッドゾーン」と呼ばれています.
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の「デッドゾーン」に属します.いくつかの「デッドゾーン」は比較的に隠れています.見つけにくいです.
function bar(x = y, y = 2) {
return [x, y];
}
bar(); //
上のコードの中で、bar関数を呼び出してエラーが発生したのは、パラメータxのデフォルト値が別のパラメータyに等しいためであり、yはまだ宣言されていません.デッドゾーンに属しています.yのデフォルト値がxであれば、エラーは発生しません.この時点でxはすでに宣言されています.ES 6は、一時的なデッドエリアとlet、constステートメントに変数のアップグレードがないことを規定しています.主に運行時のエラーを減らすために、変数宣言前にこの変数を使用することを防止して、予想外の行動を招いています.このようなエラーはES 5でよく見られます.このような規定があるので、このような間違いを避けるのは容易です.
つまり、一時的なデッドゾーンの本質は、現在のスコープに入ると、使用する変数が既に存在しますが、取得できないのは、宣言変数の行のコードが現れるまで、その変数を取得して使用することができます.
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; //
}
}
第一のシーンでは、内層変数が外層変数をカバーする場合があります.
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はループ制御のみに使用されますが、ループ終了後は消えず、グローバル変数に漏れました.ES 6のブロックレベルのスコープは実際にJavaScriptのためにブロックレベルのスコープを追加しました.
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
内層作用領域は外層作用領域の同名変数を定義することができる.{
{
{
{
let insane = 'Hello World';
{
let insane = 'Hello World'}
}}}};
ブロックレベルのスコープの出現は、実際には、幅広いアプリケーションを得るための即実行関数式(IIIIFE)を必要としなくする.// IIFE
(function () {
var tmp = ...;
...
}());
//
{
let tmp = ...;
...
}
ブロックレベルのスコープと関数宣言関数は、ブロックレベルのスコープ内で宣言できますか?かなり混淆された問題です.ES 5は、関数はトップレベルのスコープと関数のスコープの中でしか宣言できないと規定しています.ブロックレベルのスコープ宣言はできません.//
if (true) {
function f() {
}
}
//
try {
function f() {
}
} catch(e) {
}
上のコードの2つの関数宣言は、ES 5の規定により違法です.しかし、ブラウザはこの規定を遵守していません.従来のコードに対応するために、ブロックレベルのスコープ内の宣言関数をサポートしています.したがって、上の2つの場合は実際に実行できます.エラーは発生しません.ただし、厳密モードではエラーが発生します.// ES5
'use strict';
if (true) {
function f() {
}
}
//
// ES6 , 。
// ES6
'use strict';
if (true) {
function f() {
}
}
//
//ES6 , , let, 。
環境による挙動の違いを考慮して、ブロックレベルのスコープ内で関数を宣言することを避けるべきです.必要であれば、関数ステートメントの代わりに関数式を作成するべきです.//
{
let a = 'secret';
function f() {
return a;
}
}
//
{
let a = 'secret';
let f = function () {
return a;
};
}
また、もう一つの注意点があります.ES 6のブロックレベルのスコープは、ステートメント関数のルールを許可しています.大きな括弧だけを使用して成立します.大きな括弧を使用していないと、エラーが発生します.//
'use strict';
if (true) {
function f() {
}
}
//
'use strict';
if (true)
function f() {
}
{
let t = f();
t = t * t + 1;
}
上のコードでは、ブロックレベルのスコープは2つのステートメントをカプセル化しています.しかし、ブロックレベルのスコープ以外では、tの値は得られません.なぜなら、ブロックレベルのスコープは戻りません.tがグローバル変数でない限り、値を返しません.ブロックレベルのスコープを式に変えるという提案があります.つまり、値を返すことができます.ブロックレベルのスコープの前にdoを加えて、do表現にします.
let x = do {
let t = f();
t * t + 1;
};
// , x 。
2、constコマンドconstは読み取り専用の定数を宣言します.一度宣言したら定数の値は変更できません.
const PI = 3.1415;
PI // 3.1415
PI = 3;
// TypeError: Assignment to constant variable.
上のコードは定数を変更する値がエラーとなることを示しています.const宣言の変数は値を変更してはいけません.これは、constが変数を宣言すると、すぐに初期化しなければならないことを意味しています.今後の割り当てには残してはいけません.
const foo;
// SyntaxError: Missing initializer in const declaration
上のコードによると、constにとっては、割り当てがないと宣言するだけで、エラーが発生します.constのスコープはletコマンドと同じです.声明があるブロックレベルのスコープ内でのみ有効です.
if (true) {
const MAX = 5;
}
MAX // Uncaught ReferenceError: MAX is not defined
const命令声明の定数も上げられず、同様に一時的なデッドゾーンがあり、声明の位置の後にのみ使用されます.if (true) {
console.log(MAX); // ReferenceError
const MAX = 5;
}
上のコードは定数MAX宣言の前に呼び出します.結果はエラーです.const声明の定数は、letと同様に重複して声明してはならない.
var message = "Hello!";
let age = 25;
//
const message = "Goodbye!";
const age = 30;
複合型の変数に対しては、変数名はデータを指すのではなく、データの所在地を指すものです.constコマンドは変数名が指すアドレスが変わらないだけで、そのアドレスのデータが変わらないことを保証するものではないので、オブジェクトを定数として宣言するには十分注意が必要です.const foo = {
};
foo.prop = 123;
foo.prop
// 123
foo = {
}; // TypeError: "foo" is read-only
上記のコードの中で、常量fooは一つのアドレスを記憶しています.この住所は一つのオブジェクトを指しています.可変ではないのはこの住所だけです.fooを他の住所に向けることはできませんが、オブジェクト自体は可変ですので、まだ新しい属性を追加することができます.const a = [];
a.push('Hello'); //
a.length = 0; //
a = ['Dave']; //
上のコードでは、定数aは配列であり、この配列自体は書き込み可能ですが、他の配列をaに割り当てるとエラーが発生します.本当に対象を凍結したいなら、Object.freeze方法を使うべきです.
const foo = Object.freeze({
});
// , ;
// ,
foo.prop = 123;
上のコードでは、定数fooは凍結されたオブジェクトを指していますので、新しい属性を追加するのは機能しません.厳しいモードではエラーが発生します.オブジェクト自体を凍結するだけでなく、オブジェクトの属性も凍結されます.以下はオブジェクトを完全に凍結する関数です.
var constantize = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach( (key, value) => {
if ( typeof obj[key] === 'object' ) {
constantize( obj[key] );
}
});
};
ES 5は2つの変数を宣言する方法しかありません.varコマンドとfunctionコマンドです.ES 6はletとconstコマンドを追加する以外に、後の章でも言及されています.他の2つの変数を宣言する方法:importコマンドとclassコマンドです.したがって、ES 6は6つの変数を宣言する方法があります.