
JavaScriptの構文とは、正しく構造化されたJavaScriptプログラムを定義する一連の規則のことです。
以下の例では、console.log()ほとんどのブラウザに搭載されている標準的なテキスト出力機能を使用しています。
JavaScript標準ライブラリには、公式の標準テキスト出力関数がありません ( を除くdocument.write)。JavaScript は主に現代のWeb ブラウザ内でのクライアントサイドスクリプトに使用され、ほとんどすべての Web ブラウザがアラート機能を提供していることを考慮すると、も使用できますが、一般的には使用されていません。alert
JavaScriptに型注釈や追加機能を追加したTypeScriptは、JavaScriptと同じ構文を持ちながら、独自の追加機能も備えています。

ブレンダン・アイヒは、 JavaScript 1.1仕様書[ 1 ] [ 2 ]の最初の段落で、構文の起源を次のように要約しました。
JavaScriptは構文の大部分をJavaから借用しているが、AwkやPerlからも継承しており、オブジェクトプロトタイプシステムにおいてはSelfから間接的な影響を受けている。
JavaScriptの構文は主にJavaの構文から派生しており、Javaの構文はCの構文とC++の構文から派生している。
以下の単語はキーワードです。
breakcasecatchclassconstcontinuedebuggerdefaultdeletedoelseenumevalexportextendsfinallyforfunctionifimportininstanceofnewreturnsuperswitchthisthrowtrytypeofusingvarvoidwhilewith以下の単語は厳格モードにおけるキーワードです。
letimplementsinterfacestaticpackageprivateprotectedpublicyield以下の単語は、モジュールコードまたは非同期関数本体のキーワードです。
await以下の単語は、その言語で使用される文字通りの値を指します。
truefalsenullJavaScriptには、キーワードではない以下のグローバル定数も定義されています。
NaNInfinityundefined主にJavaに関連する以下の単語は、ECMAScript 5/6規格から削除されました。
abstractbooleanbytechardoublefinalfloatgotointlongnativeshortsynchronizedthrowstransientvolatile以下の単語はTypeScriptのキーワードです。
abstractanyasdeclareinferkeyofmodulenamespaceneverreadonlytypeunknownJavaScriptは大文字と小文字を区別します。コンストラクタの名前は大文字で始め、関数名や変数名は小文字で始めるのが一般的です。
例:
var a = 5 ; console.log ( a ) ; // 5 console.log ( A ) ; // ReferenceError: A is not defined がスローされるC言語とは異なり、JavaScriptソースコードの空白は意味に直接影響を与える可能性があります。JavaScriptではセミコロンで文を終了します。自動セミコロン挿入(ASI)のため、改行が解析されたときに正しく構成されている文でも、セミコロンが改行の直前に挿入されたかのように、完了した文とみなされる場合があります。自動セミコロン挿入の意図しない影響を軽減できる可能性があるため、文を終了させるセミコロンを明示的に指定することを推奨する専門家もいます。[ 3 ]
問題点は2つあります。5つのトークンは文の開始にも、完全な文の延長にもなり得ます。また、5つの制限付き生成規則では、特定の場所での改行が許可されておらず、誤った構文解析が発生する可能性があります。
問題となるトークンは、開き(括弧 " "、開き角括弧 " ["、スラッシュ " /"、プラス " +"、マイナス " -" の 5 つです。これらのうち、開き括弧は即時呼び出し関数式パターンでよく見られ、開き角括弧は時々出現しますが、その他は非常にまれです。例:
a = b + c ( d + e ). foo ()// 次のように扱われます: // a = b + c(d + e).foo();前述の文をセミコロンで終了させるという提案とともに。
代わりに、' ' または ' 'で始まる行の先頭にセミコロンを付けることで、前の行と誤って結合されないようにすることを提案する人もいます。これは防御セミコロンとして知られており、コードが再配置されたときに曖昧になる可能性があるため採用されます。例:([
a = b + c ( d + e ). foo ()// 次のように扱われます: // a = b + c; // (d + e).foo();JavaScriptライブラリの先頭にセミコロンが付けられる場合もあります。これは、末尾にセミコロンを省略する別のライブラリにライブラリを追加する場合、最初のステートメントの意味が曖昧になる可能性があるためです。このような、通常とは異なるセミコロンの位置が発生する可能性がある場合は、ステートメントの末尾に手動でセミコロンを追加する方が良いでしょう。
制限されている 5 つのプロダクションはreturn、、、、、および後置インクリメント/デクリメントです。いずれの場合も、セミコロンを挿入しても問題は解決しませんが、解析された構文が明確になり、エラーの検出が容易になります。throwとはオプションの値を取り、と はオプションのラベルを取ります。いずれの場合も、値またはラベルはステートメントと同じ行に保持することをお勧めします。これは、大きなオブジェクト リテラルを返す場合、誤って新しい行から開始される可能性がある return ステートメントで最もよく発生します。後置インクリメント/デクリメントの場合、前置インクリメント/デクリメントとの曖昧さが生じる可能性があるため、これらを同じ行に保持することをお勧めします。breakcontinuereturnthrowbreakcontinue
a + bを返す;// 未定義を返します。次のように扱われます。// return; // a + b; // 次のように記述する必要があります。// return a + b;コメントの構文は、C++、Swift 、その他のプログラミング言語と同じです。
1行コメントは で始まり//、行末まで続きます。2つ目のタイプのコメントも作成できます。これは で始まり/*で終わり*/、複数行コメントに使用できます。
3つ目のタイプのコメントであるハッシュバンコメントは、#!行の先頭から始まり、行末まで続きます。これらはファイルの先頭でのみ有効で、CLI環境での使用を想定しています。[ 4 ]
# !ハッシュバンコメント// 一行コメント/* 複数行 コメント */標準の JavaScript の変数には型が付いていないため、任意の値 (各値には型があります) を任意の変数に格納できます。言語の 6 番目のバージョンであるES6以降、変数はvar関数スコープの変数には、またはletブロックレベルのconst変数にはを使用して宣言できます。ES6 より前は、変数はステートメントでのみ宣言できました。で宣言された変数に割り当てられた値は変更できませんが、そのプロパティは変更できます。とが最新のブラウザでサポートされているため、は使用しなくなりました。 [ 5 ]変数の識別子は、文字、アンダースコア ( )、またはドル記号 ( ) で開始する必要がありますが、後続の文字は数字 ( ) にすることもできます。JavaScript は大文字と小文字を区別するため、大文字の「A」から「Z」は小文字の「a 」から「z」とは異なります。varconstvarletconst_$0-9
JavaScript 1.5以降では、識別子にISO 8859-1またはUnicode文字(または\uXXXXUnicodeエスケープシーケンス)を使用できます。[ 6 ]一部のJavaScript実装では、アットマーク(@)を識別子に使用できますが、これは仕様に反しており、新しい実装ではサポートされていません。
で宣言された変数は関数レベルで字句スコープをvar持ち、またはで宣言された変数はブロックレベルのスコープを持ちます。宣言はコードが実行される前に処理されるため、変数はコード内で宣言される前にに代入して使用できます。[ 7 ]これは、letconstホイスティングは、関数またはブロックの先頭で前方宣言することと同等です。 [ 8 ]
var、、letおよびステートメントではconst、宣言のみが巻き上げられ、代入は巻き上げられません。したがって、関数の途中のステートメントは、関数の先頭の宣言ステートメントと、関数の途中のその位置の代入ステートメントと同等です。これは、値が宣言される前にアクセスできないことを意味します。前方参照は不可能です。 の場合、変数の値は初期化されるまで です。またはで宣言された変数は初期化されるまでアクセスできないため、初期化前にそのような変数を参照するとエラーになります。varx=1varxx=1varundefinedletconst
変数宣言は、変数を宣言し、それに関数を代入するもので、変数ステートメントに似ていますが、宣言だけでなく代入も巻き上げます。つまり、ステートメント全体が包含する関数の先頭に現れるため、前方参照も可能です。関数ステートメントが包含する関数内のどこにあっても関係ありません。これは var、、、letまたはconstステートメントで関数式を変数に代入する場合とは異なります。
例えば、
var func = function () { .. } // 宣言のみが巻き上げられるfunction func () { .. } // 宣言と代入が巻き上げられるブロックスコープは、ブロック全体を関数で囲んでから実行することによって生成できます。これは即時実行関数式パターンとして知られています。または、キーワードを使用して変数を宣言することによって生成できますlet。
スコープ外で宣言された変数はグローバル変数です。上位スコープで宣言された変数は、子スコープからアクセスできます。
JavaScript は識別子を解決しようとすると、まずローカルスコープを検索します。この識別子が見つからない場合は、次の外側のスコープを検索し、グローバル変数が存在するグローバルスコープに到達するまでスコープチェーンに沿って検索を続けます。それでも見つからない場合は、JavaScript は例外を発生させます。ReferenceError
識別子を割り当てる場合、JavaScript は、この識別子を取得するためにまったく同じプロセスを実行しますが、グローバル スコープで見つからない場合は、作成されたスコープに「変数」を作成します。[ 9 ]その結果、宣言されていない変数は、割り当てられるとグローバルになります。グローバル スコープvarで変数を宣言 (キーワードを使用) (つまり、関数本体 (let/const の場合はブロック) の外側)、宣言されていない識別子を割り当てたり、グローバル オブジェクト(通常はwindow ) にプロパティを追加したりすると、新しいグローバル変数が作成されます。
JavaScriptの厳格モードでは、宣言されていない変数への代入が禁止されているため、グローバル名前空間の汚染を防ぐことができます。
以下に、変数宣言とスコープの例をいくつか示します。
var x1 = 0 ; // 関数内にないため、グローバル変数です。let x2 = 0 ; // ブロック内にないため、これもグローバル変数です。function f () { var z = 'foxes' , r = 'birds' ; // 2 つのローカル変数m = 'fish' ; // グローバル変数。これは、以前にどこにも宣言されていないためです。function child () { var r = 'monkeys' ; // この変数はローカル変数であり、親関数の「birds」rには影響しません。z = 'penguins' ; // クロージャ:子関数は親関数の変数にアクセスできます。}twenty = 20 ; // この変数は次の行で宣言されていますが、関数内のどこでも使用できます。ここに示すように、それ以前でも使用できます。var twenty ;child (); return x1 + x2 ; // x1とx2はグローバル変数なので、ここで使用できます}f ();console.log ( z ); // この行は、z の値が利用できなくなったため、ReferenceError 例外を発生させます。for ( let i = 0 ; i < 10 ; i ++ ) console.log ( i ); console.log ( i ) ; // ReferenceError: i が定義されていません というエラーが発生しますfor ( const i = 0 ; i < 10 ; i ++ ) console . log ( i ); // TypeError: 定数変数への代入 が発生しますfor ( const i of [ 1 , 2 , 3 ]) console . log ( i ); //例外は発生しません。i は再割り当てされるのではなく、各イテレーションで再作成されます。const pi ; // 構文エラー: const 宣言に初期化子がありません、というエラーが発生しますJavaScript言語には、6つの基本的なデータ型が用意されています。
UndefinedNumberBigIntStringBooleanSymbol一部の基本データ型には、型の境界範囲を表す名前付き値のセットが用意されています。これらの名前付き値については、以下の該当するセクションで説明します。
初期化されていないすべての変数には「undefined」の値が割り当てられ、存在しないオブジェクトプロパティをチェックする際にも「undefined」が返されます。ブール値のコンテキストでは、「undefined」の値は偽値とみなされます。
注:undefinedは正真正銘のプリミティブ型とみなされます。明示的に変換しない限り、undefinedの値は、論理コンテキストでfalseと評価される他の型と比較して、予期しない動作をする可能性があります。
let test ; // 変数は宣言されているが定義されていないため、... // ... undefined の値に設定されるconst testObj = {}; console.log ( test ); // test 変数は存在するが、値が定義されていないため、... // ... undefined と表示されるconsole.log ( testObj.myProp ); // testObjは存在するが、プロパティは存在しないため、... // ... undefined と表示されるconsole.log ( undefined == null ); // チェック中に型が強制されないため、true と表示されるconsole.log ( undefined === null ) ; // チェック中に型が強制されるため、false と表示される注: undefined を表す組み込みの言語リテラルはありません。そのため、変数が undefined かどうかを確実にチェックする方法ではありません。ECMAScript 5 より前のバージョンでは、 と記述することが合法だからです。より堅牢なアプローチは、 を使用して比較することです。(x===undefined)varundefined="I'm defined now";(typeofx==='undefined')
次のような関数は期待どおりに動作しません。
function isUndefined ( x ) { let u ; return x === u ; } // こんな感じ... function isUndefined ( x ) { return x === void 0 ; } // ... または 2 番目function isUndefined ( x ) { return ( typeof x ) === "undefined" ; } // ... または 3 番目ここで、my_var が不明な識別子である場合、呼び出しではReferenceErrorisUndefined(my_var)が発生しますが、呼び出しでは発生しません。typeofmy_var==='undefined'
数値は、 IEEE 754浮動小数点倍精度浮動小数点数としてバイナリで表現されます。この形式は、約16桁の有効数字の精度を提供しますが、分数を含む実数を常に正確に表現できるとは限りません。
これは、数値を比較したり書式設定したりする際に問題となります。例えば、次のようになります。
console.log ( 0.2 + 0.1 === 0.3 ); // false と表示されるconsole.log ( 0.94 - 0.01 ) ; // 0.9299999999999999 と表示されるそのため、数値を出力用にフォーマットする際には、 toFixed()メソッドなどのルーチンを使用して数値を丸める必要があります。
数値は、以下のいずれかの表記法で指定できます。
345 ; // JavaScript には数値型が 1 つしかないが、「整数」34.5 ; // 浮動小数点数3.45e2 ; // 345 と同等の別の浮動小数点数0b1011 ; // 11 に等しいバイナリ整数0o377 ; // 255 に等しい8進整数0xFF ; // 255 に等しい16進整数、数字は ... // ... 文字 AF は大文字または小文字ですES2021で導入された数値区切り文字として、 _(アンダースコア)もあります。
// 注: Wikipedia 構文はまだ数値区切り文字をサポートしていません1 _000_000_000 ; // 大きな数値で使用1 _000_000 .5 ; // 小数をサポート1 _000e1_000 ; // 指数をサポート// バイナリ、オクタル、16進数のサポート0b0000 _0000_0101_1011 ; 0o0001 _3520_0237_1327 ; 0xFFFF _FFFF_FFFF_FFFE ;// ただし、ユーザーは数字以外の数値部分の隣、または先頭や末尾でこれらを使用することはできません_12 ; // 変数が定義されていません (アンダースコアは変数識別子になります) 12 _ ; // 構文エラー (数値の末尾には使用できません) 12 _ .0 ; // 構文エラー (小数点の隣で区切り文字を使用するのは意味がありません) 12. _0 ; // 構文エラー12 e_6 ; // 構文エラー (数字以外の「e」の隣。先頭で区切り文字を使用するのは意味がありません) 1000 ____0000 ; // 構文エラー (数字以外の「_」の隣。一度に許可される区切り文字は 1 つだけです)数値型の+∞、−∞、およびNaN (非数)の範囲は、次の2つのプログラム式で取得できます。
Infinity ; // 正の無限大 (負の無限大は、たとえば -Infinity で取得されます) NaN ; // 非数値。文字列から数値への変換で失敗として返されます。無限大とNaNは数値です。
typeof Infinity ; // "number" を返しますtypeof NaN ; // "number" を返しますこれら3つの特殊値は、IEEE-754で規定されているとおりに対応し、そのように動作します。
数値コンストラクタ(関数として使用)または単項演算子の+または-を使用して、明示的な数値変換を実行できます。
const myString = "123.456" ; const myNumber1 = Number ( myString ); const myNumber2 = + myString ;コンストラクタとして使用すると、数値ラッパーオブジェクトが作成されます(ただし、あまり役に立ちません)。
const myNumericWrapper = new Number ( 123.456 );しかし、NaNはそれ自身とは等しくありません。
定数nan = NaN ;コンソール。log ( NaN == NaN ); // 偽のコンソール。log ( NaN === NaN ); // 偽のコンソール。log ( NaN !== NaN ); // 本当のコンソール。log ( nan !== nan ); // 真実// ユーザーはisNaNメソッドを使用して NaN をチェックできますconsole.log ( isNaN ( " NaN に変換されました" ) ); // true console.log ( isNaN ( NaN ) ); // true console.log ( Number.isNaN ( "変換されませんでした" ) ) ; // false console.log ( Number.isNaN ( NaN ) ); // trueJavaScript では、通常の数値は IEEE 754 浮動小数点型で表現されるため、整数は と の間にある場合にのみ安全に格納できますNumber.MIN_SAFE_INTEGER。Number.MAX_SAFE_INTEGER[ 10 ]一方、BigInt は任意のサイズの整数を表すため、プログラマーは IEEE 754 形式で表現するには大きすぎる、または小さすぎる整数を格納できます。[ 11 ]
BigInt 値を宣言する方法は 2 つあります。n整数に付加するか、BigInt関数を使用できます。[ 11 ]
const a = 12345n ; // 変数を作成し、12345 の BigInt 値を格納しますconst b = BigInt ( 12345 );JavaScript の文字列は文字のシーケンスです。JavaScript では、文字列は、文字のシーケンスを二重引用符 ( ") または単一'引用符 ( ) で囲むことで直接 (リテラルとして) 作成できます。このような文字列は 1 行に記述する必要がありますが、エスケープされた改行文字 ( など\n) を含めることができます。JavaScript 標準では、バッククォート文字 ( `、別名グレイブアクセントまたはバックティック) を使用して複数行のリテラル文字列を引用したり、構文を使用して埋め込み式を引用したりできます。[ 12 ]${expression}
const greeting = "こんにちは、世界!" ; const anotherGreeting = '地球の皆さん、ご挨拶申し上げます。' ; const aMultilineGreeting = `敬具、ジョン・ドゥ。`// テンプレートリテラルは、評価された式を型強制して文字列に挿入します。const templateLiteral = `これは anotherGreeting に格納されているものです: ${ anotherGreeting } 。` ; console . log ( templateLiteral ); // 'これは anotherGreeting に格納されているものです: '地球の皆さん、こんにちは。' console . log ( `このウェブページを見るには、${ Math . floor ( age )=> 18 ? "allowed" : "not allowed" }です` );文字列内の個々の文字には、 charAtメソッド ( String.prototypeによって提供される)を使用してアクセスできます。これは、文字列内の個々の文字にアクセスする際の推奨される方法です。なぜなら、最新のブラウザ以外でも動作するからです。
const h = greeting.charAt ( 0 ) ;最新のブラウザでは、文字列内の個々の文字に(1文字だけの文字列として)配列と同じ表記法でアクセスできます。
const h = greeting [ 0 ];しかし、JavaScriptの文字列は不変です。
greeting [ 0 ] = "H" ; // 失敗します。2 つの文字列に等価演算子 ("==")を適用すると、文字列の内容が同じであれば true が返されます。つまり、長さが同じで、同じ文字シーケンスが含まれている場合です (アルファベットの場合は大文字と小文字が区別されます)。したがって、次のようになります。
const x = "World" ; const compare1 = ( "Hello, " + x == "Hello, World" ); // ここで compare1 は true になります。const compare2 = ( "Hello, " + x == "hello, World" ); // ここで compare2 は ... // ... false になります。なぜなら、 ... // ...両方のオペランドの最初の文字 ... // ... が同じ大文字小文字ではないからです。同じ種類の引用符は、エスケープしない限りネストできません。
let x = '"Hello, World!" he said.' ; // 問題なし。x = "" Hello , World ! " he said." ; // 問題あり。x = "\"Hello, World!\" he said." ; // " を \" でエスケープすれば動作する。Stringコンストラクタは、文字列オブジェクト(文字列をラップするオブジェクト)を作成します。
const greeting = new String ( "Hello, World!" );これらのオブジェクトには、内部にラップされたプリミティブ文字列を返すvalueOfメソッドがあります。
const s = new String ( "Hello !" ); typeof s ; // 'object' です。typeof s . valueOf (); // 'string' です。2つのStringオブジェクト間の等価性は、文字列プリミティブの場合とは異なります。
const s1 = new String ( "Hello !" ); const s2 = new String ( "Hello !" ); s1 == s2 ; // これらは2つの異なるオブジェクトであるため、falseになります。s1 . valueOf () == s2 . valueOf (); // trueになります。JavaScript には、 trueとfalse のリテラルを持つブール型データ型が用意されています。typeof演算子は、これらのプリミティブ型に対して文字列"boolean"を返します。論理コンテキストで使用される場合、0、-0、null、NaN、undefined、および空文字列( "" )は、自動型変換によりfalseと評価されます。その他の値 (上記のリストの補数) はすべて、文字列"0"、"false"、および任意のオブジェクトを含め、trueと評価されます。
等価比較演算子(==および!=)による自動的な型強制は、型チェック比較演算子(===および!==)を使用することで回避できます。
型変換が必要な場合、JavaScript はBoolean、Number、String、またはObjectオペランドを次のように変換します。[ 13 ]
ダグラス・クロックフォードは、さまざまな型の値が論理コンテキストで評価されたときにどのように振る舞うかを説明するために、「真」と「偽」という用語を提唱しています。特にエッジケースに関してです。[ 14 ]バイナリ論理演算子は、 JavaScript の初期バージョンではブール値を返していましたが、現在は代わりにオペランドのいずれかを返します。論理積( )の場合は false、 論理和( )の場合はtrueと評価できる場合は、左オペランドが返されます。それ以外の場合は、右オペランドが返されます。ブール値と数値互換のオペランドが混在する場合 (数値として評価できる文字列、またはそのような文字列として評価できるオブジェクトを含む) は、比較演算子による自動的な型変換が異なる可能性があります。これは、ブール値オペランドが数値として比較されるためです。これは予期しない場合があります。式は、論理否定演算子: ( !! ) を二重にするか、Boolean()関数を使用するか、条件演算子: ( ) を使用することで、明示的にブールプリミティブにキャストできます。a && ba || bc ? t : f
// 自動型変換console.log ( true == 2 ); // false... true → 1 !== 2 ← 2 console.log ( false == 2 ) ; // false ... false → 0 !== 2 ← 2 console.log ( true == 1 ); // true .... true → 1 === 1 ← 1 console.log ( false == 0 ); // true.... false → 0 === 0 ← 0 console.log(true == " 2 " ) ; // false ... true → 1 !== 2 ← "2" console.log ( false == " 2" ); // false... false → 0 !== 2 ← "2" console.log ( true == " 1" ); // true .... true → 1 === 1 ← "1" console.log ( false == " 0 " ); // true.... false → 0 === 0 ← "0" console .ログ( false == "" ); // true.... false → 0 === 0 ← ""コンソール.ログ( false == NaN ); // false... false → 0 !== NaNconsole.log ( NaN == NaN ); // false...... NaNはNaNを含む何とも等価ではありません。//型チェック比較(型と値の変換なし)console.log ( true === 1 ); // false...... データ型が一致しません// 明示的な型変換console.log ( true === !! 2 ); // true... データ型と値が一致console.log (true === !!0); // false... データ型は一致するが、値が異なる console.log( 1 ? true : false ) ; // true ... ± 0とNaNだけが「偽」な数値console.log ( " 0 " ? true : false ); // true... 空文字列だけが「偽」console.log ( Boolean ({ } )); // true... すべてのオブジェクトが「真」new 演算子を使用すると、Boolean プリミティブのオブジェクト ラッパーを作成できます。ただし、typeof演算子はオブジェクト ラッパーに対してboolean を返さず、 objectを返します。すべてのオブジェクトはtrueと評価されるため、ラップされた値を取得するには、 .valueOf()や.toString()などのメソッドを使用する必要があります。Boolean 型への明示的な型変換には、 Boolean オブジェクトよりもBoolean()関数 ( newなし) を使用することを Mozilla は推奨します。
const b = new Boolean ( false ); //オブジェクト false {} const t = Boolean ( b ); // Boolean true const f = Boolean ( b.valueOf ( )); // Boolean false let n = new Boolean ( b ); // 推奨されないn = new Boolean ( b.valueOf ( )); // 推奨if ( 0 || - 0 || "" || null || undefined || b . valueOf () || ! new Boolean () || ! t ) { console . log ( "Never this" ); } else if ([] && {} && b && typeof b === "object" && b . toString () === "false" ) { console . log ( "Always this" ); }シンボルはES6で導入された機能です。各シンボルは一意の値が保証されており、カプセル化に使用できます。[ 15 ]
例:
let x = Symbol ( 1 ); const y = Symbol ( 1 ); x === y ; // => falseconst symbolObject = {}; const normalObject = {};// xとyは一意なので、// オブジェクトの一意のキーとして使用できますsymbolObject [ x ] = 1 ; symbolObject [ y ] = 2 ;symbolObject [ x ]; // => 1 symbolObject [ y ]; // => 2// 通常の数値キーと比較normalObject [ 1 ] = 1 ; normalObject [ 1 ] = 2 ; // 1 の値を上書きしますnormalObject [ 1 ]; // => 2// x の値を変更しても、オブジェクトに格納されているキーは変更されません。x = Symbol ( 3 ); symbolObject [ x ]; // => undefined// x を元に戻すと、別の一意の Symbol が作成されます。x = Symbol ( 1 ); symbolObject [ x ]; // => undefinedよく知られたシンボルもあります。
その一つはSymbol.iterator、何かがを実装している場合Symbol.iterator、それは反復可能であるということです。
const x = [ 1 , 2 , 3 , 4 ]; // x は配列ですx [ Symbol . iterator ] === Array . prototype [ Symbol . iterator ]; // 配列は反復可能ですconst xIterator = x [ Symbol . iterator ](); // [Symbol.iterator] 関数は x のイテレータを提供する必要がありますxIterator . next (); // { value: 1, done: false } xIterator . next (); // { value: 2, done: false } xIterator . next (); // { value: 3, done: false } xIterator . next (); // { value: 4, done: false } xIterator . next (); // { value: undefined, done: true } xIterator . next (); // { value: undefined, done: true }// for..of ループは値を自動的に反復処理しますfor ( const value of x ) { console . log ( value ); // 1 2 3 4 }// セットも反復可能です: [ Symbol . iterator ] in Set . prototype ; // truefor ( const value of new Set ([ 'apple' , 'orange' ])) { console . log ( value ); // "apple" "orange" }JavaScript言語には、いくつかのネイティブオブジェクトが用意されています。JavaScriptネイティブオブジェクトは、JavaScript仕様の一部とみなされています。JavaScript環境に関わらず、これらのオブジェクトは常に利用可能であるべきです。
配列は、整数キーでインデックス付けされたデータ値を格納するために特別に設計されたコンストラクタからプロトタイプ化されたJavaScriptオブジェクトですArray。配列は、基本的なオブジェクト型とは異なり、プログラマがルーチンタスク(たとえば、、、および)を実行するのに役立つメソッドとプロパティでプロトタイプ化されてjoinいsliceますpush。
C言語ファミリーと同様に、配列はゼロベースのインデックス方式を使用します。pushメソッドを使用して空の配列に挿入された値は、配列の0番目のインデックスを占めます。
const myArray = []; // 変数 myArray を新しく作成された空の配列にポイントします。myArray . push ( "hello World" ); // 次の空のインデックス (この場合は 0) を埋めます。 console . log ( myArray [ 0 ]); // console.log("hello World"); と同等です。配列には、length配列内で使用されている最大の整数インデックスよりも常に大きくなることが保証されたプロパティがあります。さらに大きなインデックスを持つプロパティを作成すると、このプロパティは自動的に更新されます。lengthプロパティに小さい数値を書き込むと、それよりも大きいインデックスは削除されます。
sの要素には、Array通常のオブジェクトプロパティアクセス表記を使用してアクセスできます。
myArray [ 1 ]; // myArray の 2 番目の要素myArray [ "1" ];上記2つは同等です。数値の別の表現方法を用いた「ドット」表記や文字列は使用できません。
myArray .1 ; // 構文エラーmyArray [ "01" ]; // myArray[1] とは異なります配列の宣言には、ArrayリテラルまたはArrayコンストラクタのどちらでも使用できます。
let myArray ;// 配列リテラルmyArray = [ 1 , 2 ]; // 長さが 2 myArray = [ 1 , 2 ,]; // 同じ配列 - ユーザーは最後にカンマを追加することもできます// 配列の一部を埋めないことも可能ですmyArray = [ 0 , 1 , /* 空欄 */ , /* 空欄 */ , 4 , 5 ]; // 長さ 6 myArray = [ 0 , 1 , /* 空欄 */ , /* 空欄 */ , 4 , 5 ,]; // 同じ配列myArray = [ 0 , 1 , /* 空欄 */ , /* 空欄 */ , 4 , 5 , /* 空欄 */ ,]; // 長さ 7// コンストラクタを使用する場合myArray = new Array ( 0 , 1 , 2 , 3 , 4 , 5 ); // 長さ6の配列myArray = new Array ( 365 ); // 長さ365の空の配列配列は、定義された要素のみがメモリを使用するように実装されています。つまり、「疎配列」です。 と を設定すると、他のオブジェクトと同様に、これら 2 つの要素にのみスペースが使用されます。配列の は、引き続き 58 と報告されます。配列の最大長は 4,294,967,295 で、これは 32 ビットのバイナリ数 (111111111111111111111111111111111) 2に相当します。myArray[10]='someThing'myArray[57]='somethingOther'length
オブジェクト宣言リテラルを使用すると、他の言語の連想配列とよく似た動作をするオブジェクトを作成できます。
const dog = { color : "brown" , size : "large" }; dog [ "color" ]; // 結果は "brown" dog . color ; // 結果も "brown"オブジェクトと配列の宣言リテラルを使用すると、連想配列、多次元配列、またはその両方を素早く作成できます。(厳密には、JavaScriptは多次元配列をサポートしていませんが、配列の配列を使用することでそれを模倣できます。)
const cats = [{ color : "brown" , size : "large" }, { color : "black" , size : "small" }]; cats [ 0 ][ "size" ]; // 結果は "large" になりますconst dogs = { rover : { color : "brown" , size : "large" }, spot : { color : "black" , size : "small" }}; dogs [ "spot" ][ "size" ]; // 結果は "small" dogs . rover . color ; // 結果は "brown"オブジェクトDateには、符号付きミリ秒カウントが格納されます。ゼロは1970年1月1日00:00:00 UTを表し、範囲は±10 8日です。コンストラクタに引数を渡す方法はいくつかありますDate。月は0から始まることに注意してください。
new Date (); // 現在の日時を表す新しい Date インスタンスを作成します。new Date ( 2010 , 2 , 1 ); // 2010-Mar-01 00:00:00 を表す新しい Date インスタンスを作成します。new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // 2010-Mar-01 14:25:30 を表す新しい Date インスタンスを作成します。new Date ( "2010-3-1 14:25:30" ); // 文字列から新しい Date インスタンスを作成します。フィールドを抽出する方法と便利な以下の方法が提供されていますtoString。
const d = new Date ( 2010 , 2 , 1 , 14 , 25 , 30 ); // 2010-Mar-01 14:25:30;// '2010-3-1 14:25:30' と表示されます: console.log( d.getFullYear ( ) + ' - ' + ( d.getMonth ( ) + 1 ) + ' - ' + d.getDate ( ) + ' ' + d.getHours ( ) + ' : ' + d.getMinutes ( ) + ' :' + d.getSeconds ( ) ) ;//組み込みの toString は、'Mon 1 March, 2010 14:25:30 GMT-0500 (EST)' のようなものを返します: console.log ( d ) ;以下のクラスを使用すると、カスタムエラーメッセージを作成できますError。
throw new Error ( "何らかのエラーが発生しました。" );これらは、例外処理のセクションで説明されているように、try...catch...finally ブロックで捕捉できます。
Mathオブジェクトには、数学に関連するさまざまな定数 (例えば、π ) や関数 (例えば、コサイン) が含まれています。( Mathオブジェクトには、 ArrayやDateとは異なり、コンストラクタがありません。すべてのメソッドは「静的」、つまり「クラス」メソッドです。) すべての三角関数は、度やグラジアンではなく、ラジアンで表される角度を使用します。
/expression/ . test ( string ); // ブール値を返す"string" . search ( /expression/ ); // 位置番号を返す"string" . replace ( /expression/ , replacement );// 以下はいくつかの例ですif ( /Tom/ . test ( "My name is Tom" )) console . log ( "Hello Tom!" ); console . log ( "My name is Tom" . search ( /Tom/ )); // == 11 (Tom の前の文字) console . log ( "My name is Tom" . replace ( /Tom/ , "John" )); // == "My name is John"// \d - 数字// \D - 数字以外// \s - スペース// \S - スペース以外// \w - 単語文字// \W - 単語以外// [ ] - いずれか// [^] - いずれか以外// - - 範囲if ( /\d/ . test ( '0' )) console . log ( 'Digit' ); if ( /[0-9]/ . test ( '6' )) console . log ( 'Digit' ); if ( /[13579]/ . test ( '1' )) console . log ( 'Odd number' ); if ( /\S\S\s\S\S\S\S/ . test ( 'My name' )) console . log ( 'Format OK' ); if ( /\w\w\w/ . test ( 'Tom' )) console . log ( 'Hello Tom' ); if ( /[a-zA-Z]/ . test ( 'B' )) console . log ( 'Letter' );// A...Z a...z 0...9 - 英数字// \u0000...\uFFFF - Unicode 16 進数// \x00...\xFF - ASCII 16 進数// \t - タブ// \n - 改行// \r - CR // . - 任意の文字// | - ORif ( /Tm/ . test ( 'Tom' )) console . log ( 'こんにちは、Tom、Tam、またはTim' ); if ( /A|B/ . test ( "A" )) console . log ( 'AまたはB' );// ? - 0 または 1 が一致// * - 0 以上// + - 1 以上// {n} - ちょうど n // {n,} - n 以上// {0,n} - n 以下// {n,m} - n から m の範囲if ( /ab?c/ . test ( "ac" )) console . log ( "OK" ); // 一致: "ac", "abc" if ( /ab*c/ . test ( "ac" )) console . log ( "OK" ); // 一致: "ac", "abc", "abbc", "abbbc" などif ( /ab+c/ . test ( "abc" )) console . log ( "OK" ); // 一致: "abc", "abbc", "abbbc" などif ( /ab{3}c/ . test ( "abbbc" )) console . log ( "OK" ); // 一致: "abbbc" if ( /ab{3,}c/ . test ( "abbbc" )) console . log ( "OK" ); // 一致: "abbbc"、"abbbbc"、"abbbbbc" などif ( /ab{1,3}c/ . test ( "abc" )) console .ログ( "OK" ); // 一致: "abc"、"abbc"、"abbbc"// ^ - 文字列は// $ - 文字列はif ( /^My/ . test ( "My name is Tom" )) console . log ( "Hi!" ); if ( /Tom$/ . test ( "My name is Tom" )) console . log ( "Hi Tom!" );// ( ) - 文字をグループ化しますif ( /water(mark)?/ . test ( "watermark" )) console . log ( "ここに水があります!" ); // 一致: "water", "watermark", if ( /(Tom)|(John)/ . test ( "John" )) console . log ( "こんにちは、トムまたはジョン!" );// /g - グローバル// /i - 大文字/小文字を無視// /m - 一致が複数行にまたがることを許可console.log ( "hi tom!" . replace ( /Tom/i , "John" )); // == "hi John!" console.log ("ratatam".replace ( / ta / , " tu " ) ) ; // == "ratutam" console.log ( " ratatam" .replace ( /ta/g , " tu" ) ); // == "ratutum"my_array = my_string.split ( my_delimiter ) ; // 例my_array = "dog,cat,cow" .split ( "," ) ; // my_array==["dog","cat", " cow"];my_array = my_string.match ( my_expression ); // 例my_array = "We start at 11:30, 12:15 and 16:45" .match ( / \d\d:\d\d/g ) ; // my_array==["11:30","12:15","16:45"];const myRe = /(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})/ ; const results = myRe . exec ( "日付と時刻は 2009-09-08 09:37:08 です。" ); if ( results ) { console . log ( "一致: " + results [ 0 ]); // 一致全体const my_date = results [ 1 ]; // 最初のグループ == "2009-09-08" const my_time = results [ 2 ]; // 2 番目のグループ == "09:37:08" console . log ( `時刻は $ { my_date }の${ my_time }です` ); } else console . log ( "有効な日付が見つかりませんでした!" );FunctionJavaScriptのすべての関数はコンストラクタのインスタンスです。
// x、y は引数です。'return x + y' は関数本体で、引数リストの最後です。const add = new Function ( 'x' , 'y' , 'return x + y' ); add ( 1 , 2 ); // => 3上記のadd関数は、関数式を使用して定義することもできます。
const add = function ( x , y ) { return x + y ; }; add ( 1 , 2 ); // => 3ES6では、アロー関数構文が追加され、値を返す関数をより簡潔に記述できるようになりました。また、式thisとは異なり、呼び出し元や呼び出し対象から継承するのではなく、グローバルオブジェクトの型を保持しますfunction() {}。
const add = ( x , y ) => { return x + y ;}; // 値は暗黙的に返されることもあります (つまり、return ステートメントは不要です) const addImplicit = ( x , y ) => x + y ;add ( 1 , 2 ); // => 3 addImplicit ( 1 , 2 ) // => 3ホイスティングが必要な関数については、別の式があります。
function add ( x , y ) { return x + y ; } add ( 1 , 2 ); // => 3ホイスティングにより、ユーザーは関数が「宣言」される前に使用できるようになります。
add ( 1 , 2 ); // => 3、ReferenceErrorではないfunction add ( x , y ) { return x + y ; }関数インスタンスには、プロパティとメソッドがあります。
function subtract ( x , y ) { return x - y ; }console.log ( subtract.length ) ; // = > 2 、関数の引数の数console.log ( subtract.toString ( ) ) ;/* "関数 subtract(x, y) { return x - y; }" */'+'演算子はオーバーロードされており、文字列の連結と算術加算の両方に使用されます。そのため、文字列と数値を意図せず混在させてしまうと問題が発生する可能性があります。また、単項演算子として、数値文字列を数値に変換することもできます。
// 2つの文字列を連結するconsole.log ( ' He ' + 'llo' ); // Helloと表示される// 2つの数値を加算するconsole.log ( 2 + 6 ) ; // 8と表示される//数値と文字列を加算すると、左から右に連結されますconsole.log ( 2 + ' 2' ); // 22 と表示されますconsole.log ( '$' + 3 + 4 ); // $34 と表示されますが、$7 が期待されていたかもしれませんconsole.log ( ' $ ' + ( 3 + 4 ) ) ; // $7 と表示されますconsole.log ( 3 + 4 + '7' ); // 77と表示されます。文字列が追加されるまで数値は数値のままです//単項プラスを使用して文字列を数値に変換しますconsole.log ( + '2' === 2 ); // true と表示されますconsole.log ( + 'Hello' ); // NaN と表示されます同様に、演算子「*」はオーバーロードされており、文字列を数値に変換することができます。
console.log ( 2 + ' 6 ' * 1 ); // 8 と表示されるconsole.log ( 3 * ' 7' ); // 21 console.log ( ' 3' * '7' ); // 21 console.log ( ' hello ' * ' world ' ); // NaN と表示されるJavaScript は以下の二項算術演算子をサポートしています。
JavaScript は以下の単項算術演算子をサポートしています。
let x = 1 ; console.log ( ++ x ); // xは2 になります。2 と表示されます。console.log ( x ++ ) ; // 2 と表示されます。x は 3 になります。 console.log ( x ) ; // x は 3 です。3 と表示されます。console.log ( x-- ) ; // 3 と表示されます。x は 2 になります。console.log ( x ); // 2と表示されます。x は 2 です。console.log ( -- x ); // x は 1 になります。1 と表示されます。剰余演算子は、剰余で除算した後の余りを表示します。負の数が含まれる場合、返される値はオペランドによって異なります。
const x = 17 ; console.log ( x % 5 ); // 2 と表示されるconsole.log ( x % 6 ) ; // 5 と表示されるconsole.log ( -x % 5 ) ; // -2 と表示されるconsole.log ( -x % -5 ) ; // -2 と表示されるconsole.log ( x % -5 ) ; // 2と表示される常に負でない数を返すには、ユーザーは剰余項を再度加算し、剰余演算子を再度適用すればよい。
const x = 17 ; console.log (( - x % 5 + 5 ) % 5 ); // 3 と表示されるユーザーは以下のことも実行できます。
const x = 17 ; console.log ( Math.abs ( -x % 5 ) ) ; // 3もlet x = 9 ; x += 1 ; console.log ( x ); // 表示: 10 x *= 30 ; console.log ( x ); //表示: 300 x /= 6 ; console.log ( x ); //表示: 50 x - = 3 ; console.log ( x ); //表示: 47 x % = 7 ; console.log ( x ) ; //表示: 5オブジェクトタイプの割り当て
/** * JavaScriptオブジェクトを学習するために... */ const object_1 = { a : 1 }; // 新しく作成されたオブジェクトの参照をobject_1に割り当てますlet object_2 = { a : 0 }; let object_3 = object_2 ; // object_3はobject_2と同じオブジェクトを参照しますobject_3 . a = 2 ; message (); // 1 2 2と表示されますobject_2 = object_1 ; // object_2はobject_1と同じオブジェクトを参照します// object_3はobject_2が参照していたオブジェクトを依然として参照しますmessage ( ); // 1 1 2と表示されますobject_2 . a = 7 ; // object_1を変更しますmessage (); // 7 7 2と表示されますobject_3.a = 5 ; // object_3 は object_2 を変更しませんmessage (); // 7 7 5 と表示されますobject_3 = object_2 ; object_3.a = 4 ; // object_3はobject_1 と object_2 を変更しますmessage ( ); // 4 4 4 と表示されます/** * console.log メッセージを出力します*/ function message () { console . log ( object_1 . a + " " + object_2 . a + " " + object_3 . a ); }MozillaのJavaScriptでは、バージョン1.7以降、分割代入によってデータ構造の一部を複数の変数に一度に代入できるようになりました。代入式の左辺は、任意にネストされたオブジェクト/配列リテラルに似たパターンで、その末端には代入される値のサブ構造を受け取る左辺値が含まれています。
let a , b , c , d , e ; [ a , b , c ] = [ 3 , 4 , 5 ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // 表示: 3,4,5 e = { foo : 5 , bar : 6 , baz : [ 'Baz' , 'Content' ]}; const arr = []; ({ baz : [ arr [ 0 ], arr [ 3 ]], foo : a , bar : b } = e ); console . log ( ` ${ a } , ${ b } , ${ arr } ` ); // 表示: 5,6,Baz,,,Content [ a , b ] = [ b , a ]; // a と b の内容を入れ替えるconsole . log ( a + ',' + b ); // 表示: 6,5[ a , b , c ] = [ 3 , 4 , 5 ]; // 順列[ a , b , c ] = [ b , c , a ]; console . log ( ` ${ a } , ${ b } , ${ c } ` ); // 表示: 4,5,3ECMAScript 2015 標準では、 「スプレッド構文」 [ 16 ]および「レスト パラメータ」 [ 17 ]...の関連概念に対して「」配列演算子が導入されました。オブジェクトのスプレッドは ECMAScript 2018 で追加されました。
スプレッド構文は、配列やオブジェクトを分割代入する別の方法を提供します。配列の場合、要素を関数呼び出しの引数、または配列リテラルの要素として使用します。オブジェクトの場合、複数のオブジェクトを結合したり、プロパティを上書きしたりするために使用できます。
言い換えれば、「 」は「 」を「 」に、「」を「 」に、「 」を「」に...変換します。[...foo][foo[0], foo[1], foo[2]]this.bar(...foo);this.bar(foo[0], foo[1], foo[2]);{ ...bar }{ prop: bar.prop, prop2: bar.prop2 }
const a = [ 1 , 2 , 3 , 4 ];// 同じ式の中で複数回使用できますconst b = [... a , ... a ]; // b = [1, 2, 3, 4, 1, 2, 3, 4];// スプレッド項目以外の項目と組み合わせることができます。const c = [ 5 , 6 , ... a , 7 , 9 ]; // c = [5, 6, 1, 2, 3, 4, 7, 9];// 比較のために、スプレッド演算子を使用せずにこれを実行する// ネストされた配列を作成します。const d = [ a , a ]; // d = [[1, 2, 3, 4], [1, 2, 3, 4]]// 関数呼び出しでも同様に機能しますfunction foo ( arg1 , arg2 , arg3 ) {console.log ( ` ${ arg1 } : ${ arg2 } : $ { arg3 } ` ) ;}// 関数が使用するパラメータよりも多くのパラメータを渡す場合でも、ユーザーはこれを使用できますfoo (... a ); // "1:2:3" → foo(a[0], a[1], a[2], a[3]);// ユーザーはこれを非スプレッドパラメータと組み合わせることができますfoo ( 5 , ... a , 6 ); // "5:1:2" → foo(5, a[0], a[1], a[2], a[3], 6);// 比較のために、スプレッド演算子を使用せずにこれを実行する// 配列を arg1 に割り当て、他のパラメータには何も割り当てません。foo ( a ); // "1,2,3,4:undefined:undefined"const bar = { a : 1 , b : 2 , c : 3 };// これはオブジェクトをコピーしますconst copy = { ... bar }; // copy = { a: 1, b: 2, c: 3 };// ここで「b」が上書きされますconst override = { ... bar , b : 4 }; // override = { a: 1, c: 3, b: 4 }...関数宣言で が使用される場合、それは残余パラメータを示します。残余パラメータは、関数のパラメータリストの最後の名前付きパラメータでなければなりません。このパラメータには、Array他の名前付きパラメータを超える関数に渡された引数を含む が割り当てられます。つまり、関数に渡された引数の「残り」を受け取ります(そのため、この名前が付けられています)。
function foo ( a , b , ... c ) { console . log ( c . length ); }foo ( 1 , 2 , 3 , 4 , 5 ); // "3" → c = [3, 4, 5] foo ( 'a' , 'b' ); // "0" → c = []レストパラメータは、JavaScriptのオブジェクトに似ていますarguments。これは、現在の関数呼び出しに含まれるすべてのパラメータ(名前付きと名前なし)を含む配列のようなオブジェクトです。ただしarguments、とは異なり、レストパラメータは真のArrayオブジェクトであるため、などのメソッド.slice()を.sort()直接使用できます。
オブジェクトを参照する変数は、同じオブジェクトを参照している場合にのみ、等しいまたは同一であるとみなされます。
const obj1 = { a : 1 }; const obj2 = { a : 1 }; const obj3 = obj1 ; console . log ( obj1 == obj2 ); //false console . log ( obj3 == obj1 ); //true console . log ( obj3 === obj1 ); //true文字列も参照してください。
JavaScriptには4つの論理演算子があります。
論理演算の文脈では、以下の式を除き、すべての式が真と評価されます。
""、''、0、-0、NaN、null、undefined、false。ブール関数は、型プリミティブに明示的に変換するために使用できますBoolean。
//空の文字列のみが false を返しますconsole.log ( Boolean ( " " ) === false ) ; console.log ( Boolean ( " false" ) === true ); console.log ( Boolean ( "0" ) === true ) ;//ゼロと NaN のみが false を返しますconsole.log ( Boolean ( NaN ) === false ) ; console.log ( Boolean ( 0 ) === false ) ; console.log ( Boolean ( -0 ) === false ) ; // -1 * 0と同等console.log ( Boolean ( -2 ) === true ) ;//すべてのオブジェクトは true を返しますconsole.log ( Boolean ( this ) === true ) ; console.log ( Boolean ( {}) === true ); console.log ( Boolean ( [ ]) === true ) ;//これらの型はfalse を返しますconsole.log ( Boolean ( null ) === false ); console.log ( Boolean ( undefined ) === false ); // Boolean ( ) と同等NOT演算子は、オペランドをブール値として評価し、否定を返します。この演算子を連続して2回使用して二重否定にすると、式が明示的にブール型のプリミティブに変換されます。
console.log ( ! 0 === Boolean ( ! 0 )); console.log ( Boolean ( ! 0 ) === !! 1 ) ; console.log ( !! 1 === Boolean ( 1 ) ); console.log ( !! 0 === Boolean ( 0 ) ); console.log ( Boolean ( 0 ) === ! 1 ) ; console.log ( ! 1 === Boolean ( ! 1 )); console.log ( ! " " === Boolean ( ! " " ) ) ; console.log ( Boolean ( ! " " ) === !! " s" ) ; console.log ( !! " s " === Boolean ( "s " ) ) ; console.log ( !! " " === Boolean ( " " ) ) ; console . console.log ( Boolean ( "" ) === ! "s" ) ; console.log ( ! " s" === Boolean ( ! "s" ));三項演算子は、明示的な型変換にも使用できます。
console.log ([] == false ) ; console.log ([] ? true : false ) ; // “ truthy” だが、比較には [].toString() を使用console.log ( [ 0 ] == false ); console.log ([ 0 ] ? true : false ) ; // [0].toString() == "0" console.log ( "0" == false); console.log("0" ? true : false ) ; // " 0 " → 0 ... ( 0 == 0 ) ... 0 ← false console.log ( [ 1 ] == true ) ; console.log ([ 1 ] ? true : false ) ; // [1].toString() == "1" console.log("1" == true); console.log ( " 1 " ? true : false ) ; // " 1 " → 1 ... (1 == 1) ... 1 ← true console . console.log ([ 2 ] != true ) ; console.log ([ 2 ] ? true : false ); // [2].toString() == "2" console.log("2" != true); console.log("2" ? true : false ) ; // " 2 " → 2 ... ( 2 ! = 1 ) ... 1 ← truei++後置インクリメント( )などの機能を使用する式には、予期される副作用があります。JavaScript は式の短絡評価を提供します。左オペランドだけでは式の値を決定するのに十分でない場合にのみ、右オペランドが実行されます。
console.log ( a || b ); // aがtrue の場合、bを評価する理由はありません。console.log ( a && b ); // a が false の場合、bを評価する理由はありません。console.log ( c ? t : f ); // c が true の場合、fを評価する理由はありません。JavaScriptとJScriptの初期バージョンでは、二項論理演算子はブール値を返していました(ほとんどのC言語由来のプログラミング言語と同様)。しかし、現代のすべての実装では、代わりにオペランドのいずれかを返します。
console.log ( a || b ); // aがtrueの場合はaを返し、そうでない場合はbを返すconsole.log ( a && b ) ; // aがfalseの場合はaを返し、そうでない場合はbを返すC言語の動作に慣れているプログラマーはこの機能に驚くかもしれないが、ヌル値の合体などのパターンをより簡潔に表現できる。
const s = t || "(default)" ; // t に値を割り当てます。t が null、空などの場合はデフォルト値を割り当てます。JavaScript は以下の二項ビット演算子をサポートしています。
例:
const x = 11 & 6 ; console.log ( x ) ; // 2JavaScript は、以下の単項ビット演算子をサポートしています。
JavaScript は以下の二項代入演算子をサポートしています。
例:
let x = 7 ; console.log ( x ); // 7 x << = 3 ; console.log ( x ) ; // 7->14->28-> 56例:
str = "ab" + "cd"とします。// "abcd" str += "e" ; // "ABCDE"const str2 = "2" + 2 ; // "22" であって "4" や 4 ではありません。JavaScriptの最も近い演算子は、 ECMAScriptの第 11 版??で標準に追加された「null 合体演算子」です。 [ 18 ]以前のバージョンでは、 Babelプラグインを介して使用でき、TypeScriptでは使用できました。左辺のオペランドを評価し、結果の値が「null でない」(または)場合は、その値を結果として取得します。そうでない場合は、右辺のオペランドを評価し、結果の値を結果として取得します。nullundefined
次の例では、の値がまたはでない場合は、aの値が割り当てられ、それ以外の場合は3が割り当てられます。bbnullundefined
const a = b ?? 3 ;ヌル合体演算子が登場する前は、プログラマーは論理OR演算子()を使用していました。||しかし、が特にまたは??を探すのに対し、演算子は偽値(、、、、、、およびもちろん)を探します。nullundefined||nullundefined""0NaNfalse
次の例では、の値が真である場合aはの値が割り当てられ、そうでない場合は3が割り当てられます。bb
const a = b || 3 ;一対の波括弧と、その中に含まれる一連の文で構成されるのが複合文であり、これは文が使用できる場所であればどこでも使用できます。{ }
if ( expr ) { //ステートメント; } else if ( expr2 ) { //ステートメント; } else { //ステートメント; }条件演算子は、条件に応じて2つの式のうちの1つとして評価される式を作成します。これは、条件に応じて実行する2つのステートメントのうちの1つを選択するif文に似ています。つまり、条件演算子は式にとってのif文のようなものです。
const result = condition ? expression : alternative ;は以下と同じです。
if (条件) { const result =式; } else { const result =代替案; }if文とは異なり、条件演算子は「else分岐」を省略することはできません。
JavaScriptのswitch文の構文は以下のとおりです。
switch ( expr ) { case SOMEVALUE : // ステートメント; break ; case ANOTHERVALUE : // ANOTHERVALUE || ORANOTHERONE の場合のステートメント// break ステートメントはなく、次のケースにフォールスルーしますcase ORANOTHERONE : // ORANOTHERONE に固有のステートメント (つまり、!ANOTHERVALUE && ORANOTHER); break ; // ここで処理が終了します。case YETANOTHER : // ステートメント; break ; default : // ステートメント; break ; }break;これはオプションですが、通常は必要です。そうしないと、コードの実行が次のケースブロックの本体に続いてしまうためです。このフォールスルー動作は、同じステートメントのセットが複数のケースに適用される場合に使用でき、それらのケース間で事実上の論理和を作成します。JavaScriptのforループの構文は以下のとおりです。
for (初期値;条件;ループ文) { /* 条件が満たされている 間、for{} ループが繰り返される たびに文が実行されます */ }または
for (初期値;条件;ループ文(反復回数)) // 1つの文JavaScriptの構文はfor ... in loop以下のとおりです。
for ( var property_name in some_object ) { // some_object[property_name] を使用するステートメント; }if(some_object.hasOwnProperty(property_name)){...}Array.prototype.newMethod=function(){...}for ... inJavaScriptのwhileループの構文は以下のとおりです。
while (条件) {ステートメント1 ;ステートメント2 ;ステートメント3 ; ... }JavaScriptの構文はdo ... while loop以下のとおりです。
do { statement1 ; statement2 ; statement3 ; ... } while ( condition );with ステートメントは、指定されたオブジェクトのすべてのプロパティとメソッドを次のブロックのスコープに追加し、それらをローカル変数であるかのように参照できるようにします。
with ( document ) { const a = getElementById ( 'a' ); const b = getElementById ( 'b' ); const c = getElementById ( 'c' ); };その意味論は、 Pascalの with 文に似ています。
with ステートメントの使用はプログラムのパフォーマンスを阻害し、コードの明確さを低下させると考えられているため (任意の変数が実際にはwith で囲まれたプロパティである可能性があるため)、厳格モードではこのステートメントは許可されていません。
JavaScript は、ほとんどの実装でネストされたラベルをサポートしています。ループまたはブロックは break ステートメント用にラベル付けでき、ループは 用にラベル付けできますcontinue。gotoは予約語ですが、[ 19 ]gotoは JavaScript では実装されていません。
loop1 : for ( let a = 0 ; a < 10 ; ++ a ) { if ( a === 4 ) break loop1 ; // 4 回目の試行後に停止console . log ( 'a = ' + a ); loop2 : for ( let b = 0 ; b < 10 ; ++ b ) { if ( b === 3 ) continue loop2 ; // 3 はスキップされますif ( b === 6 ) continue loop1 ; // 最初のループを続行します。「finished」は表示されませんconsole . log ( 'b = ' + b ); } // loop2 の終了console . log ( 'finished' ); } // loop1 の終了block1 : { console . log ( 'Hello' ); // 'Hello' を表示break block1 ; console . log ( 'World' ); // ここには到達しません} goto block1 ; // 解析エラー。関数とは、通常は名前が付けられる(空の場合もある)引数リストを持つブロックです。関数はローカル変数を使用できます。ユーザーがreturn文を指定せずに関数を終了した場合、undefinedが返されます。
function gcd ( number1 , number2 ) { if ( isNaN ( number1 * number2 )) throw TypeError ( "非数値引数は許可されていません。" ) ; number1 = Math.round ( number1 ) ; number2 = Math.round ( number2 ) ; let difference = number1 - number2 ; if ( difference === 0 ) return number1 ; return difference > 0 ? gcd ( number2 , difference ) : gcd ( number1 , - difference ) ; } console.log ( gcd ( 60 , 40 )) ; // 20//以下の代入式の右辺にある識別子「gcd」の後に括弧がない場合、「gcd」は関数を呼び出さずに、関数自体への参照を返します。let mygcd = gcd ; // mygcd と gcd は同じ関数を参照します。console . log ( mygcd ( 60 , 40 )); // 20関数は第一級オブジェクトであり、他の変数に代入することができます。
関数呼び出し時に指定する引数の数は、関数定義内の引数の数と必ずしも一致するとは限りません。定義内の名前付き引数で、呼び出し時に対応する引数がない場合、値はundefined になります(暗黙的に false にキャストできます)。関数内では、引数オブジェクトを介して引数にアクセスすることもできます。これにより、名前付き引数の数を超える引数も含め、インデックス (例: ) を使用してすべての引数にアクセスできます。(引数リストにはプロパティがありますが、Arrayのインスタンスではありません。.slice()、. sort()などのメソッドはありません。)arguments[0],arguments[1],...arguments[n].length
function add7 ( x , y ) { if ( ! y ) { y = 7 ; } console . log ( x + y + arguments . length ); }; add7 ( 3 ); // 11 add7 ( 3 , 4 ); // 9プリミティブ値(数値、ブール値、文字列)は値渡しされます。オブジェクトの場合は、オブジェクトへの参照が渡されます。
const obj1 = { a : 1 }; const obj2 = { b : 2 }; function foo ( p ) { p = obj2 ; // 実際のパラメータは無視しますp . b = arguments [ 1 ]; } foo ( obj1 , 3 ); // obj1 には全く影響しません。3 は追加のパラメータですconsole . log ( ` ${ obj1 . a } ${ obj2 . b } ` ); // 1 3 と出力されます関数は他の関数内で宣言でき、外側の関数のローカル変数にアクセスできます。さらに、外側の関数が終了した後もそのローカル変数を記憶することで、完全なクロージャを実現します。
let t = "Top" ; let bar , baz ; function foo () { let f = "foo var" ; bar = function () { console . log ( f ) }; baz = function ( x ) { f = x ; }; } foo (); baz ( "baz arg" ); bar (); // foo() が終了したにもかかわらず、"baz arg" ("foo var") と表示されます。console . log ( t ); // Top匿名関数とは、単に名前のない関数であり、関数表記または矢印表記のどちらでも記述できます。これらの同等の例では、匿名関数がmap関数に渡され 、配列の各要素に適用されます。[ 20 ]
[ 1 , 2 , 3 ]. map ( function ( x ) { return x * 2 ;); // [2,4,6] を返します[ 1 , 2 , 3 ]. map (( x ) => { return x * 2 ;}); // 同じ結果ジェネレータ関数は、キーワードfunctionの後に * を付けることで示され、1 つ以上のyieldステートメントを含みます。効果は、値を返して現在の状態で実行を一時停止することです。ジェネレータ関数を宣言すると、イテレータが返されます。その後のiterator.next()の呼び出しは、次のyieldまで実行を再開します。イテレータが yield ステートメントを使用せずに返された場合、それ以上の値は存在せず、イテレータのdoneプロパティはtrueに設定されます。[ 21 ]
AppleのiOSデバイスを除き、モバイルデバイスのブラウザにはジェネレーターは実装されていません。 [ 22 ]
function * generator () { yield "red" ; yield "green" ; yield "blue" ; }let iterator = generator (); let current ;while ( current = iterator.next ( ) . value ) console.log ( current ) ; // 赤、緑、青と表示console.log ( iterator.next ( ) . done ) // trueと表示JavaScript (および TypeScript) の await 演算子は、非同期関数内またはモジュールの最上位レベルでのみ使用できます。パラメータがPromiseの場合、Promise が解決されると非同期関数の実行が再開されます (Promise が拒否された場合は、通常の JavaScript例外処理で処理できるエラーがスローされます)。パラメータが Promise でない場合は、パラメータ自体がすぐに返されます。[ 23 ]
多くのライブラリは、ネイティブJavaScriptのpromiseの仕様に合致する限り、awaitでも使用できるpromiseオブジェクトを提供しています。しかし、jQueryライブラリのpromiseは、jQuery 3.0までPromises/A+と互換性がありませんでした。[ 24 ]
以下に例を示します(この[ 25 ]記事から改変)。
interface DBResponse { id : string ; rev? : string ; ok? : boolean ; }interface Document { _id : string ; _rev? : string ; [ key : string ] : any ; }interface Database { post ( doc : object ) : Promise < DBResponse > ; get ( id : string ) : Promise < Document > ; }declare const db : Database ;async function createNewDoc ( ) : Promise <Document> { const response : DBResponse = await db.post ( { } ) ; const doc : Document = await db.get ( response.id ) ; return doc ; }async function main () : Promise <void> { try { const doc : Document = await createNewDoc (); console.log ( doc ); } catch ( err : Error ) { console.error ( "ドキュメントの作成または取得中にエラーが発生しました:" , err ); } }主要();Node.jsバージョン 8 には、標準ライブラリのコールバックベースのメソッドをプロミスとして使用できるようにするユーティリティが含まれています。[ 26 ]
便宜上、型は通常、プリミティブ型とオブジェクト型に分類されます。オブジェクトは、固有の識別子(自身としか等しくない)を持ち、プロパティ名を値(プロトタイプベースのプログラミング用語では「スロット」)にマッピングする実体です。オブジェクトは連想配列やハッシュと見なすことができ、これらのデータ構造を用いて実装されることがよくあります。ただし、オブジェクトには、通常の連想配列にはないプロトタイプチェーンなどの追加機能があります。
ArrayJavaScriptには、<object> 、Boolean<object>、 <object> Date、 <object>、<object>、<object> Function、Math<object>、Number<object>、Object<object>RegExpなど、いくつかの種類の組み込みオブジェクトがありますString。その他のオブジェクトは「ホストオブジェクト」と呼ばれ、言語ではなく実行環境によって定義されます。たとえば、ブラウザでは、典型的なホストオブジェクトはDOM(ウィンドウ、フォーム、リンクなど)に属します。
オブジェクトは、コンストラクタまたはオブジェクトリテラルを使用して作成できます。コンストラクタでは、組み込みのオブジェクト関数またはカスタム関数を使用できます。コンストラクタ関数には、大文字で始まる名前が付けられるのが慣例です。
// コンストラクタconst anObject = new Object ();// オブジェクトリテラルconst objectA = {}; const objectA2 = {}; // A != A2 の場合、{} はコピーとして新しいオブジェクトを作成します。const objectB = { index1 : 'value 1' , index2 : 'value 2' };// カスタムコンストラクタ(下記参照)オブジェクトリテラルと配列リテラルを使用すると、柔軟なデータ構造を簡単に作成できます。
const myStructure = { name : { first : "Mel" , last : "Smith" }, age : 33 , hobbies : [ "chess" , "jogging" ] };これがJSONの基礎であり、JSONはJavaScriptに似た構文を用いてデータ交換を行うシンプルな表記法である。
メソッドとは、オブジェクトのプロパティ名に割り当てられた関数のことです。多くのオブジェクト指向言語とは異なり、オブジェクト関連のJavaScriptでは、関数定義とメソッド定義の区別はありません。むしろ、区別が生じるのは関数呼び出し時です。関数はメソッドとして呼び出すことができます。
メソッドとして呼び出された場合、標準のローカル変数thisは自動的に " . " の左側のオブジェクトインスタンスに設定されます。( call メソッドやapplyメソッドでは、this を明示的に設定することもできます。jQuery などの一部のパッケージでは、thisに関して特殊な処理が行われます。)
以下の例では、Foo はコンストラクタとして使用されています。コンストラクタに特別なことは何もありません。単にオブジェクトを初期化する関数です。通常のように、newキーワードと一緒に使用すると、これは新しく作成された空のオブジェクトに設定されます。
以下の例では、Fooは単にスロットに値を割り当てているだけであり、その中には関数も含まれています。したがって、異なるインスタンスに異なる関数を割り当てることができます。この例ではプロトタイピングは行われていません。
function px () { return this . prefix + "X" ; }function Foo ( yz ) { this . prefix = "a-" ; if ( yz > 0 ) { this . pyz = function () { return this . prefix + "Y" ; }; } else { this . pyz = function () { return this . prefix + "Z" ; }; } this . m1 = px ; return this ; }const foo1 = new Foo ( 1 ); const foo2 = new Foo ( 0 ); foo2 . prefix = "b-" ;console.log ( "foo1/2" + foo1.pyz ( ) + foo2.pyz ( ) ) ; // foo1/ 2 aY bZfoo1 . m3 = px ; // 評価結果ではなく、関数自体を割り当てます。つまり、px() ではありません。 const baz = { "prefix" : "c-" }; baz . m4 = px ; // オブジェクトを作成するためにコンストラクタは必要ありません。console.log ( "m1/m3/m4" + foo1.m1 ( ) + foo1.m3 ( ) + baz.m4 ( ) ) ; // m1/m3 / m4 aX aX cXfoo1.m2 (); // foo1.m2が存在しないため、例外が発生します。コンストラクタ関数は、新しく作成されたオブジェクトのスロットに値を割り当てるだけのシンプルな関数です。これらの値は、データでも他の関数でも構いません。
例:オブジェクトの操作:
function MyObject ( attributeA , attributeB ) { this . attributeA = attributeA ; this . attributeB = attributeB ; }MyObject.staticC = " blue " ; // MyObject 関数上、オブジェクトではないconsole.log ( MyObject.staticC ) ; // blueconst object = new MyObject ( 'red' , 1000 );console.log ( object.attributeA ) ; //赤console.log ( object.attributeB ) ; // 1000console.log ( object.staticC ) ; // undefined object.attributeC = new Date ( ); //新しいプロパティを追加delete object . attributeB ; // オブジェクトのプロパティを削除します// C++ とは異なり、delete は「デストラクタ」を呼び出すのではなく、 // オブジェクトのプロパティを削除します。console.log ( object.attributeB ) ; // undefinedコンストラクタ自体は、オブジェクトのプロトタイプのコンストラクタスロットで参照されます。したがって、
function Foo () {} // 'new' を使用するとプロトタイプ スロットが設定されます (たとえば、// x = new Foo() は x のプロトタイプを Foo.prototype に設定し、// Foo.prototype には Foo を指すコンストラクタ スロットがあります)。const x = new Foo (); // 上記は、const y = {}; y . constructor = Foo ; y . constructor ();とほぼ同等です。 // ただし、 x . constructor == y . constructor ; // true x instanceof Foo ; // true y instanceof Foo ; // false // y のプロトタイプは Object.prototype であり、// Foo.prototype ではありません。これは、new Foo ではなく // {} で初期化されたためです。// Foo が y のコンストラクタ スロットに設定されているにもかかわらず、// これは instanceof によって無視されます。y のプロトタイプの// コンストラクタ スロットのみが考慮されます。関数自体もオブジェクトであり、以下に示すように、C++/Javaの用語でいうところの「静的プロパティ」と同様の効果を生み出すために使用できます。(関数オブジェクトには、prototype後述の「継承」の項で説明する特別なプロパティもあります。)
オブジェクトの削除は、スクリプトエンジンが参照されなくなったオブジェクトを自動的にガベージコレクションするため、ほとんど使用されません。
JavaScript は、 Selfのようなプロトタイピングを通じて継承階層をサポートしています。
次の例では、DerivedクラスはBaseクラスを継承しています。d が Derived として作成されると、Baseの基本インスタンスへの参照がd.baseにコピーされます。
Derive にはaBaseFunctionの値が含まれないため、 aBaseFunctionにアクセスする際にaBaseFunctionから値が取得されます。これはbase.aBaseFunctionの値を変更することで明確になり、その変更はd.aBaseFunctionの値に反映されます。
一部の実装では、以下に示すように、 __proto__スロットを使用してプロトタイプに明示的にアクセスまたは設定できます。
function Base () { this . anOverride = function () { console . log ( "Base::anOverride()" ); };this.aBaseFunction = function () { console.log ( " Base ::aBaseFunction() " ) ; } ; }function Derived () { this . anOverride = function () { console . log ( "Derived::anOverride()" ); }; }const base = new Base ( ); Derived.prototype = base ; // new Derived()の前に記述する必要があります Derived.prototype.constructor = Derived ; // ` instanceof`を機能させるために必要ですconst d = new Derived (); // Derived.prototype を d インスタンスの隠しプロトタイプ スロットにコピーします。d instanceof Derived ; // true d instanceof Base ; // truebase.aBaseFunction = function () { console.log ( " Base ::aNEWBaseFunction() " ) ; } ;d.anOverride (); // Derived :: anOverride() d.aBaseFunction ( ) ; // Base :: aNEWBaseFunction ( ) console.log ( d.aBaseFunction == Derived.prototype.aBaseFunction ) ; // trueconsole.log ( d .__ proto__ == base ); // Mozillaベースの実装ではtrue、その他多くの実装ではfalse 。以下は、プロトタイプへの参照がインスタンス作成時にどのようにコピーされるかを明確に示していますが、プロトタイプへの変更は、それを参照するすべてのインスタンスに影響を与える可能性があります。
function m1 () { return "One" ; } function m2 () { return "Two" ; } function m3 () { return "Three" ; }function Base () {}Base.prototype.m = m2 ; const bar = new Base ( ); console.log ( " bar.m " + bar.m ( ) ) ; // bar.m Twofunction Top () { this . m = m3 ; } const t = new Top ();const foo = new Base ( ); Base.prototype = t ; // fooには影響なし、tへの*参照*がコピーされる。console.log( " foo.m " + foo.m ( ) ); // foo.m 2const baz = new Base (); console.log ( " baz.m " + baz.m ( )); // baz.m Threet.m = m1 ; // baz およびその他の派生クラスに影響します。console.log( " baz.m1 " + baz.m ( ) ) ; // baz.m1 1実際には、これらのテーマには多くのバリエーションがあり、それは強力な効果をもたらす一方で、混乱を招く可能性もある。
JavaScriptには、実行時エラーを処理するためのtry ... catch ... finally例外処理文が含まれています。
このtry ... catch ... finallyステートメントは、エラーまたはthrowステートメントによって発生した例外を捕捉します。構文は次のとおりです。
try { // 例外が発生する可能性のあるステートメント} catch ( errorValue ) { // 例外が発生した場合に実行されるステートメント} finally { // 例外発生後、いずれにしても実行されるステートメント}まず、tryブロック内のステートメントが実行されます。例外が発生した場合は、スクリプトの制御フローは直ちにcatchブロック内のステートメントに移り、例外はerror引数として渡されます。例外が発生しない場合は、catchブロックはスキップされます。catchブロックは、特定のエラーを処理したくない場合、throw(errorValue) をスローすることができます。
いずれにしても、finally ブロック内のステートメントは必ず実行されます。メモリは自動的にガベージコレクションされますが、これを利用してリソースのクリーンアップ(ファイルや接続のクローズなど)を手動で行うこともできます。
catch句またはfinally句のどちらかを省略できます。catch引数は必須です。
Mozillaの実装では、ECMAScript標準の拡張として、複数のcatch文を使用できます。構文はJavaで使用されるものと似ています。
try { statement ; } catch ( e if e == "InvalidNameException" ) { statement ; } catch ( e if e == "InvalidIdException" ) { statement ; } catch ( e if e == "InvalidEmailException" ) { statement ; } catch ( e ) { statement ; } finally { statement ; }ブラウザでは、onerrorイベントは例外を捕捉するためによく使用されます。
onerror = function ( errorValue , url , lineNr ) {...; return true ;};最初のパラメータを式として評価します。式には代入文を含めることができます。関数のローカル変数は式から参照できます。ただし、eval悪意のある攻撃者が任意のコードを実行できるため、重大なセキュリティリスクとなるため、使用は推奨されません。[ 27 ]
> ( function foo () { ... var x = 7 ; ... console . log ( "val " + eval ( "x + 2" )); ... })(); val 9 undefinedMicrosoftが開発したJavaScriptの上位互換言語であるTypeScriptは、 JavaScriptに以下の構文拡張機能を追加します。
構文的には、TypeScriptはJScript .NETと非常によく似ています。JScript .NETも、静的型付けと、クラス、継承、インターフェース、名前空間といった古典的なオブジェクト指向言語機能のサポートを追加した、ECMA-262言語標準のMicrosoftによる実装です。その他、JavaやC#からも影響を受けています。
TypeScriptは、コンパイル時に型チェックを可能にするために、型アノテーションによる静的型付けを提供します。
function add ( left : number , right : number ) : number { return left + right ; }numberプリミティブ型は、boolean、 、bigint、 などのすべて小文字の型を使用して注釈付けされます。これらの型は、ボックス化された対応型(、 、 など)stringとは異なり、ボックス化された型では値から直接演算を実行することはできません( とを加算することはできません)。さらに、それぞれの値に対応する と の型があります。NumberBooleanNumbernumberundefinednull
All other non-primitive types are annotated using their class name, such as Error. Arrays can be written in two different ways which are both syntactically the same: the generic-based syntax Array<T> and a shorthand with T[].
Additional built-in data types are tuples, unions, never, unknown, void, and any:
[type1, type2, ..., typeN].| symbol (string | number).never type is used when a given type should be impossible to create, which is useful for filtering mapped types.unknown type is used when dealing with data of an unpredictable shape. Unlike any, an unknown-typed variable will throw compilation errors when attempting to access properties or methods on that variable without first narrowing the type to something known. This type is often used for catching Errors, handling API responses, or user input.[29]void type is used to represent the lack of a type, e.g. from a function with no return statement.any supports the same operations as a value in JavaScript and minimal static type checking is performed,[30] which makes it suitable for weakly or dynamically typed structures. This is generally discouraged practice and should be avoided when possible.[31]Type annotations can be exported to a separate declarations file to make type information available for TypeScript scripts using types already compiled into JavaScript. Annotations can be declared for an existing JavaScript library, as has been done for Node.js and jQuery.
The TypeScript compiler makes use of type inference when types are not given. For example, the add method in the code above would be inferred as returning a number even if no return type annotation had been provided. This is based on the static types of left and right being numbers, and the compiler's knowledge that the result of adding two numbers is always a number.
If no type can be inferred because of lack of declarations (such as in a JavaScript module without types), then it defaults to the dynamic any type. Additional module types can be provided using a .d.ts declaration file using the declare module "moduleName" syntax.
When a TypeScript script gets compiled, there is an option to generate a declaration file (with the extension .d.ts) that functions as an interface to the components in the compiled JavaScript. In the process, the compiler strips away all function and method bodies and preserves only the signatures of the types that are exported. The resulting declaration file can then be used to describe the exported virtual TypeScript types of a JavaScript library or module when a third-party developer consumes it from TypeScript.
The concept of declaration files is analogous to the concept of header files found in C/C++.
declarenamespaceArithmetics{add(left:number,right:number):number;subtract(left:number,right:number):number;multiply(left:number,right:number):number;divide(left:number,right:number):number;}Type declaration files can be written by hand for existing JavaScript libraries, as has been done for jQuery and Node.js.
Large collections of declaration files for popular JavaScript libraries are hosted on GitHub in DefinitelyTyped.
TypeScript supports generic programming using a syntax similar to Java.[32] The following is an example of the identity function.[33]
functionidentity<T>(x:T):T{returnx;}Similar to Java generics, it is possible to bound a type parameter:
functionf<Textendsstring>(x:T):void{// ...}functionprop<T,KextendskeyofT>(obj:T,key:K):T[K]{returnobj[key];}Also, like C++, it is possible to have default generics parameters.
functionmakeArray<T=number>(value:T):T[]{return[value];}TypeScript uses the same annotation style for class methods and fields as for functions and variables respectively. Compared with vanilla JavaScript classes, a TypeScript class can also implement an interface through the implements keyword, use generic parameters similarly to Java, and specify public and private fields.
classPerson{publicname:string;privateage:number;privatesalary:number;constructor(name:string,age:number,salary:number){this.name=name;this.age=age;this.salary=salary;}toString():string{return`${this.name} (${this.age}) (${this.salary})`;}}Union types are supported in TypeScript.[34] The values are implicitly "tagged" with a type by the language, and may be retrieved using a typeof call for primitive values and an instanceof comparison for complex data types. Types with overlapping usage (e.g. a slice method exists on both strings and arrays, the plus operator works on both strings and numbers) don't need additional narrowing to use these features.
functionsuccessor(n:number|bigint):number|bigint{// types that support the same operations don't need narrowingreturn++n;}functiondependsOnParameter(v:string|string[]|number){// distinct types need narrowingif(vinstanceofArray){// do something}elseif(typeof(v)==="string"){// do something else}else{// has to be a number}}TypeScript adds an 'enum' data type to JavaScript.
enumCardSuit{Clubs,Diamonds,Hearts,Spades};letc:CardSuit=CardSuit.Diamonds;By default, enums number members starting at 0; this can be overridden by setting the value of the first:
enumCardSuit{Clubs=1,Diamonds,Hearts,Spades};letc:CardSuit=CardSuit.Diamonds;All the values can be set:
enumCardSuit{Clubs=1,Diamonds=2,Hearts=4,Spades=8};letc:CardSuit=CardSuit.Diamonds;TypeScript supports mapping the numeric value to its name. For example, this finds the name of the value 2:
enumCardSuit{Clubs=1,Diamonds,Hearts,Spades};letsuitName:string=CardSuit[2];alert(suitName);TypeScript distinguishes between modules and namespaces, similar to C++ modules. Both features in TypeScript support encapsulation of classes, interfaces, functions and variables into containers. Namespaces (formerly internal modules) use JavaScript immediately-invoked function expressions to encapsulate code, whereas modules (formerly external modules) use existing JavaScript library patterns (CommonJS or ES Modules).[35]
Although TypeScript does not have manual memory management, it has resource management similar to using-with-resource blocks in C# or try-with-resources blocks in Java, or C++resource acquisition is initialization, that automatically close resources without need for finally blocks. In TypeScript, to automatically close an object, it must implement a global interface Disposable, and implement a method Symbol.dispose(). This will automatically be called at the end of scope.[28]
import*asfsfrom'fs';classTempFileimplementsDisposable{#path:string;#handle:number;constructor(path:string){this.#path=path;this.#handle=fs.openSync(path,"w+");}write(data:string):void{fs.writeSync(this.#handle,data);}[Symbol.dispose]():void{fs.closeSync(this.#handle);fs.unlinkSync(this.#path);}}exportfunctiondoSomeWork(){usingfile:TempFile=newTempFile(".some_temp_file.txt");if(someCondition()){// do something here}}Omitting semicolons is not a good programming practice; you should get into the habit of inserting them.
In JavaScript, a variable can be declared after it has been used. In other words; a variable can be used before it has been declared.