
JSアプリケーションの作成経験がある場合は、おそらくその構文に精通しているでしょう。 それは非常に珍しく、いくつかの癖がありますが、一般的に考え抜かれ、理解可能で、他の言語と多くの類似点があります。
ES6では、いくつかの新しい構文形式を追加します。 この章では、それらの多くを調べて、私たちの武器庫の新機能を見つけます。
注:この本の執筆時点では、ES6のほとんどの新機能は、人気のあるブラウザー(Firefox、Chromeなど)と多くの興味深い環境の両方で既に実装されています。 しかし、残念なことに、すべてのブラウザーまたは環境がES6で動作できるわけではありません。 前の章で述べたように、トランスパイリングがすべてです。 このアプローチを使用すると、このマニュアルの例を実行できます。 これを行うには、自由に
使えるツールがいくつかあります
-ES6Fiddle (
http://www.es6fiddle.net /)は、
Babelの ES6とREPL(
http://babeljs.io/repl/を試すための優れた使いやすいプラットフォームです)
ブロックスコープ
JavaScriptの可視性の基本単位は関数であることはご存知でしょう。 スコープでブロックを実装する必要がある場合、IIFE(すぐに呼び出される関数の式)を使用するのが最も適切な方法です。次に例を示します。
var a = 2; (function IIFE(){ var a = 3; console.log( a );
Letステートメント
ただし、現在では、あらゆる種類のブロックにスコープを実装でき、これはブロックスコープと呼ばれます。 新しいスコープを作成するために必要なのは、長い間誰もが知っている中括弧
{ .. }
ペア
{ .. }
。 内部(またはグローバル)スコープの変数を宣言するために使用した
var
演算子を使用する代わりに、
let
を使用してブロックを宣言できます。
var a = 2; { let a = 3; console.log( a );
もちろん、これはJSにとっては珍しいことですが、他の言語で作業した開発者にとっては、このパターンは長い間知られています。
これは、
{ ... }
を使用してブロックの可視性を作成する最良の方法
{ ... }
。 ブロックの先頭に
let
宣言を配置することをお勧めします。複数の宣言がある場合は、
let
ステートメントを1つだけ使用
let
ください。
様式的には、これらの変数の対象となるブロックを
明示的に強調するために、開始
{
と同じ行でアナウンスすることをお勧めします。
{ let a = 2, b, c;
今ではかなり奇妙に見え、ES6に関する文献のほとんどの推奨事項と一致していませんが、私には狂気の理由があります。 (perevに注意してください:少し低めに学んでください)。
let
ステートメントには別の推奨形式があり、
let
ブロックと呼ばれます。
これは、「
明示的ブロックスコープ 」と呼ぶものの優れた例ですが、
let
var
と同様に、スコープのブロック全体に拡張されるため、
明示的ではあり
ません 。
残念ながら、
let (..) { .. }
form
let (..) { .. }
はES6では受け入れられませんでした。 おそらく、今後のES6の更新でこのフォームが表示されますが、現時点では最初の例が最適です。
let
ステートメントの
暗黙的な性質を強調するために、次の例を見てみましょう。
let a = 2; if (a > 1) { let b = a * 3; console.log( b );
そして、コードを再検討することなく、少しクイズを教えてください:
if
ブロックに存在する変数とforブロックのみに存在する変数はどれですか?
回答:
if
ブロックに
b
ブロックスコープの変数
a
と
b
含まれ、ブロックスコープ
for
変数
i
と
j
ます。
変数
i
if
ブロックのスコープに追加されなかったのは驚くことではありませんか?
この例では、変数
c
宣言が非常に低いことにも危険があります。
従来の
var
ステートメントの種類は、変数をスコープに「
アタッチ 」し、関数が実行される前に入力されたときに、どこで宣言されたかに関係なく変数を初期化します。 この現象は
隆起として知られています。
let
ステートメントは、実行前に変数をスコープにアタッチしますが、関数に入るときに変数を初期化しません。宣言/初期化される前にそのような変数にアクセスしようとすると、エラーになります。
実例:
{ console.log( a );
注:
変数が宣言または初期化される前の以前
の変数呼び出しによって引き起こされるReferenceErrorは、技術的にはTDZ(一時デッドゾーン)エラーと呼ばれます。
「初期化されていない」とは、明示的に値を割り当てる必要があるという意味ではないという事実に注意を喚起したいと思います。
let b;
-結構です。 宣言中に値が割り当てられなかった変数は、デフォルトで
undefined
に初期化されると想定されています。 したがって
let b;
let b = undefined;
と同じ
let b = undefined;
。 しかし、私は繰り返します-前に、式
let b;
失敗します。この変数を使用してください、できません。
別の予期しないひねりは、TDZ変数を使用したtypeofの動作です。
{ if (typeof a === "undefined") { console.log( "cool" ); } if (typeof b === "undefined") {
変数
宣言さ
いないため、存在をテストする唯一の安全な方法は
typeof
演算子を使用することです。 しかし、変数
b
場合はそうではありません。変数
b
は例外をスローします。これは、
let
ステートメントを使用してはるかに低く宣言されている
let
です。
推奨するだけではありませんが、新しい
let
ステートメントを使用するすべての広告はブロックの最上部に配置することを強くお勧めします。 これにより、リファクタリングの頭痛から解放され、不可解なエラーが排除され、コードがより理解しやすく、予測可能になります。
注:
let
ステートメントとブロックスコープの詳細については、第3章で説明します。
させる+
let
ステートメントのもう1つの重要な機能は、
for
ループでの動作です。
例を考えてみましょう:
var funcs = []; for (let i = 0; i < 5; i++) { funcs.push( function(){ console.log( i ); } ); } funcs[3]();
for
ヘッダーの
let i
式は、ループ全体ではなく、個々の反復ごとに新しい変数を宣言します。 同じことがループ内のクロージャーにも当てはまります。 実際、コードは期待どおりに動作します。
let i
var i
代わりに
var i
を使用しようとすると、結果として3ではなく例5が得られます。この場合、クロージャはすべての反復に共通するためです。
少量の水を追加すると、同じことを行う次の例を取得できます。
var funcs = []; for (var i = 0; i < 5; i++) { let j = i; funcs.push( function(){ console.log( j ); } ); } funcs[3]();
この例では、反復ごとに新しい変数
j
を明示的に作成します。 私は最初のオプションを好みます。もちろん、これはそれほど明確ではありませんが、放棄するほどではありません。
定数ステートメント
考慮すべき別のステートメントがあります。これもブロックスコープ
const
関連しています。
定数。これは、初期初期化後に読み取り専用になる変数です。
例:
{ const a = 2; console.log( a );
宣言中に既に値が割り当てられている変数の値を変更することはできません。 定数を宣言するとき
は、変数の値を明示的に指定する必要があります 。 デフォルトでは、定数は値
undefined
取得しません。したがって、そのような値が必要な場合は、手動で割り当てる必要があります
const a = undefined;
。
定数には割り当てに制限がありますが、変数の値に関連する制限はありません。 たとえば、定数が複雑な値である場合、引き続き変更できます。
{ const a = [1,2,3]; a.push( 4 ); console.log( a );
したがって、定数kindは
定数参照を保持し
ますが、それが指す配列はまだ動的です。
注:リンクを削除できないため、定数にオブジェクトまたは配列を割り当てることは、値がレキシカルスコープを離れるまでガベージコレクターによって値を削除できないことを意味します。 もちろん、これは望ましい動作かもしれませんが、注意してください。
以前は、変数を意図したリテラルで大文字を使用していたため、そのような変数の値を変更することはお勧めできません。 これで、不要な変更に対して警告する定数を使用できます。
噂によると、定数を使用すると、値が変更されないことがJSエンジンに明らかになるため、この演算子は
let
または
var
よりも最適化されたソリューションになります。
これについての空想にもかかわらず、定数を本当に使用する必要がある場合を理解することははるかに重要です。 単純な変数には定数を使用しないでください。そうしないと、誤解を招く可能性があります。
機能のブロック範囲
ES6以降、ブロック内で宣言された関数にはスコープ(ブロック)が含まれることが理解されています。 ES6より前は、さまざまな特定の実装とは異なり、仕様はこれについて沈黙していました。 しかし、今では仕様は真実です。
例を考えてみましょう:
{ foo();
この例では、関数はブロックスコープで宣言されているため、外部からアクセスできません。 また、興味深い事実に注目する価値があります。このような変数が初期化される前に操作できない
let
宣言とは対照的に、この場合はTDZエラーはありません。
関数のブロックスコープは、以下の例のように古い動作に依存してコードを記述している場合、問題になる可能性があります。
if (something) { function foo() { console.log( "1" ); } } else { function foo() { console.log( "2" ); } } foo();
ES6以前の環境では、
foo()
関数を呼び出した結果は
"2"
になります。これは、 something
変数の値に関係なく 、作業関数を
上げることで2番目だけになるためです。
ES6では、最後の行は例外
ReferenceError
スローします。