From 76378dbb7394142afaa5e33ff4537a095fadcb07 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Tue, 1 Feb 2022 00:40:23 +0900 Subject: JavaScript リファレンスの基本部分を移行 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- files/ja/web/javascript/reference/about/index.html | 51 -- files/ja/web/javascript/reference/about/index.md | 51 ++ .../deprecated_and_obsolete_features/index.html | 291 --------- .../deprecated_and_obsolete_features/index.md | 291 +++++++++ .../the_legacy_iterator_protocol/index.html | 77 --- .../the_legacy_iterator_protocol/index.md | 77 +++ .../reference/iteration_protocols/index.html | 394 ------------- .../reference/iteration_protocols/index.md | 394 +++++++++++++ .../reference/lexical_grammar/index.html | 651 --------------------- .../javascript/reference/lexical_grammar/index.md | 651 +++++++++++++++++++++ .../javascript/reference/strict_mode/index.html | 368 ------------ .../web/javascript/reference/strict_mode/index.md | 368 ++++++++++++ .../transitioning_to_strict_mode/index.html | 142 ----- .../transitioning_to_strict_mode/index.md | 142 +++++ .../reference/template_literals/index.html | 271 --------- .../reference/template_literals/index.md | 271 +++++++++ 16 files changed, 2245 insertions(+), 2245 deletions(-) delete mode 100644 files/ja/web/javascript/reference/about/index.html create mode 100644 files/ja/web/javascript/reference/about/index.md delete mode 100644 files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.html create mode 100644 files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md delete mode 100644 files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.html create mode 100644 files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.md delete mode 100644 files/ja/web/javascript/reference/iteration_protocols/index.html create mode 100644 files/ja/web/javascript/reference/iteration_protocols/index.md delete mode 100644 files/ja/web/javascript/reference/lexical_grammar/index.html create mode 100644 files/ja/web/javascript/reference/lexical_grammar/index.md delete mode 100644 files/ja/web/javascript/reference/strict_mode/index.html create mode 100644 files/ja/web/javascript/reference/strict_mode/index.md delete mode 100644 files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html create mode 100644 files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.md delete mode 100644 files/ja/web/javascript/reference/template_literals/index.html create mode 100644 files/ja/web/javascript/reference/template_literals/index.md (limited to 'files/ja/web') diff --git a/files/ja/web/javascript/reference/about/index.html b/files/ja/web/javascript/reference/about/index.html deleted file mode 100644 index b9609d7c8e..0000000000 --- a/files/ja/web/javascript/reference/about/index.html +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: JavaScript リファレンスについて -slug: Web/JavaScript/Reference/About -tags: - - Guide - - JavaScript -translation_of: Web/JavaScript/Reference/About ---- -
{{JsSidebar}}
- -

この JavaScript リファレンスは、JavaScript 言語に関する事実の情報倉庫となっています。言語全体がここで詳細に記述されています。JavaScript コードを書くとき、これらのページをよく参照することになるでしょう (だからリファレンスです)。JavaScript を学んだり JavaScript の能力や機能について理解する助けがほしければ、JavaScript ガイドを見てみてください。

- -

JavaScript 言語は、ブラウザーやサーバー側スクリプトなど、より大きな環境で使用することを想定しています。このリファレンスは、大部分が環境に依存しないようにしており、ウェブブラウザー環境のみを対象としたものではありません。

- -

JavaScript の情報の所在

- -

JavaScript のコア言語機能 (ほとんどの部分は純粋な ECMAScript) の文書としては、次のものがあります。

- - - -

初めて JavaScript に触れる方は、ガイド から読み始めましょう。基本をしっかり理解してしまえば、リファレンス を使用すると、個々のオブジェクトや言語構造について詳しい情報が得られます。

- -

リファレンスの構造

- -

JavaScript リファレンスには、次の章が用意されています。

- -
-
標準組み込みオブジェクト
-
この章では、 JavaScript のすべての標準組み込みオブジェクトと、そのメソッドおよびプロパティについて説明します。
-
文と宣言
-
JavaScript アプリケーションは、適切な構文の文からなります。1つの文でも、複数の行に渡ることもあります。複数の文でも、各文をセミコロンで挟むことで1行に収めることができます。これはキーワードではありませんが、キーワードのグループです。
-
式と演算子
-
この章では、JavaScript 言語のすべての演算子、式、キーワードについて説明します。
-
関数
-
JavaScript の関数についての章。
-
クラス
-
ECMAScript 2015 で導入された JavaScript クラスについての章。
-
JavaScript の新機能
-
JavaScript のバージョン履歴についての章。
-
- -

その他の参照ページ

- - diff --git a/files/ja/web/javascript/reference/about/index.md b/files/ja/web/javascript/reference/about/index.md new file mode 100644 index 0000000000..b9609d7c8e --- /dev/null +++ b/files/ja/web/javascript/reference/about/index.md @@ -0,0 +1,51 @@ +--- +title: JavaScript リファレンスについて +slug: Web/JavaScript/Reference/About +tags: + - Guide + - JavaScript +translation_of: Web/JavaScript/Reference/About +--- +
{{JsSidebar}}
+ +

この JavaScript リファレンスは、JavaScript 言語に関する事実の情報倉庫となっています。言語全体がここで詳細に記述されています。JavaScript コードを書くとき、これらのページをよく参照することになるでしょう (だからリファレンスです)。JavaScript を学んだり JavaScript の能力や機能について理解する助けがほしければ、JavaScript ガイドを見てみてください。

+ +

JavaScript 言語は、ブラウザーやサーバー側スクリプトなど、より大きな環境で使用することを想定しています。このリファレンスは、大部分が環境に依存しないようにしており、ウェブブラウザー環境のみを対象としたものではありません。

+ +

JavaScript の情報の所在

+ +

JavaScript のコア言語機能 (ほとんどの部分は純粋な ECMAScript) の文書としては、次のものがあります。

+ + + +

初めて JavaScript に触れる方は、ガイド から読み始めましょう。基本をしっかり理解してしまえば、リファレンス を使用すると、個々のオブジェクトや言語構造について詳しい情報が得られます。

+ +

リファレンスの構造

+ +

JavaScript リファレンスには、次の章が用意されています。

+ +
+
標準組み込みオブジェクト
+
この章では、 JavaScript のすべての標準組み込みオブジェクトと、そのメソッドおよびプロパティについて説明します。
+
文と宣言
+
JavaScript アプリケーションは、適切な構文の文からなります。1つの文でも、複数の行に渡ることもあります。複数の文でも、各文をセミコロンで挟むことで1行に収めることができます。これはキーワードではありませんが、キーワードのグループです。
+
式と演算子
+
この章では、JavaScript 言語のすべての演算子、式、キーワードについて説明します。
+
関数
+
JavaScript の関数についての章。
+
クラス
+
ECMAScript 2015 で導入された JavaScript クラスについての章。
+
JavaScript の新機能
+
JavaScript のバージョン履歴についての章。
+
+ +

その他の参照ページ

+ + diff --git a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.html b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.html deleted file mode 100644 index ac58824709..0000000000 --- a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.html +++ /dev/null @@ -1,291 +0,0 @@ ---- -title: 非推奨の機能、廃止された機能 -slug: Web/JavaScript/Reference/Deprecated_and_obsolete_features -tags: - - Deprecated - - Guide - - JavaScript - - Obsolete -translation_of: Web/JavaScript/Reference/Deprecated_and_obsolete_features ---- -

{{JsSidebar("More")}}

- -

この付録リストは JavaScript で廃止予定 (まだ使用できるが削除する予定) とされた、あるいは既に廃止され使用不可となった機能の一覧です。

- -

非推奨の機能

- -

これらの非推奨機能はまだ使用可能かもしれません。しかし将来的には完全に削除されるでしょう。既にあなたがコード内でこれらを使用している場合は、代替となるコードに置き換えておく必要があります。

- -

RegExp オブジェクトのプロパティ

- -

以下のプロパティは非推奨です。これらは{{jsxref("String.replace", "文字列置換", "", 1)}}で使用しても効果がありません。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
プロパティ説明
{{jsxref("RegExp.n", "$1-$9")}}(もしあれば)括弧で囲まれた部分文字列にマッチします。 -

警告:このプロパティを使うことで、問題が起きる恐れがあります。なぜなら、ブラウザーの拡張がそれらを変更可能なためです。使用は避けるべきです。

-
{{jsxref("RegExp.input", "$_")}}input プロパティを参照してください。
{{jsxref("RegExp.multiline", "$*")}}multiline プロパティを参照してください。
{{jsxref("RegExp.lastMatch", "$&")}}lastMatch プロパティを参照してください。
{{jsxref("RegExp.lastParen", "$+")}}lastParen プロパティを参照してください。
{{jsxref("RegExp.leftContext", "$`")}}leftContext プロパティを参照してください。
{{jsxref("RegExp.rightContext", "$'")}}rightContext プロパティを参照してください。
{{jsxref("RegExp.input", "input")}}正規表現がマッチする対象となる文字列。
{{jsxref("RegExp.lastMatch", "lastMatch")}}最後にマッチした文字。
{{jsxref("RegExp.lastParen", "lastParen")}}(もしあれば)最後に括弧で囲まれた部分文字列のマッチ。
{{jsxref("RegExp.leftContext", "leftContext")}}一番最近のマッチに先行する部分文字列。
{{jsxref("RegExp.rightContext", "rightContext")}}一番最近のマッチの後に続く部分文字列。
- -

以下は、現在、RegExp インスタンスのプロパティであり、もはや、RegExp オブジェクトのプロパティではありません。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
プロパティ説明
{{jsxref("RegExp.global", "global")}}対象文字列で可能なマッチすべてに対して正規表現をテストするか、それとも、最初のマッチに対してのみテストするどうかのフラグ。
{{jsxref("RegExp.ignoreCase", "ignoreCase")}}文字列でのマッチを適用する際に、大文字と小文字の違いを無視するかどうかのフラグ。
{{jsxref("RegExp.lastIndex", "lastIndex")}}次のマッチが始まる位置。
{{jsxref("RegExp.multiline", "multiline")}}複数行に渡って文字列を検索するかどうかのフラグ。
{{jsxref("RegExp.source", "source")}}パターンのテキスト。
- -

RegExp オブジェクトのメソッド

- - - -

Function オブジェクトのプロパティ

- - - -

旧形式のジェネレーター

- - - -

イテレーター

- - - -

Object オブジェクトのメソッド

- - - -

Date オブジェクトのメソッド

- - - -

関数

- - - -

Proxy

- - - -

エスケープシーケンス

- - - -

String オブジェクトのメソッド

- - - -

廃止された機能

- -

これらは JavaScript において完全に廃止されており、現在では使用不可となっています。

- -

Object

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
プロパティ/メソッド概要
{{jsxref("Global_Objects/Object/count", "__count__")}}ユーザーがオブジェクトに直接定義した、列挙可能なプロパティの個数
{{jsxref("Global_Objects/Object/Parent", "__parent__")}}オブジェクトのコンテキストへのポインタ
{{jsxref("Global_Objects/Object/eval", "Object.prototype.eval()")}}指定したオブジェクトのコンテキスト内の JavaScript コードの文字列を評価します。
{{jsxref("Object.observe()")}}オブジェクトに対する変更を非同期に監視します。
{{jsxref("Object.unobserve()")}}observer を削除します。
{{jsxref("Object.getNotifier()")}}総合的に変更をトリガーできるオブジェクトを生成します。
- -

Function

- - - - - - - - - - - - -
プロパティ概要
{{jsxref("Global_Objects/Function/arity", "arity")}}仮引数の個数
- -

Array

- - - - - - - - - - - - - - - - -
プロパティ説明
{{jsxref("Array.observe()")}}配列に対する変更を非同期に監視します。
{{jsxref("Array.unobserve()")}}observer を削除します。
- -

Number

- - - -

ParallelArray

- - - -

- - - -

E4X

- -

詳しくは E4X をご覧ください。

- -

シャープ変数

- -

詳しくは Sharp variables in JavaScript をご覧ください。

diff --git a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md new file mode 100644 index 0000000000..ac58824709 --- /dev/null +++ b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/index.md @@ -0,0 +1,291 @@ +--- +title: 非推奨の機能、廃止された機能 +slug: Web/JavaScript/Reference/Deprecated_and_obsolete_features +tags: + - Deprecated + - Guide + - JavaScript + - Obsolete +translation_of: Web/JavaScript/Reference/Deprecated_and_obsolete_features +--- +

{{JsSidebar("More")}}

+ +

この付録リストは JavaScript で廃止予定 (まだ使用できるが削除する予定) とされた、あるいは既に廃止され使用不可となった機能の一覧です。

+ +

非推奨の機能

+ +

これらの非推奨機能はまだ使用可能かもしれません。しかし将来的には完全に削除されるでしょう。既にあなたがコード内でこれらを使用している場合は、代替となるコードに置き換えておく必要があります。

+ +

RegExp オブジェクトのプロパティ

+ +

以下のプロパティは非推奨です。これらは{{jsxref("String.replace", "文字列置換", "", 1)}}で使用しても効果がありません。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティ説明
{{jsxref("RegExp.n", "$1-$9")}}(もしあれば)括弧で囲まれた部分文字列にマッチします。 +

警告:このプロパティを使うことで、問題が起きる恐れがあります。なぜなら、ブラウザーの拡張がそれらを変更可能なためです。使用は避けるべきです。

+
{{jsxref("RegExp.input", "$_")}}input プロパティを参照してください。
{{jsxref("RegExp.multiline", "$*")}}multiline プロパティを参照してください。
{{jsxref("RegExp.lastMatch", "$&")}}lastMatch プロパティを参照してください。
{{jsxref("RegExp.lastParen", "$+")}}lastParen プロパティを参照してください。
{{jsxref("RegExp.leftContext", "$`")}}leftContext プロパティを参照してください。
{{jsxref("RegExp.rightContext", "$'")}}rightContext プロパティを参照してください。
{{jsxref("RegExp.input", "input")}}正規表現がマッチする対象となる文字列。
{{jsxref("RegExp.lastMatch", "lastMatch")}}最後にマッチした文字。
{{jsxref("RegExp.lastParen", "lastParen")}}(もしあれば)最後に括弧で囲まれた部分文字列のマッチ。
{{jsxref("RegExp.leftContext", "leftContext")}}一番最近のマッチに先行する部分文字列。
{{jsxref("RegExp.rightContext", "rightContext")}}一番最近のマッチの後に続く部分文字列。
+ +

以下は、現在、RegExp インスタンスのプロパティであり、もはや、RegExp オブジェクトのプロパティではありません。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティ説明
{{jsxref("RegExp.global", "global")}}対象文字列で可能なマッチすべてに対して正規表現をテストするか、それとも、最初のマッチに対してのみテストするどうかのフラグ。
{{jsxref("RegExp.ignoreCase", "ignoreCase")}}文字列でのマッチを適用する際に、大文字と小文字の違いを無視するかどうかのフラグ。
{{jsxref("RegExp.lastIndex", "lastIndex")}}次のマッチが始まる位置。
{{jsxref("RegExp.multiline", "multiline")}}複数行に渡って文字列を検索するかどうかのフラグ。
{{jsxref("RegExp.source", "source")}}パターンのテキスト。
+ +

RegExp オブジェクトのメソッド

+ + + +

Function オブジェクトのプロパティ

+ + + +

旧形式のジェネレーター

+ + + +

イテレーター

+ + + +

Object オブジェクトのメソッド

+ + + +

Date オブジェクトのメソッド

+ + + +

関数

+ + + +

Proxy

+ + + +

エスケープシーケンス

+ + + +

String オブジェクトのメソッド

+ + + +

廃止された機能

+ +

これらは JavaScript において完全に廃止されており、現在では使用不可となっています。

+ +

Object

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
プロパティ/メソッド概要
{{jsxref("Global_Objects/Object/count", "__count__")}}ユーザーがオブジェクトに直接定義した、列挙可能なプロパティの個数
{{jsxref("Global_Objects/Object/Parent", "__parent__")}}オブジェクトのコンテキストへのポインタ
{{jsxref("Global_Objects/Object/eval", "Object.prototype.eval()")}}指定したオブジェクトのコンテキスト内の JavaScript コードの文字列を評価します。
{{jsxref("Object.observe()")}}オブジェクトに対する変更を非同期に監視します。
{{jsxref("Object.unobserve()")}}observer を削除します。
{{jsxref("Object.getNotifier()")}}総合的に変更をトリガーできるオブジェクトを生成します。
+ +

Function

+ + + + + + + + + + + + +
プロパティ概要
{{jsxref("Global_Objects/Function/arity", "arity")}}仮引数の個数
+ +

Array

+ + + + + + + + + + + + + + + + +
プロパティ説明
{{jsxref("Array.observe()")}}配列に対する変更を非同期に監視します。
{{jsxref("Array.unobserve()")}}observer を削除します。
+ +

Number

+ + + +

ParallelArray

+ + + +

+ + + +

E4X

+ +

詳しくは E4X をご覧ください。

+ +

シャープ変数

+ +

詳しくは Sharp variables in JavaScript をご覧ください。

diff --git a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.html b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.html deleted file mode 100644 index b4148651b5..0000000000 --- a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.html +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: 古いイテレータープロトコル -slug: >- - Web/JavaScript/Reference/Deprecated_and_obsolete_features/The_legacy_Iterator_protocol -tags: - - ES2015 - - Guide - - JavaScript - - Legacy Iterator -translation_of: >- - Web/JavaScript/Reference/Deprecated_and_obsolete_features/The_legacy_Iterator_protocol ---- -
{{jsSidebar("More")}}
- -
標準外です。 古いイテレータープロトコルは SpiderMonkey 固有の機能で、 Firefox 58 で削除されました。将来に向けた使用では、 for..of ループと 反復処理プロトコル を使用することを検討してください。
- -

非推奨の Firefox 専用イテレータープロトコル

- -

Firefox version 26 以前は、標準の ES2015 のイテレータープロトコルに似た別のイテレータープロトコルを実装していました。

- -

オブジェクトが次のセマンティックスをもつ next() メソッドを実装している場合、そのオブジェクトは古いイテレーターで、反復処理の最後に {{jsxref("Global_Objects/StopIteration", "StopIteration")}} をスローします。

- - - - - - - - - - - - -
プロパティ
next引数なしの関数で、値を返します。
- -

古いイテレータープロトコルと ES2015 イテレータープロトコルとの違い

- - - -

古いプロトコルをもつ簡単な例

- -
function makeIterator(array){
-    var nextIndex = 0;
-
-    return {
-       next: function(){
-           if(nextIndex < array.length){
-               return array[nextIndex++];
-           else
-               throw new StopIteration();
-       }
-    }
-}
-
-var it = makeIterator(['yo', 'ya']);
-
-console.log(it.next()); // 'yo'
-console.log(it.next()); // 'ya'
-try{
-    console.log(it.next());
-}
-catch(e){
-    if(e instanceof StopIteration){
-         // iteration over
-    }
-}
-
- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.md b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.md new file mode 100644 index 0000000000..b4148651b5 --- /dev/null +++ b/files/ja/web/javascript/reference/deprecated_and_obsolete_features/the_legacy_iterator_protocol/index.md @@ -0,0 +1,77 @@ +--- +title: 古いイテレータープロトコル +slug: >- + Web/JavaScript/Reference/Deprecated_and_obsolete_features/The_legacy_Iterator_protocol +tags: + - ES2015 + - Guide + - JavaScript + - Legacy Iterator +translation_of: >- + Web/JavaScript/Reference/Deprecated_and_obsolete_features/The_legacy_Iterator_protocol +--- +
{{jsSidebar("More")}}
+ +
標準外です。 古いイテレータープロトコルは SpiderMonkey 固有の機能で、 Firefox 58 で削除されました。将来に向けた使用では、 for..of ループと 反復処理プロトコル を使用することを検討してください。
+ +

非推奨の Firefox 専用イテレータープロトコル

+ +

Firefox version 26 以前は、標準の ES2015 のイテレータープロトコルに似た別のイテレータープロトコルを実装していました。

+ +

オブジェクトが次のセマンティックスをもつ next() メソッドを実装している場合、そのオブジェクトは古いイテレーターで、反復処理の最後に {{jsxref("Global_Objects/StopIteration", "StopIteration")}} をスローします。

+ + + + + + + + + + + + +
プロパティ
next引数なしの関数で、値を返します。
+ +

古いイテレータープロトコルと ES2015 イテレータープロトコルとの違い

+ + + +

古いプロトコルをもつ簡単な例

+ +
function makeIterator(array){
+    var nextIndex = 0;
+
+    return {
+       next: function(){
+           if(nextIndex < array.length){
+               return array[nextIndex++];
+           else
+               throw new StopIteration();
+       }
+    }
+}
+
+var it = makeIterator(['yo', 'ya']);
+
+console.log(it.next()); // 'yo'
+console.log(it.next()); // 'ya'
+try{
+    console.log(it.next());
+}
+catch(e){
+    if(e instanceof StopIteration){
+         // iteration over
+    }
+}
+
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/iteration_protocols/index.html b/files/ja/web/javascript/reference/iteration_protocols/index.html deleted file mode 100644 index 0ea6bd0831..0000000000 --- a/files/ja/web/javascript/reference/iteration_protocols/index.html +++ /dev/null @@ -1,394 +0,0 @@ ---- -title: 反復処理プロトコル -slug: Web/JavaScript/Reference/Iteration_protocols -tags: - - ECMAScript 2015 - - Intermediate - - Iterable - - Iterator - - JavaScript - - ガイド - - プロトコル - - 中級者 - - 反復処理 - - 反復子 -translation_of: Web/JavaScript/Reference/Iteration_protocols ---- -
{{jsSidebar("More")}}
- -

ECMAScript 2015 で追加されたいくつかの機能の中で、反復処理プロトコルは新しい組み込みオブジェクトや構文ではなくプロトコルです。これらのプロトコルは以下のような単純な約束事によって、すべてのオブジェクトで実装することができます。

- -

プロトコルは2つあります。 反復可能プロトコル反復子プロトコルです。

- -

反復可能 (iterable) プロトコル

- -

反復可能プロトコルによって、 JavaScript のオブジェクトは反復動作を定義またはカスタマイズすることができます。例えば、 {{jsxref("Statements/for...of", "for...of")}} 構造の中でどの値がループに使われるかです。一部の組み込み型は既定の反復動作を持つ組み込み反復可能オブジェクトで、これには {{jsxref("Array")}} や {{jsxref("Map")}} がありますが、他の型 ({{jsxref("Object")}} など) はそうではありません。

- -

反復可能であるために、オブジェクトは @@iterator メソッドを実装する必要があります。これはつまり、オブジェクト (または、プロトタイプチェーン上のオブジェクトの一つ) が {{jsxref("Symbol.iterator")}} 定数にて利用できる @@iterator キーのプロパティを持つ必要があります。

- - - - - - - - - - - - - - -
プロパティ
[Symbol.iterator]反復子プロトコルに準拠するオブジェクトを返す、引数なしの関数。
- -

({{jsxref("Statements/for...of", "for...of")}} ループの始まりのように) オブジェクトが反復される必要があるときはいつでも、その @@iterator メソッドが引数なしで呼ばれます。そして、返される反復子は、反復される値を取得するために使用されます。

- -

なお、この引数なしの関数が呼び出されると、反復可能オブジェクト上のメソッドとして呼び出されます。従って関数の中では、 this キーワードを反復可能オブジェクトのプロパティにアクセスするために使用して、反復の間に何を提供するかを決めることができます。

- -

この関数は普通の関数、またはジェネレーター関数にすることができ、そのため呼び出されると、反復子オブジェクトが返されます。このジェネレーター関数の中では yield を使用してそれぞれの項目を提供することができます。

- -

反復子 (iterator) プロトコル

- -

反復子プロトコルは、値のシーケンス (有限でも無限でも) を生成するための標準的な方法と、すべての値が生成された場合の返値を定義します。

- -

以下の意味で next() メソッドを実装していれば、オブジェクトは反復子になります。

- - - - - - - - - - - - - - -
プロパティ
next() -

引数なしの関数で、少なくとも以下の二つのプロパティを持つオブジェクトを返します。

- -
-
done (boolean)
-
-

反復子がシーケンス内の次の値を生成できるとき false の値になります。 (これは done プロパティが指定されていない場合も同じです。)

- -

反復子が反復シーケンスを終了した場合、 true の値になります。この場合、 value は任意で反復子の返値を指定します。

-
-
value
-
反復子によって返される任意の JavaScript 値。 donetrue のときは省略することができます。
-
- -

next() メソッドは常に donevalue などの適切なプロパティを持つオブジェクトを返します。オブジェクトでない値が返された場合 (例えば falseundefined)、 {{jsxref("TypeError")}} ("iterator.next() returned a non-object value") が発生します。

-
- -
-

メモ: 特定のオブジェクトが反復子プロトコルを実装しているかどうかを反射的に知ることはできません。しかし、反復子プロトコルと反復可能プロトコルの両方を満たすオブジェクトを作成するのは簡単です (以下の例にあるように)。

- -

そうすることで、反復可能オブジェクトを期待するさまざまな構文で反復子を使用できます。したがって、反復子プロトコルを実装するには反復可能プロトコルも実装しないと、ほとんど役に立ちません。

- -
// 反復子と反復可能の両プロトコルを満たす
-let myIterator = {
-    next: function() {
-        // ...
-    },
-    [Symbol.iterator]: function() { return this; }
-};
-
-
- -

例: 反復処理プロトコルの使用

- -

{{jsxref("String")}} は組み込み反復可能オブジェクトの一例です。

- -
let someString = 'hi';
-console.log(typeof someString[Symbol.iterator]); // "function"
-
- -

String の{{jsxref("String/@@iterator", "既定の反復子", "", 1)}}は文字列のコードポイントを1つずつ返します。

- -
let iterator = someString[Symbol.iterator]();
-console.log(iterator + ''); // "[object String Iterator]"
-
-console.log(iterator.next()); // { value: "h", done: false }
-console.log(iterator.next()); // { value: "i", done: false }
-console.log(iterator.next()); // { value: undefined, done: true }
- -

一部の組み込みコンストラクター — 例えば{{jsxref("Operators/Spread_operator", "スプレッド構文", "", 1)}} — は、まったく同じ反復処理プロトコルを使用しています。

- -
console.log([...someString]); // ["h", "i"]
- -

自身の @@iterator を提供することによって反復動作を再定義できます。:

- -
// need to construct a String object explicitly to avoid auto-boxing
-let someString = new String('hi');
-
-someString[Symbol.iterator] = function () {
-  return {
-    // this is the iterator object, returning a single element (the string "bye")
-    next: function () {
-      return this._first ? {
-        value: 'bye',
-        done: (this._first = false)
-      } : {
-        done: true
-      }
-    },
-    _first: true
-  };
-};
-
- -

@@iterator を再定義することによって、反復処理プロトコルを使用する組み込みコンストラクターの動作にどれほど影響を与えるか注意してください。

- -
console.log([...someString]); // ["bye"]
-console.log(someString + ''); // "hi"
-
- -

反復可能プロトコルの例

- -

組み込み反復可能オブジェクト

- -

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}} は、すべての組み込み反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは @@iterator メソッドをもつからです。

- -

ユーザー定義の反復可能オブジェクト

- -

下記のように反復可能オブジェクトを生成できます。

- -
let myIterable = {};
-myIterable[Symbol.iterator] = function* () {
-    yield 1;
-    yield 2;
-    yield 3;
-};
-console.log([...myIterable]); // [1, 2, 3]
-
- -

反復可能オブジェクトを受け入れる組み込み API

- -

反復可能オブジェクトを受け入れる API はたくさんあります。以下はその例です。

- - - -
new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b"
-
-let myObj = {};
-
-new WeakMap([
-    [{}, 'a'],
-    [myObj, 'b'],
-    [{}, 'c']
-]).get(myObj);             // "b"
-
-new Set([1, 2, 3]).has(3); // true
-new Set('123').has('2');   // true
-
-new WeakSet(function* () {
-    yield {}
-    yield myObj
-    yield {}
-}()).has(myObj);           // true
-
- -

関連情報

- - - -

反復可能オブジェクトを期待する構文

- -

いくつかの文や式は反復可能オブジェクトを期待します。例えば、 {{jsxref("Statements/for...of", "for...of")}} ループ、{{jsxref("Operators/Spread_syntax", "スプレッド演算子", "", "1")}}、{{jsxref("Operators/yield*", "yield*")}}、{{jsxref("Operators/Destructuring_assignment", "分割代入", "", "1")}} などです。

- -
for (let value of ['a', 'b', 'c']) {
-    console.log(value);
-}
-// "a"
-// "b"
-// "c"
-
-console.log([...'abc']);   // ["a", "b", "c"]
-
-function* gen() {
-  yield* ['a', 'b', 'c'];
-}
-
-console.log(gen().next()); // { value: "a", done: false }
-
-[a, b, c] = new Set(['a', 'b', 'c']);
-console.log(a);            // "a"
-
-
- -

非整形反復可能オブジェクト

- -

反復可能オブジェクトの @@iterator メソッドが反復子オブジェクトを返さない場合、それは非整形反復可能オブジェクトと見なされます。

- -

これを使用すると、ランタイムエラーやバグの挙動をもたらす可能性があります。

- -
let nonWellFormedIterable = {}
-nonWellFormedIterable[Symbol.iterator] = () => 1
-[...nonWellFormedIterable] // TypeError: [] is not a function
-
- -

反復子の例

- -

簡単な反復子

- -
function makeIterator(array) {
-  let nextIndex = 0
-  return {
-    next: function() {
-      return nextIndex < array.length ? {
-        value: array[nextIndex++],
-        done: false
-      } : {
-        done: true
-      };
-    }
-  };
-}
-
-let it = makeIterator(['yo', 'ya']);
-
-console.log(it.next().value); // 'yo'
-console.log(it.next().value); // 'ya'
-console.log(it.next().done);  // true
-
- -

無限の反復子

- -
function idMaker() {
-  let index = 0;
-  return {
-    next: function() {
-      return {
-        value: index++,
-        done: false
-      };
-    }
-  };
-}
-
-let it = idMaker();
-
-console.log(it.next().value); // '0'
-console.log(it.next().value); // '1'
-console.log(it.next().value); // '2'
-// ...
-
- -

ジェネレーターで

- -
function* makeSimpleGenerator(array) {
-  let nextIndex = 0;
-  while (nextIndex < array.length) {
-    yield array[nextIndex++];
-  }
-}
-
-let gen = makeSimpleGenerator(['yo', 'ya']);
-
-console.log(gen.next().value); // 'yo'
-console.log(gen.next().value); // 'ya'
-console.log(gen.next().done);  // true
-
-function* idMaker() {
-  let index = 0;
-  while (true) {
-    yield index++;
-  }
-}
-
-let gen = idMaker()
-
-console.log(gen.next().value); // '0'
-console.log(gen.next().value); // '1'
-console.log(gen.next().value); // '2'
-// ...
-
- -

ES2015 クラスで

- -
class SimpleClass {
-  constructor(data) {
-    this.data = data;
-  }
-
-  [Symbol.iterator]() {
-    // Use a new index for each iterator. This makes multiple
-    // iterations over the iterable safe for non-trivial cases,
-    // such as use of break or nested looping over the same iterable.
-    let index = 0;
-
-    return {
-      next: () => {
-        if (index < this.data.length) {
-          return {value: this.data[index++], done: false}
-        } else {
-          return {done: true}
-        }
-      }
-    }
-  }
-}
-
-const simple = new SimpleClass([1,2,3,4,5]);
-
-for (const val of simple) {
-  console.log(val); // '1' '2' '3' '4' '5'
-}
-
- -

ジェネレーターは反復子か反復可能か

- -

{{jsxref("Generator", "ジェネレーターオブジェクト", "", 1)}} は、反復子でも反復可能でもあります。

- -
let aGeneratorObject = function* () {
-  yield 1;
-  yield 2;
-  yield 3;
-}();
-
-console.log(typeof aGeneratorObject.next);
-// "function", because it has a next method, so it's an iterator
-
-console.log(typeof aGeneratorObject[Symbol.iterator]);
-// "function", because it has an @@iterator method, so it's an iterable
-
-console.log(aGeneratorObject[Symbol.iterator]() === aGeneratorObject);
-// true, because its @@iterator method returns itself (an iterator), so it's an well-formed iterable
-
-console.log([...aGeneratorObject]);
-// [1, 2, 3]
-
- -

仕様書

- - - - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-iteration', 'Iteration')}}
- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/iteration_protocols/index.md b/files/ja/web/javascript/reference/iteration_protocols/index.md new file mode 100644 index 0000000000..0ea6bd0831 --- /dev/null +++ b/files/ja/web/javascript/reference/iteration_protocols/index.md @@ -0,0 +1,394 @@ +--- +title: 反復処理プロトコル +slug: Web/JavaScript/Reference/Iteration_protocols +tags: + - ECMAScript 2015 + - Intermediate + - Iterable + - Iterator + - JavaScript + - ガイド + - プロトコル + - 中級者 + - 反復処理 + - 反復子 +translation_of: Web/JavaScript/Reference/Iteration_protocols +--- +
{{jsSidebar("More")}}
+ +

ECMAScript 2015 で追加されたいくつかの機能の中で、反復処理プロトコルは新しい組み込みオブジェクトや構文ではなくプロトコルです。これらのプロトコルは以下のような単純な約束事によって、すべてのオブジェクトで実装することができます。

+ +

プロトコルは2つあります。 反復可能プロトコル反復子プロトコルです。

+ +

反復可能 (iterable) プロトコル

+ +

反復可能プロトコルによって、 JavaScript のオブジェクトは反復動作を定義またはカスタマイズすることができます。例えば、 {{jsxref("Statements/for...of", "for...of")}} 構造の中でどの値がループに使われるかです。一部の組み込み型は既定の反復動作を持つ組み込み反復可能オブジェクトで、これには {{jsxref("Array")}} や {{jsxref("Map")}} がありますが、他の型 ({{jsxref("Object")}} など) はそうではありません。

+ +

反復可能であるために、オブジェクトは @@iterator メソッドを実装する必要があります。これはつまり、オブジェクト (または、プロトタイプチェーン上のオブジェクトの一つ) が {{jsxref("Symbol.iterator")}} 定数にて利用できる @@iterator キーのプロパティを持つ必要があります。

+ + + + + + + + + + + + + + +
プロパティ
[Symbol.iterator]反復子プロトコルに準拠するオブジェクトを返す、引数なしの関数。
+ +

({{jsxref("Statements/for...of", "for...of")}} ループの始まりのように) オブジェクトが反復される必要があるときはいつでも、その @@iterator メソッドが引数なしで呼ばれます。そして、返される反復子は、反復される値を取得するために使用されます。

+ +

なお、この引数なしの関数が呼び出されると、反復可能オブジェクト上のメソッドとして呼び出されます。従って関数の中では、 this キーワードを反復可能オブジェクトのプロパティにアクセスするために使用して、反復の間に何を提供するかを決めることができます。

+ +

この関数は普通の関数、またはジェネレーター関数にすることができ、そのため呼び出されると、反復子オブジェクトが返されます。このジェネレーター関数の中では yield を使用してそれぞれの項目を提供することができます。

+ +

反復子 (iterator) プロトコル

+ +

反復子プロトコルは、値のシーケンス (有限でも無限でも) を生成するための標準的な方法と、すべての値が生成された場合の返値を定義します。

+ +

以下の意味で next() メソッドを実装していれば、オブジェクトは反復子になります。

+ + + + + + + + + + + + + + +
プロパティ
next() +

引数なしの関数で、少なくとも以下の二つのプロパティを持つオブジェクトを返します。

+ +
+
done (boolean)
+
+

反復子がシーケンス内の次の値を生成できるとき false の値になります。 (これは done プロパティが指定されていない場合も同じです。)

+ +

反復子が反復シーケンスを終了した場合、 true の値になります。この場合、 value は任意で反復子の返値を指定します。

+
+
value
+
反復子によって返される任意の JavaScript 値。 donetrue のときは省略することができます。
+
+ +

next() メソッドは常に donevalue などの適切なプロパティを持つオブジェクトを返します。オブジェクトでない値が返された場合 (例えば falseundefined)、 {{jsxref("TypeError")}} ("iterator.next() returned a non-object value") が発生します。

+
+ +
+

メモ: 特定のオブジェクトが反復子プロトコルを実装しているかどうかを反射的に知ることはできません。しかし、反復子プロトコルと反復可能プロトコルの両方を満たすオブジェクトを作成するのは簡単です (以下の例にあるように)。

+ +

そうすることで、反復可能オブジェクトを期待するさまざまな構文で反復子を使用できます。したがって、反復子プロトコルを実装するには反復可能プロトコルも実装しないと、ほとんど役に立ちません。

+ +
// 反復子と反復可能の両プロトコルを満たす
+let myIterator = {
+    next: function() {
+        // ...
+    },
+    [Symbol.iterator]: function() { return this; }
+};
+
+
+ +

例: 反復処理プロトコルの使用

+ +

{{jsxref("String")}} は組み込み反復可能オブジェクトの一例です。

+ +
let someString = 'hi';
+console.log(typeof someString[Symbol.iterator]); // "function"
+
+ +

String の{{jsxref("String/@@iterator", "既定の反復子", "", 1)}}は文字列のコードポイントを1つずつ返します。

+ +
let iterator = someString[Symbol.iterator]();
+console.log(iterator + ''); // "[object String Iterator]"
+
+console.log(iterator.next()); // { value: "h", done: false }
+console.log(iterator.next()); // { value: "i", done: false }
+console.log(iterator.next()); // { value: undefined, done: true }
+ +

一部の組み込みコンストラクター — 例えば{{jsxref("Operators/Spread_operator", "スプレッド構文", "", 1)}} — は、まったく同じ反復処理プロトコルを使用しています。

+ +
console.log([...someString]); // ["h", "i"]
+ +

自身の @@iterator を提供することによって反復動作を再定義できます。:

+ +
// need to construct a String object explicitly to avoid auto-boxing
+let someString = new String('hi');
+
+someString[Symbol.iterator] = function () {
+  return {
+    // this is the iterator object, returning a single element (the string "bye")
+    next: function () {
+      return this._first ? {
+        value: 'bye',
+        done: (this._first = false)
+      } : {
+        done: true
+      }
+    },
+    _first: true
+  };
+};
+
+ +

@@iterator を再定義することによって、反復処理プロトコルを使用する組み込みコンストラクターの動作にどれほど影響を与えるか注意してください。

+ +
console.log([...someString]); // ["bye"]
+console.log(someString + ''); // "hi"
+
+ +

反復可能プロトコルの例

+ +

組み込み反復可能オブジェクト

+ +

{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}}, {{jsxref("Set")}} は、すべての組み込み反復可能オブジェクトです。というのも、それらすべてのプロトタイプオブジェクトは @@iterator メソッドをもつからです。

+ +

ユーザー定義の反復可能オブジェクト

+ +

下記のように反復可能オブジェクトを生成できます。

+ +
let myIterable = {};
+myIterable[Symbol.iterator] = function* () {
+    yield 1;
+    yield 2;
+    yield 3;
+};
+console.log([...myIterable]); // [1, 2, 3]
+
+ +

反復可能オブジェクトを受け入れる組み込み API

+ +

反復可能オブジェクトを受け入れる API はたくさんあります。以下はその例です。

+ + + +
new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b"
+
+let myObj = {};
+
+new WeakMap([
+    [{}, 'a'],
+    [myObj, 'b'],
+    [{}, 'c']
+]).get(myObj);             // "b"
+
+new Set([1, 2, 3]).has(3); // true
+new Set('123').has('2');   // true
+
+new WeakSet(function* () {
+    yield {}
+    yield myObj
+    yield {}
+}()).has(myObj);           // true
+
+ +

関連情報

+ + + +

反復可能オブジェクトを期待する構文

+ +

いくつかの文や式は反復可能オブジェクトを期待します。例えば、 {{jsxref("Statements/for...of", "for...of")}} ループ、{{jsxref("Operators/Spread_syntax", "スプレッド演算子", "", "1")}}、{{jsxref("Operators/yield*", "yield*")}}、{{jsxref("Operators/Destructuring_assignment", "分割代入", "", "1")}} などです。

+ +
for (let value of ['a', 'b', 'c']) {
+    console.log(value);
+}
+// "a"
+// "b"
+// "c"
+
+console.log([...'abc']);   // ["a", "b", "c"]
+
+function* gen() {
+  yield* ['a', 'b', 'c'];
+}
+
+console.log(gen().next()); // { value: "a", done: false }
+
+[a, b, c] = new Set(['a', 'b', 'c']);
+console.log(a);            // "a"
+
+
+ +

非整形反復可能オブジェクト

+ +

反復可能オブジェクトの @@iterator メソッドが反復子オブジェクトを返さない場合、それは非整形反復可能オブジェクトと見なされます。

+ +

これを使用すると、ランタイムエラーやバグの挙動をもたらす可能性があります。

+ +
let nonWellFormedIterable = {}
+nonWellFormedIterable[Symbol.iterator] = () => 1
+[...nonWellFormedIterable] // TypeError: [] is not a function
+
+ +

反復子の例

+ +

簡単な反復子

+ +
function makeIterator(array) {
+  let nextIndex = 0
+  return {
+    next: function() {
+      return nextIndex < array.length ? {
+        value: array[nextIndex++],
+        done: false
+      } : {
+        done: true
+      };
+    }
+  };
+}
+
+let it = makeIterator(['yo', 'ya']);
+
+console.log(it.next().value); // 'yo'
+console.log(it.next().value); // 'ya'
+console.log(it.next().done);  // true
+
+ +

無限の反復子

+ +
function idMaker() {
+  let index = 0;
+  return {
+    next: function() {
+      return {
+        value: index++,
+        done: false
+      };
+    }
+  };
+}
+
+let it = idMaker();
+
+console.log(it.next().value); // '0'
+console.log(it.next().value); // '1'
+console.log(it.next().value); // '2'
+// ...
+
+ +

ジェネレーターで

+ +
function* makeSimpleGenerator(array) {
+  let nextIndex = 0;
+  while (nextIndex < array.length) {
+    yield array[nextIndex++];
+  }
+}
+
+let gen = makeSimpleGenerator(['yo', 'ya']);
+
+console.log(gen.next().value); // 'yo'
+console.log(gen.next().value); // 'ya'
+console.log(gen.next().done);  // true
+
+function* idMaker() {
+  let index = 0;
+  while (true) {
+    yield index++;
+  }
+}
+
+let gen = idMaker()
+
+console.log(gen.next().value); // '0'
+console.log(gen.next().value); // '1'
+console.log(gen.next().value); // '2'
+// ...
+
+ +

ES2015 クラスで

+ +
class SimpleClass {
+  constructor(data) {
+    this.data = data;
+  }
+
+  [Symbol.iterator]() {
+    // Use a new index for each iterator. This makes multiple
+    // iterations over the iterable safe for non-trivial cases,
+    // such as use of break or nested looping over the same iterable.
+    let index = 0;
+
+    return {
+      next: () => {
+        if (index < this.data.length) {
+          return {value: this.data[index++], done: false}
+        } else {
+          return {done: true}
+        }
+      }
+    }
+  }
+}
+
+const simple = new SimpleClass([1,2,3,4,5]);
+
+for (const val of simple) {
+  console.log(val); // '1' '2' '3' '4' '5'
+}
+
+ +

ジェネレーターは反復子か反復可能か

+ +

{{jsxref("Generator", "ジェネレーターオブジェクト", "", 1)}} は、反復子でも反復可能でもあります。

+ +
let aGeneratorObject = function* () {
+  yield 1;
+  yield 2;
+  yield 3;
+}();
+
+console.log(typeof aGeneratorObject.next);
+// "function", because it has a next method, so it's an iterator
+
+console.log(typeof aGeneratorObject[Symbol.iterator]);
+// "function", because it has an @@iterator method, so it's an iterable
+
+console.log(aGeneratorObject[Symbol.iterator]() === aGeneratorObject);
+// true, because its @@iterator method returns itself (an iterator), so it's an well-formed iterable
+
+console.log([...aGeneratorObject]);
+// [1, 2, 3]
+
+ +

仕様書

+ + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-iteration', 'Iteration')}}
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/lexical_grammar/index.html b/files/ja/web/javascript/reference/lexical_grammar/index.html deleted file mode 100644 index 95435185df..0000000000 --- a/files/ja/web/javascript/reference/lexical_grammar/index.html +++ /dev/null @@ -1,651 +0,0 @@ ---- -title: 字句文法 -slug: Web/JavaScript/Reference/Lexical_grammar -tags: - - JavaScript - - Keyword - - Lexical Grammar - - Literal - - キーワード - - リテラル - - 字句文法 -translation_of: Web/JavaScript/Reference/Lexical_grammar ---- -
{{JsSidebar("More")}}
- -

このページでは、 JavaScript の字句文法について説明します。 ECMAScript スクリプトのソーステキストは、左から右へスキャンされ、入力要素、すなわちトークン、制御文字、行末、コメント、{{glossary("whitespace", "ホワイトスペース")}}の並びに変換されます。 ECMAScript も、特定のキーワードとリテラルを定義しており、文を終了するにはセミコロンを自動挿入するためのルールがあります。

- -

制御文字

- -

制御文字は、視覚的表現を有していないものの、テキストの解釈を制御するために使用されます。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Unicode の書式制御文字
コードポイント名称略語説明
U+200Cゼロ幅非接合子<ZWNJ>特定の言語において、合字に接合されることを防ぐために、文字の間に配置されます。(Wikipedia).
U+200Dゼロ幅接合子<ZWJ>特定の言語において、通常は接合されない文字を、接合した形を使用して文字を表示するために文字間に配置されます。 (Wikipedia)
U+FEFFバイトオーダーマーク<BOM>スクリプトの先頭において、 Unicode を使用することと、そのテキストのバイト順をマークします。 (Wikipedia).
- -

ホワイトスペース

- -

{{glossary("whitespace", "ホワイトスペース")}}はソースのテキストの読みやすさを向上させ、トークンを互いに区別します。これらの文字は通常、コードの機能性には不要なものです。 Minification tools を使用して、転送する必要があるデータの量を削減するためにホワイトスペースを除去することがよく行われます。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ホワイトスペース文字
コードポイント名称略語説明エスケープシーケンス
U+0009文字単位のタブ<HT>水平タブ\t
U+000B行単位のタブ<VT>垂直タブ\v
U+000Cフォームフィード<FF>改ページの制御文字 (Wikipedia).\f
U+0020空白<SP>通常の空白
U+00A0ノーブレークスペース<NBSP>通常の空白だが、改行を行ってよい位置ではない
Others他の Unicode の空白文字<USP>Spaces in Unicode on Wikipedia
- -

行末文字

- -

{{glossary("Whitespace", "ホワイトスペース")}}文字に加えて、行末文字もソースのテキストの読みやすさを改善するために使用されます。しかし、行末文字は JavaScript の実行に影響を与える場合があり、禁止されている場所もいくらかあります。行末文字は自動的なセミコロンの挿入の処理にも影響を与えます。行末文字は正規表現\s クラスに一致します。

- -

以下の Unicode コードポイントのみが ECMAScript では行末文字として扱われ、他の改行文字はホワイトスペースとして扱われます (例えば、次の行、 NEL、 U+0085 はホワイトスペースと見なされます)。

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
行末文字
コードポイント名称略語説明エスケープシーケンス
U+000Aラインフィード<LF>UNIX システムでの改行文字です。\n
U+000Dキャリッジリターン<CR>コモドールと初期の Mac システムでの改行文字です。\r
U+2028ラインセパレーター<LS>Wikipedia
U+2029改段落<PS>Wikipedia
- -

コメント

- -

コメントは、ヒント、メモ、提案、警告を JavaScript のコードに追加するために使用されます。これにより、コードがより読みやすく、より理解しやすいものなります。また、コードが実行されないよう無効にするために使用することができます。これは、貴重なデバッグツールになることがあります。

- -

JavaScript には、コード内にコメントを割り当てる方法が 2 つあります。

- -

一番目の方法は // コメントです。つまり、これは同じ行にある、その後のすべてのテキストをコメントにします。例えば、

- -
function comment() {
-  // This is a one line JavaScript comment
-  console.log('Hello world!');
-}
-comment();
-
- -

二番目の方法は /* */ スタイルで、もっとずっと柔軟なものです。

- -

例えば、単一行に利用した場合は次のようになります。

- -
function comment() {
-  /* This is a one line JavaScript comment */
-  console.log('Hello world!');
-}
-comment();
- -

複数行のコメントも下記のように作成することができます。

- -
function comment() {
-  /* This comment spans multiple lines. Notice
-     that we don't need to end the comment until we're done. */
-  console.log('Hello world!');
-}
-comment();
- -

必要であれば、行の途中でコメントを使用することもできますが、これはコードが読みにくくなることがあるので注意が必要です。

- -
function comment(x) {
-  console.log('Hello ' + x /* insert the value of x */ + ' !');
-}
-comment('world');
- -

また、コードをコメントで囲むことで、コードが実行されないよう無効にすることができます。

- -
function comment() {
-  /* console.log('Hello world!'); */
-}
-comment();
- -

この場合、 console.log() の呼び出しはコメント内部にあるので、実行されることはありません。何行分のコードであっても、このようにして無効にすることができます。

- -

ハッシュバンコメント

- -

特殊な三番目のコメントの構文であるハッシュバンコメントは、 ECMAScript で標準化の途中にあるものです (Hashbang Grammar proposal を参照してください)。

- -

ハッシュバンコメントは、ちょうど単一行コメント (//) のように動作しますが、 #! で始まり、スクリプトやモジュールの絶対的な開始位置にある場合のみ有効です。 #! の前にホワイトスペースも許されないことに注意してください。このコメントは #! の後から最初の行の末尾までのすべての文字で構成されます。このコメントは1つだけが許可されます。

- -

ハッシュバンコメントは、スクリプトを実行したい特定の JavaScript インタープリターへのパスを指定します。例えば次のようになります。

- -
#!/usr/bin/env node
-
-console.log("Hello world");
-
- -
-

メモ: JavaScript のハッシュバンコメントは、ファイルを正しいインタープリターで実行するために使用される UNIX のシバンを模倣したものです。

-
- -
-

ハッシュバンコメントの前に BOM があってもブラウザーでは動作しますが、ハッシュバンのあるスクリプトで BOM を使用することは推奨されていません。 BOM は Unix/Linux でスクリプトを実行しようとすると動作しません。したがって、シェルから直接スクリプトを実行したい場合は BOM の付かない UTF-8 を使用してください。

-
- -

#! の形のコメントは JavaScript インタープリターを指定するためにだけ使用してください。他の用途ではすべて // のコメント (または複数行コメント) を使用してください。

- -

キーワード

- -

ECMAScript 2015 における予約キーワード

- - - -

今後の予約済みキーワード

- -

以下のものは、 ECMAScript の仕様によって今後のキーワードとして予約されています。これらは現時点では特別な機能を持っていませんが、将来は持つ可能性があるので、識別子として使用することはできません。

- -

以下のものは常に予約されています。

- - - -

以下のものは、 strict モードで遭遇した場合のみ予約語になります。

- - - -

以下のものは、モジュールコードで遭遇した場合のみ予約語になります。

- - - -

旧仕様にあった今後の予約キーワード

- -

以前の ECMAScript の仕様書 (ECMAScript 1 から 3 まで) では、以下のものが将来のキーワードとして予約されています。

- - - -

加えて、 null, true, false の各リテラルは、 ECMAScript では識別子として使用することができません。

- -

予約語の使用

- -

予約語は実際には (IdentifierName ではなく) 識別子にのみ適用されます。 es5.github.com/#A.1 に記載されているように、これらはすべてIdentifierName であり、ReservedWord を除外しません。

- -
a.import
-a['import']
-a = { import: 'test' }.
-
- -

一方、以下のものはIdentifier であり、IdentifierName から予約語を除外したものであるからです。識別子は、FunctionDeclaration,FunctionExpression,VariableDeclaration などのために使用されます。 Identifiers はFunctionDeclaration,FunctionExpression,VariableDeclaration などについて使用されます。IdentifierNamesMemberExpression,CallExpression などについて使用されます。

- -
function import() {} // 違反
- -

リテラル

- -

Null リテラル

- -

詳細については {{jsxref("null")}} をご覧ください。

- -
null
- -

真偽値リテラル

- -

詳細について、 {{jsxref("Boolean")}} をご覧ください。

- -
true
-false
- -

数値リテラル

- -

{{jsxref("Number")}} および {{jsxref("BigInt")}} 型が数値リテラルを使用します。

- -

10進数

- -
1234567890
-42
-
-// 先頭にゼロがあるものを使用する場合は注意してください
-0888 // 888 は10進数として解釈されます
-0777 // 8進数として解釈され、10進数では 511 です。
-
- -

なお、10進数リテラルはゼロ (0) から始め、他の10進数の数字を続けることができますが、 0 に続く数字がすべて8より小さい場合は、その数値が8進数として解釈されることに注意してください。 JavaScript では、この場合に例外が発生しませんので、 {{bug(957513)}} をご覧ください。 {{jsxref("parseInt", "parseInt()")}} についてのページもご覧ください。

- -

2進数

- -

2進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字 "B" を使用します (0b または 0B)。この構文は ECMAScript 2015 の新しい構文なので、下記のブラウザー互換性表をご覧ください。 0b の後の数字が 0 または 1 でない場合は、 {{jsxref("SyntaxError")}} が "Missing binary digits after 0b" の内容で発生します。

- -
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
-var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
-var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
- -

8進数

- -

8進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字"O" を使用します (0o または 0O)。この構文は ECMAScript 2015 の新しい構文なので、下記のブラウザー互換性表をご覧ください。 0o の後の数字が範囲 (01234567) 外の場合、 {{jsxref("SyntaxError")}} が "Missing octal digits after 0o" の内容で発生します。

- -
var n = 0O755; // 493
-var m = 0o644; // 420
-
-// ゼロだけで始めることもできます (上記の10進数についてのメモを参照)
-0755
-0644
-
- -

16進数

- -

16進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字"X" を使用します (0x または 0X)。 0x の後の数字が範囲 (0123456789ABCDEF) 外の場合、 {{jsxref("SyntaxError")}} が "Identifier starts immediately after numeric literal" の内容で発生します。

- -
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
-0x123456789ABCDEF   // 81985529216486900
-0XA                 // 10
-
- -

BigInt リテラル

- -

{{jsxref("BigInt")}} 型は JavaScript のプリミティブな数値であり、自由な精度の整数を表すことができます。 BigInt リテラルは、整数の末尾に n を追加することで作成されます。

- -
123456789123456789n     (10進数)
-0o777777777777n         (8進数)
-0x123456789ABCDEFn      ("hex" または16進数)
-0b11101001010101010101n (2進数)
-
- -

なお、先頭がゼロだけの8進数は BigInt では動作しません。

- -
// 0755n
-// SyntaxError: invalid BigInt syntax
- -

8進数の BigInt 数値では、常にゼロの後に "o" (大文字でも小文字でも) を付けて使用してください。

- -
0o755n
- -

BigInt についての詳細な情報は、 JavaScript データ構造をご覧ください。

- -

数値の区切り文字

- -

数値リテラルの可読性を高めるために、アンダースコア (_, U+005F) を区切り文字として使用することができます。

- -
// 10進数の区切り文字
-1_000_000_000_000
-1_050.95
-
-// 2進数の区切り文字
-0b1010_0001_1000_0101
-
-// 8進数の区切り文字
-0o2_2_5_6
-
-// 16進数の区切り文字
-0xA0_B0_C0
-
-// BigInt の区切り文字
-1_000_000_000_000_000_000_000n
-
- -

なお、以下の制限があります。

- -
// 連続して2つ以上のアンダースコアは許可されていません
-100__000; // SyntaxError
-
-// 数値リテラルの末尾に置くことは許可されていません
-100_; // SyntaxError
-
-// 先頭の 0 の後に使用することはできません
-0_1; // SyntaxError
-
- -

オブジェクトリテラル

- -

詳細については、 {{jsxref("Object")}} とオブジェクト初期化子をご覧ください。

- -
var o = { a: 'foo', b: 'bar', c: 42 };
-
-// ES2015 で導入された短縮表記
-var a = 'foo', b = 'bar', c = 42;
-var o = {a, b, c};
-
-// 以前の表記
-var o = { a: a, b: b, c: c };
-
- -

配列リテラル

- -

詳細については {{jsxref("Array")}} をご覧ください。

- -
[1954, 1974, 1990, 2014]
- -

文字列リテラル

- -

文字列リテラルは、単一引用符または二重引用符に囲まれた零個以上の Unicode コードポイントです。 Unicode コードポイントはエスケープシーケンスで表すこともできます。以下の引用符を閉じるコードポイントを除いて、すべてのコードポイントが文字列リテラルに現れることができます。

- - - -

proposal to make all JSON text valid ECMA-262 より以前は、 U+2028 <LS> および U+2029 <PS> は文字列リテラル内にエスケープせずに現れることができませんでした。

- -

すべてのコードポイントが、エスケープシーケンスの形で現れることができます。文字列リテラルは ECMAScript の文字列値として評価されます。これらの String の値を生成する際に、 Unicode コードポイントは UTF-16 エンコードされます。

- -
'foo'
-"bar"
- -

16進エスケープシーケンス

- -

16進エスケープシーケンスは \x に続いてちょうど2桁の16進数から成り、 0x0000 から 0x00FF までのコード単位またはコードポイントを表します。

- -
'\xA9' // "©"
-
- -

Unicode エスケープシーケンス

- -

Unicode エスケープシーケンスは \u に続いてちょうど4桁の16進数から成ります。これで UTF-16 エンコーディングのコード単位を表します。コードポイント U+0000 から U+FFFF までは、コード単位とコードポイントは等しくなります。コードポイント U+10000 から U+10FFFF までは、2つのエスケープシーケンスで2つのコード単位 (サロゲートペア) を表す必要があります。サロゲートペアはコードポイントで区別されます。

- -

See also {{jsxref("String.fromCharCode()")}} and {{jsxref("String.prototype.charCodeAt()")}}.

- -
'\u00A9' // "©" (U+A9)
- -

Unicode コードポイントエスケープ

- -

Unicode コードポイントエスケープは \u{ に続いて16進数のコードポイントが続き、 } が続きます。16進数の値は 0 から 0x10FFFF までの範囲に含まれている必要があります。 U+10000 から U+10FFFF までの範囲のコードポイントを、サロゲートペアとして表す必要はありません。コードポイントエスケープは ECMAScript 2015 (ES6) で JavaScript に追加されました。

- -

{{jsxref("String.fromCodePoint()")}} または {{jsxref("String.prototype.codePointAt()")}} もご覧ください。

- -
'\u{2F804}' // CJK COMPATIBILITY IDEOGRAPH-2F804 (U+2F804)
-
-// the same character represented as a surrogate pair
-'\uD87E\uDC04'
- -

正規表現リテラル

- -

詳細については {{jsxref("RegExp")}} を参照してください。

- -
/ab+c/g
-
-// 「空の」正規表現リテラル
-// 単一行コメントと区別するために、空のキャプチャしない
-// グループが必要です。
-/(?:)/
- -

テンプレートリテラル

- -

詳細について、template strings をご覧ください。

- -
`string text`
-
-`string text line 1
- string text line 2`
-
-`string text ${expression} string text`
-
-tag `string text ${expression} string text`
- -

自動セミコロン挿入

- -

一部の JavaScript 文はセミコロンで終わる必要があります。したがって、自動セミコロン挿入 (ASI) の影響を受けます。:

- - - -

ECMAScript 仕様書は、セミコロン挿入の3つの規則に言及しています。

- -

1. 文法上許されない位置で行末文字または "}" に遭遇したとき、セミコロンが前に挿入されます。

- -
{ 1 2 } 3
-
-// 上記の文は、 ASI によって次のように変換されます
-
-{ 1 2 ;} 3;
- -

2. トークンの入力ストリームの終末が検出され、パーサーが単一の入力ストリームを完全なプログラムとして解釈できない場合、末尾にセミコロンが挿入されます。

- -

ここで ++ は、変数 b に適用される 後置演算子としては扱われません。というのも、行末文字が b++ の間に見られるからです。

- -
a = b
-++c
-
-// 上記の文は、 ASI によって次のように変換されます
-
-a = b;
-++c;
-
- -

3. 文法上、成果が制限された文の直後に行末文字が来た時、末尾にセミコロンが挿入されます。以下の文が "no LineTerminator here" 規則を持っています。

- - - -
return
-a + b
-
-// 上記の文は、 ASI によって次のように変換されます
-
-return;
-a + b;
-
- -

仕様書

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
仕様書状態備考
{{SpecName('ESDraft', '#sec-ecmascript-language-lexical-grammar', 'Lexical Grammar')}}{{Spec2('ESDraft')}}
{{SpecName('ES6', '#sec-ecmascript-language-lexical-grammar', 'Lexical Grammar')}}{{Spec2('ES6')}}追加: 2進数リテラル と 8進数リテラル、 Unicode コードポイントエスケープ、テンプレート
{{SpecName('ES5.1', '#sec-7', 'Lexical Conventions')}}{{Spec2('ES5.1')}}
{{SpecName('ES1')}}{{Spec2("ES1")}}初回定義
- -

ブラウザーの互換性

- -

{{Compat("javascript.grammar")}}

- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/lexical_grammar/index.md b/files/ja/web/javascript/reference/lexical_grammar/index.md new file mode 100644 index 0000000000..95435185df --- /dev/null +++ b/files/ja/web/javascript/reference/lexical_grammar/index.md @@ -0,0 +1,651 @@ +--- +title: 字句文法 +slug: Web/JavaScript/Reference/Lexical_grammar +tags: + - JavaScript + - Keyword + - Lexical Grammar + - Literal + - キーワード + - リテラル + - 字句文法 +translation_of: Web/JavaScript/Reference/Lexical_grammar +--- +
{{JsSidebar("More")}}
+ +

このページでは、 JavaScript の字句文法について説明します。 ECMAScript スクリプトのソーステキストは、左から右へスキャンされ、入力要素、すなわちトークン、制御文字、行末、コメント、{{glossary("whitespace", "ホワイトスペース")}}の並びに変換されます。 ECMAScript も、特定のキーワードとリテラルを定義しており、文を終了するにはセミコロンを自動挿入するためのルールがあります。

+ +

制御文字

+ +

制御文字は、視覚的表現を有していないものの、テキストの解釈を制御するために使用されます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Unicode の書式制御文字
コードポイント名称略語説明
U+200Cゼロ幅非接合子<ZWNJ>特定の言語において、合字に接合されることを防ぐために、文字の間に配置されます。(Wikipedia).
U+200Dゼロ幅接合子<ZWJ>特定の言語において、通常は接合されない文字を、接合した形を使用して文字を表示するために文字間に配置されます。 (Wikipedia)
U+FEFFバイトオーダーマーク<BOM>スクリプトの先頭において、 Unicode を使用することと、そのテキストのバイト順をマークします。 (Wikipedia).
+ +

ホワイトスペース

+ +

{{glossary("whitespace", "ホワイトスペース")}}はソースのテキストの読みやすさを向上させ、トークンを互いに区別します。これらの文字は通常、コードの機能性には不要なものです。 Minification tools を使用して、転送する必要があるデータの量を削減するためにホワイトスペースを除去することがよく行われます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ホワイトスペース文字
コードポイント名称略語説明エスケープシーケンス
U+0009文字単位のタブ<HT>水平タブ\t
U+000B行単位のタブ<VT>垂直タブ\v
U+000Cフォームフィード<FF>改ページの制御文字 (Wikipedia).\f
U+0020空白<SP>通常の空白
U+00A0ノーブレークスペース<NBSP>通常の空白だが、改行を行ってよい位置ではない
Others他の Unicode の空白文字<USP>Spaces in Unicode on Wikipedia
+ +

行末文字

+ +

{{glossary("Whitespace", "ホワイトスペース")}}文字に加えて、行末文字もソースのテキストの読みやすさを改善するために使用されます。しかし、行末文字は JavaScript の実行に影響を与える場合があり、禁止されている場所もいくらかあります。行末文字は自動的なセミコロンの挿入の処理にも影響を与えます。行末文字は正規表現\s クラスに一致します。

+ +

以下の Unicode コードポイントのみが ECMAScript では行末文字として扱われ、他の改行文字はホワイトスペースとして扱われます (例えば、次の行、 NEL、 U+0085 はホワイトスペースと見なされます)。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
行末文字
コードポイント名称略語説明エスケープシーケンス
U+000Aラインフィード<LF>UNIX システムでの改行文字です。\n
U+000Dキャリッジリターン<CR>コモドールと初期の Mac システムでの改行文字です。\r
U+2028ラインセパレーター<LS>Wikipedia
U+2029改段落<PS>Wikipedia
+ +

コメント

+ +

コメントは、ヒント、メモ、提案、警告を JavaScript のコードに追加するために使用されます。これにより、コードがより読みやすく、より理解しやすいものなります。また、コードが実行されないよう無効にするために使用することができます。これは、貴重なデバッグツールになることがあります。

+ +

JavaScript には、コード内にコメントを割り当てる方法が 2 つあります。

+ +

一番目の方法は // コメントです。つまり、これは同じ行にある、その後のすべてのテキストをコメントにします。例えば、

+ +
function comment() {
+  // This is a one line JavaScript comment
+  console.log('Hello world!');
+}
+comment();
+
+ +

二番目の方法は /* */ スタイルで、もっとずっと柔軟なものです。

+ +

例えば、単一行に利用した場合は次のようになります。

+ +
function comment() {
+  /* This is a one line JavaScript comment */
+  console.log('Hello world!');
+}
+comment();
+ +

複数行のコメントも下記のように作成することができます。

+ +
function comment() {
+  /* This comment spans multiple lines. Notice
+     that we don't need to end the comment until we're done. */
+  console.log('Hello world!');
+}
+comment();
+ +

必要であれば、行の途中でコメントを使用することもできますが、これはコードが読みにくくなることがあるので注意が必要です。

+ +
function comment(x) {
+  console.log('Hello ' + x /* insert the value of x */ + ' !');
+}
+comment('world');
+ +

また、コードをコメントで囲むことで、コードが実行されないよう無効にすることができます。

+ +
function comment() {
+  /* console.log('Hello world!'); */
+}
+comment();
+ +

この場合、 console.log() の呼び出しはコメント内部にあるので、実行されることはありません。何行分のコードであっても、このようにして無効にすることができます。

+ +

ハッシュバンコメント

+ +

特殊な三番目のコメントの構文であるハッシュバンコメントは、 ECMAScript で標準化の途中にあるものです (Hashbang Grammar proposal を参照してください)。

+ +

ハッシュバンコメントは、ちょうど単一行コメント (//) のように動作しますが、 #! で始まり、スクリプトやモジュールの絶対的な開始位置にある場合のみ有効です。 #! の前にホワイトスペースも許されないことに注意してください。このコメントは #! の後から最初の行の末尾までのすべての文字で構成されます。このコメントは1つだけが許可されます。

+ +

ハッシュバンコメントは、スクリプトを実行したい特定の JavaScript インタープリターへのパスを指定します。例えば次のようになります。

+ +
#!/usr/bin/env node
+
+console.log("Hello world");
+
+ +
+

メモ: JavaScript のハッシュバンコメントは、ファイルを正しいインタープリターで実行するために使用される UNIX のシバンを模倣したものです。

+
+ +
+

ハッシュバンコメントの前に BOM があってもブラウザーでは動作しますが、ハッシュバンのあるスクリプトで BOM を使用することは推奨されていません。 BOM は Unix/Linux でスクリプトを実行しようとすると動作しません。したがって、シェルから直接スクリプトを実行したい場合は BOM の付かない UTF-8 を使用してください。

+
+ +

#! の形のコメントは JavaScript インタープリターを指定するためにだけ使用してください。他の用途ではすべて // のコメント (または複数行コメント) を使用してください。

+ +

キーワード

+ +

ECMAScript 2015 における予約キーワード

+ + + +

今後の予約済みキーワード

+ +

以下のものは、 ECMAScript の仕様によって今後のキーワードとして予約されています。これらは現時点では特別な機能を持っていませんが、将来は持つ可能性があるので、識別子として使用することはできません。

+ +

以下のものは常に予約されています。

+ + + +

以下のものは、 strict モードで遭遇した場合のみ予約語になります。

+ + + +

以下のものは、モジュールコードで遭遇した場合のみ予約語になります。

+ + + +

旧仕様にあった今後の予約キーワード

+ +

以前の ECMAScript の仕様書 (ECMAScript 1 から 3 まで) では、以下のものが将来のキーワードとして予約されています。

+ + + +

加えて、 null, true, false の各リテラルは、 ECMAScript では識別子として使用することができません。

+ +

予約語の使用

+ +

予約語は実際には (IdentifierName ではなく) 識別子にのみ適用されます。 es5.github.com/#A.1 に記載されているように、これらはすべてIdentifierName であり、ReservedWord を除外しません。

+ +
a.import
+a['import']
+a = { import: 'test' }.
+
+ +

一方、以下のものはIdentifier であり、IdentifierName から予約語を除外したものであるからです。識別子は、FunctionDeclaration,FunctionExpression,VariableDeclaration などのために使用されます。 Identifiers はFunctionDeclaration,FunctionExpression,VariableDeclaration などについて使用されます。IdentifierNamesMemberExpression,CallExpression などについて使用されます。

+ +
function import() {} // 違反
+ +

リテラル

+ +

Null リテラル

+ +

詳細については {{jsxref("null")}} をご覧ください。

+ +
null
+ +

真偽値リテラル

+ +

詳細について、 {{jsxref("Boolean")}} をご覧ください。

+ +
true
+false
+ +

数値リテラル

+ +

{{jsxref("Number")}} および {{jsxref("BigInt")}} 型が数値リテラルを使用します。

+ +

10進数

+ +
1234567890
+42
+
+// 先頭にゼロがあるものを使用する場合は注意してください
+0888 // 888 は10進数として解釈されます
+0777 // 8進数として解釈され、10進数では 511 です。
+
+ +

なお、10進数リテラルはゼロ (0) から始め、他の10進数の数字を続けることができますが、 0 に続く数字がすべて8より小さい場合は、その数値が8進数として解釈されることに注意してください。 JavaScript では、この場合に例外が発生しませんので、 {{bug(957513)}} をご覧ください。 {{jsxref("parseInt", "parseInt()")}} についてのページもご覧ください。

+ +

2進数

+ +

2進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字 "B" を使用します (0b または 0B)。この構文は ECMAScript 2015 の新しい構文なので、下記のブラウザー互換性表をご覧ください。 0b の後の数字が 0 または 1 でない場合は、 {{jsxref("SyntaxError")}} が "Missing binary digits after 0b" の内容で発生します。

+ +
var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
+var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
+var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607
+ +

8進数

+ +

8進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字"O" を使用します (0o または 0O)。この構文は ECMAScript 2015 の新しい構文なので、下記のブラウザー互換性表をご覧ください。 0o の後の数字が範囲 (01234567) 外の場合、 {{jsxref("SyntaxError")}} が "Missing octal digits after 0o" の内容で発生します。

+ +
var n = 0O755; // 493
+var m = 0o644; // 420
+
+// ゼロだけで始めることもできます (上記の10進数についてのメモを参照)
+0755
+0644
+
+ +

16進数

+ +

16進数の構文は、先頭のゼロに続いて小文字または大文字のラテン文字"X" を使用します (0x または 0X)。 0x の後の数字が範囲 (0123456789ABCDEF) 外の場合、 {{jsxref("SyntaxError")}} が "Identifier starts immediately after numeric literal" の内容で発生します。

+ +
0xFFFFFFFFFFFFFFFFF // 295147905179352830000
+0x123456789ABCDEF   // 81985529216486900
+0XA                 // 10
+
+ +

BigInt リテラル

+ +

{{jsxref("BigInt")}} 型は JavaScript のプリミティブな数値であり、自由な精度の整数を表すことができます。 BigInt リテラルは、整数の末尾に n を追加することで作成されます。

+ +
123456789123456789n     (10進数)
+0o777777777777n         (8進数)
+0x123456789ABCDEFn      ("hex" または16進数)
+0b11101001010101010101n (2進数)
+
+ +

なお、先頭がゼロだけの8進数は BigInt では動作しません。

+ +
// 0755n
+// SyntaxError: invalid BigInt syntax
+ +

8進数の BigInt 数値では、常にゼロの後に "o" (大文字でも小文字でも) を付けて使用してください。

+ +
0o755n
+ +

BigInt についての詳細な情報は、 JavaScript データ構造をご覧ください。

+ +

数値の区切り文字

+ +

数値リテラルの可読性を高めるために、アンダースコア (_, U+005F) を区切り文字として使用することができます。

+ +
// 10進数の区切り文字
+1_000_000_000_000
+1_050.95
+
+// 2進数の区切り文字
+0b1010_0001_1000_0101
+
+// 8進数の区切り文字
+0o2_2_5_6
+
+// 16進数の区切り文字
+0xA0_B0_C0
+
+// BigInt の区切り文字
+1_000_000_000_000_000_000_000n
+
+ +

なお、以下の制限があります。

+ +
// 連続して2つ以上のアンダースコアは許可されていません
+100__000; // SyntaxError
+
+// 数値リテラルの末尾に置くことは許可されていません
+100_; // SyntaxError
+
+// 先頭の 0 の後に使用することはできません
+0_1; // SyntaxError
+
+ +

オブジェクトリテラル

+ +

詳細については、 {{jsxref("Object")}} とオブジェクト初期化子をご覧ください。

+ +
var o = { a: 'foo', b: 'bar', c: 42 };
+
+// ES2015 で導入された短縮表記
+var a = 'foo', b = 'bar', c = 42;
+var o = {a, b, c};
+
+// 以前の表記
+var o = { a: a, b: b, c: c };
+
+ +

配列リテラル

+ +

詳細については {{jsxref("Array")}} をご覧ください。

+ +
[1954, 1974, 1990, 2014]
+ +

文字列リテラル

+ +

文字列リテラルは、単一引用符または二重引用符に囲まれた零個以上の Unicode コードポイントです。 Unicode コードポイントはエスケープシーケンスで表すこともできます。以下の引用符を閉じるコードポイントを除いて、すべてのコードポイントが文字列リテラルに現れることができます。

+ + + +

proposal to make all JSON text valid ECMA-262 より以前は、 U+2028 <LS> および U+2029 <PS> は文字列リテラル内にエスケープせずに現れることができませんでした。

+ +

すべてのコードポイントが、エスケープシーケンスの形で現れることができます。文字列リテラルは ECMAScript の文字列値として評価されます。これらの String の値を生成する際に、 Unicode コードポイントは UTF-16 エンコードされます。

+ +
'foo'
+"bar"
+ +

16進エスケープシーケンス

+ +

16進エスケープシーケンスは \x に続いてちょうど2桁の16進数から成り、 0x0000 から 0x00FF までのコード単位またはコードポイントを表します。

+ +
'\xA9' // "©"
+
+ +

Unicode エスケープシーケンス

+ +

Unicode エスケープシーケンスは \u に続いてちょうど4桁の16進数から成ります。これで UTF-16 エンコーディングのコード単位を表します。コードポイント U+0000 から U+FFFF までは、コード単位とコードポイントは等しくなります。コードポイント U+10000 から U+10FFFF までは、2つのエスケープシーケンスで2つのコード単位 (サロゲートペア) を表す必要があります。サロゲートペアはコードポイントで区別されます。

+ +

See also {{jsxref("String.fromCharCode()")}} and {{jsxref("String.prototype.charCodeAt()")}}.

+ +
'\u00A9' // "©" (U+A9)
+ +

Unicode コードポイントエスケープ

+ +

Unicode コードポイントエスケープは \u{ に続いて16進数のコードポイントが続き、 } が続きます。16進数の値は 0 から 0x10FFFF までの範囲に含まれている必要があります。 U+10000 から U+10FFFF までの範囲のコードポイントを、サロゲートペアとして表す必要はありません。コードポイントエスケープは ECMAScript 2015 (ES6) で JavaScript に追加されました。

+ +

{{jsxref("String.fromCodePoint()")}} または {{jsxref("String.prototype.codePointAt()")}} もご覧ください。

+ +
'\u{2F804}' // CJK COMPATIBILITY IDEOGRAPH-2F804 (U+2F804)
+
+// the same character represented as a surrogate pair
+'\uD87E\uDC04'
+ +

正規表現リテラル

+ +

詳細については {{jsxref("RegExp")}} を参照してください。

+ +
/ab+c/g
+
+// 「空の」正規表現リテラル
+// 単一行コメントと区別するために、空のキャプチャしない
+// グループが必要です。
+/(?:)/
+ +

テンプレートリテラル

+ +

詳細について、template strings をご覧ください。

+ +
`string text`
+
+`string text line 1
+ string text line 2`
+
+`string text ${expression} string text`
+
+tag `string text ${expression} string text`
+ +

自動セミコロン挿入

+ +

一部の JavaScript 文はセミコロンで終わる必要があります。したがって、自動セミコロン挿入 (ASI) の影響を受けます。:

+ + + +

ECMAScript 仕様書は、セミコロン挿入の3つの規則に言及しています。

+ +

1. 文法上許されない位置で行末文字または "}" に遭遇したとき、セミコロンが前に挿入されます。

+ +
{ 1 2 } 3
+
+// 上記の文は、 ASI によって次のように変換されます
+
+{ 1 2 ;} 3;
+ +

2. トークンの入力ストリームの終末が検出され、パーサーが単一の入力ストリームを完全なプログラムとして解釈できない場合、末尾にセミコロンが挿入されます。

+ +

ここで ++ は、変数 b に適用される 後置演算子としては扱われません。というのも、行末文字が b++ の間に見られるからです。

+ +
a = b
+++c
+
+// 上記の文は、 ASI によって次のように変換されます
+
+a = b;
+++c;
+
+ +

3. 文法上、成果が制限された文の直後に行末文字が来た時、末尾にセミコロンが挿入されます。以下の文が "no LineTerminator here" 規則を持っています。

+ + + +
return
+a + b
+
+// 上記の文は、 ASI によって次のように変換されます
+
+return;
+a + b;
+
+ +

仕様書

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
仕様書状態備考
{{SpecName('ESDraft', '#sec-ecmascript-language-lexical-grammar', 'Lexical Grammar')}}{{Spec2('ESDraft')}}
{{SpecName('ES6', '#sec-ecmascript-language-lexical-grammar', 'Lexical Grammar')}}{{Spec2('ES6')}}追加: 2進数リテラル と 8進数リテラル、 Unicode コードポイントエスケープ、テンプレート
{{SpecName('ES5.1', '#sec-7', 'Lexical Conventions')}}{{Spec2('ES5.1')}}
{{SpecName('ES1')}}{{Spec2("ES1")}}初回定義
+ +

ブラウザーの互換性

+ +

{{Compat("javascript.grammar")}}

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/strict_mode/index.html b/files/ja/web/javascript/reference/strict_mode/index.html deleted file mode 100644 index 5ef5aaf11e..0000000000 --- a/files/ja/web/javascript/reference/strict_mode/index.html +++ /dev/null @@ -1,368 +0,0 @@ ---- -title: Strict モード -slug: Web/JavaScript/Reference/Strict_mode -tags: - - ECMAScript 5 - - Guide - - JavaScript - - Strict Mode -translation_of: Web/JavaScript/Reference/Strict_mode ---- -
{{JsSidebar("More")}}
- -
デフォルトの厳格でないモードをSloppy モードと呼ぶのを目にすることがあるかもしれません。これは公式な用語ではありません、念のため注意してください。
- -

ECMAScript 5 で導入された Strict モードは JavaScript にオプトインすることによって幾つかの機能を制限する方法であり、それによって暗黙のうちに "Sloppy モード" からオプトアウトすることができます。Strict モードは単なるサブセットではなく、通常モードとは意図的に異なる意味を持っています。Strict モードをサポートしないブラウザーは、Strict モードをサポートするブラウザーとは異なる動作をする可能性がありますので、Strict モードに関する側面をサポートするかの機能テストを行わずに Strict モードを頼らないでください。Strict モードのコードと非 Strict モードのコードは共存できますので、スクリプトを順次 Strict モードにオプトインすることができます。

- -

Strict モードでは、通常の JavaScript の意味にいくつかの変更を加えます。

- -
    -
  1. エラーではないが落とし穴になる一部の事柄を、エラーが発生するように変更することで除去します。
  2. -
  3. JavaScript エンジンによる最適化処理を困難にする誤りを修正します。Strict モードのコードは、非 Strict モードのコードより高速に実行できる可能性があります。
  4. -
  5. 将来の ECMAScript で定義される予定の構文の使用を禁止します。
  6. -
- -

JavaScript の制限付きバリアントで機能するようにコードを変更する場合は、厳格モードへの移行を参照してください。

- -

Strict モードの呼び出し

- -

Strict モードはスクリプト全体または個別の関数に適用できます。括弧 {} で括られるブロック構文には適用できません。そのような場所に適用しようとしても何も起きません。eval コード、Function コード、イベントハンドラ属性、setTimeout コードに渡す文字列、およびこれらに似たものはスクリプト全体であり、Strict モードを呼び出すと期待どおりに動作します。

- -

スクリプトでの Strict モード

- -

スクリプト全体で Strict モードを呼び出すには、他のいかなる文よりも前に "use strict"; (または 'use strict';) という文をそのまま追加します。

- -
// スクリプト全体の Strict モード構文
-'use strict';
-var v = "こんにちは! Strict モードのスクリプト!";
-
- -

この構文には、著名なサイト悩ませた落とし穴があります。それは、競合しないスクリプトをむやみに連結できないことです。Strict モードのスクリプトと非 Strict モードのスクリプトを連結することを考えてみてください。連結後のスクリプト全体が strict になるのです! これは逆も言えます。非 Strict のスクリプトと Strict のスクリプトを連結すると非 Strict になります。もちろん、スクリプトの連結は決して理想的なものではありませんが、どうしても必要な場合は、機能ごとに Strict を有効にすることを検討してください。

- -

スクリプトの内容全体を関数でラップし、その外側の関数で Strict モードを使用するという方法もあります。これにより連結の問題が解消され、共有変数を関数スコープから明示的にエクスポートする必要があります。

- -

関数での Strict モード

- -

同様に、関数で Strict モードを呼び出すには、関数本体で他のいかなる文よりも前に "use strict"; (または 'use strict';) という文をそのまま追加します。

- -
function strict() {
-  // 関数レベルの Strict モード構文
-  'use strict';
-  function nested() { return '私もそうです!'; }
-  return "こんにちは! Strict モードの関数です!  " + nested();
-}
-function notStrict() { return "Strict モードではありません"; }
-
- -

モジュールでの Strict モード

- -

ECMAScript 2015 では、JavaScript モジュールが導入されたため、Strict モードに入るための第3 の方法が導入されました。JavaScript モジュールの内容全体が自動的に Strict モードになり、それを開始するための宣言は必要ありません。

- -
function strict() {
-    // これはモジュールなので、既定で Strict モードです
-}
-export default strict;
-
- -

Strict モードでの変更点

- -

Strict モードでは構文とランタイムの動作の両方に変更を加えます。変更点は主に以下のカテゴリに分類できます: ミスからエラー (構文エラーまたは実行時エラー) への変更、与えられた名前から特定の変数を算出する方法の単純化、eval および arguments の単純化、セキュアな JavaScript 作成の容易化、将来の ECMAScript の進化への事前対処。

- -

ミスからエラーへの変換

- -

Strict モードでは、従来は受け入れていた一部のミスをエラーに変更します。JavaScript は未熟な開発者にも易しいように設計され、またエラーとすべき操作の一部をエラーとして扱いません。これにより当面の問題を解決したことがありますが、後により大きな問題を引き起こしたこともあります。Strict モードではこれらのミスをエラーとして扱うことで、開発者は気づいて修正するようになります。

- -

第一に、Strict モードでは、偶発的にグローバル変数を作成できないようにします。通常の JavaScript では、代入文で変数名の綴りを間違えるとグローバルオブジェクトに新しいプロパティが作成され、そしてそれは動作し続けます (現在または将来問題になる可能性はありますが)。Strict モードでは、代入文で偶発的にグローバル変数を作成せずにエラーを投げます:

- -
'use strict';
-                       // グローバル変数 mistypeVariable が存在しないと仮定すると
-mistypeVariable = 17;  // この行は変数のスペルミスによる参照エラーを投げます。
-
- -

第二に、Strict モードでは、代入文で暗黙的に失敗せずに例外が発生するようにします。例えば、NaN は書き込み不可のグローバル変数です。通常のコードでは NaN に代入しても何も起きません。つまり、開発者は失敗したという通知を受けません。Strict モードでは NaN に代入すると例外が発生します。通常のコードで暗黙的に失敗する代入 (書き込み不可のプロパティへの代入、getter のみのプロパティへの代入、拡張不可 オブジェクトへの新規プロパティ割り当て) について、Strict モードでは例外が発生します:

- -
'use strict';
-
-// 書き換え不可能なグローバルへの代入
-var undefined = 5; // TypeError を投げます
-var Infinity = 5; // TypeError を投げます
-
-// 書き換え不可能なプロパティへの代入
-var obj1 = {};
-Object.defineProperty(obj1, 'x', { value: 42, writable: false });
-obj1.x = 9; // TypeError を投げます
-
-// ゲッター専用プロパティへの代入
-var obj2 = { get x() { return 17; } };
-obj2.x = 5; // TypeError を投げます
-
-// 拡張不可能なオブジェクトの新しいプロパティへの代入
-var fixed = {};
-Object.preventExtensions(fixed);
-fixed.newProp = 'ohai'; // TypeError を投げます
-
- -

第三に、Strict モードでは、削除できないプロパティを削除しようとするとエラーが発生します。(非 Strict モードでは何も起きません)

- -
'use strict';
-delete Object.prototype; // TypeError を投げます
-
- -

第四に、Strict モードでは、オブジェクトリテラル内のプロパティ名は一意であることを必須にします。通常のコードではプロパティ名が重複してもよく、最後に宣言したものがプロパティの値になります。しかし最後のものだけが有効になることから、例えばプロパティの値を変更するために最後のインスタンス以外を変更する形でコードを書き換える場合など、重複していることがバグになり得ます。Strict モードではプロパティ名の重複が構文エラーになります。

- -
-

ECMAScript 2015 では、このようなことはなくなりました。 - (bug 1041128).

-
- -
'use strict';
-var o = { p: 1, p: 2 }; // !!! 構文エラー
-
- -

第五に、Strict モードでは、関数の引数名が一意であることを必須にします。通常のコードでは、重複した引数がそれより前にある同名の引数を隠します。それら前の引数は arguments[i] を通して利用できますので、アクセスすることは可能です。しかしこのように隠すことはほとんど意味がなく、またおそらく不要なものであるため (例えば綴りの間違いをわかりにくくするかもしれません)、Strict モードでは引数名の重複を構文エラーにします。

- -
function sum(a, a, c) { // !!! 構文エラー
-  'use strict';
-  return a + a + c; // このコードが実行されると
-}
-
- -

第六に、ECMAScript 5 の Strict モードでは、8 進数表記を禁止します。8 進数表記は ECMAScript 5 の仕様に含まれていませんが、8 進数の前にゼロを付けることで、すべてのブラウザーでサポートされます: 0644 === 420 および "\045" === "%" のように。ECMAScript 2015 では、8 進数は数字の前に "0o" を付けることでサポートされます。

- -
var a = 0o10; // ES2015: 8 進数
- -

未熟な開発者は先頭のゼロに意味がないと考え、それを桁揃えのために用いることがあります。しかし、これでは数値の意味が変わってしまいます。8 進数表記が役立つことはほとんどなく、また誤って使われかねないため、Strict モードでは構文エラーになります。

- -
'use strict';
-var sum = 015 + // !!! 構文エラー
-          197 +
-          142;
-
-var sumWithOctal = 0o10 + 8;
-console.log(sumWithOctal); // 16
-
- -

第七に、ECMAScript 2015 の Strict モードでは、プリミティブ値にプロパティを設定することが禁止されます。非 Strict モードではプロパティの設定が単純に無視され、Strict モードでは {{jsxref("TypeError")}} が投げられます。

- -
(function() {
-'use strict';
-
-false.true = '';         // TypeError
-(14).sailing = 'home';   // TypeError
-'with'.you = 'far away'; // TypeError
-
-})();
- -

変数の使用の単純化

- -

Strict モードでは、コード中の変数名と特定の変数定義との対応づけ方法を単純化します。多くのコンパイラの最適化は、変数 Xあの場所に保管している と表現できることに頼ります: これは JavaScript のコードを最大限に最適化するために重要です。JavaScript ではこのようなコード内の名前と変数定義との基本的な対応づけを、実行時まで行うことができない場合があります。Strict モードではこのような事態が起こるケースを取り除くことで、コンパイラが Strict モードのコードをより最適化できるようにします。

- -

第一に、Strict モードでは、with を禁止します。with の問題点はブロック内にある名前を、渡されたオブジェクトのプロパティまたはブロックの周囲 (あるいはグローバル) のスコープへ実行時に対応づけることです: これは事前に行うことができません。Strict モードでは with をエラーとすることで、with 内にある名前の指す場所が実行時に不明になる可能性をなくします。

- -
'use strict';
-var x = 17;
-with (obj) { // !!! 構文エラー
-  // Strict モードでなかったら、これは var x になるのでしょうか、
-  // それとも obj.x になるのでしょうか?
-  // コードを実行してみないと一概には言えないので、
-  // 名前を最適化することはできません。
-  x;
-}
-
- -

with の置き換えとして、オブジェクトに短い名前の変数を割り当てて、その変数を用いて対応するプロパティにアクセスするという代案があります。

- -

第二に、Strict モードでは、eval は新しい変数を周囲のスコープに広めません。通常 eval("var x;") というコードは、変数 x を周囲の関数やグローバルスコープに広めます。これは通常 eval の呼び出しを含む関数は、引数やローカル変数を指していないすべての名前を実行時に特定の定義へ対応づけることを意味します (eval が外部の変数を隠蔽する新たな変数を生成する可能性があるためです)。Strict モードでは eval で評価されているコードでのみ使用できる変数を作成するので、変数名が外部の変数や一部のローカル変数を指しているかにかかわらず eval は影響を与えません:

- -
var x = 17;
-var evalX = eval("'use strict'; var x = 42; x;");
-console.assert(x === 17);
-console.assert(evalX === 42);
-
- -

関連して、Strict モードのコード内で eval(...) という形式で eval 関数を呼び出した場合は、コードは Strict モードとして評価されます。コードを明示的に Strict モードで呼び出してもよいですが、必須ではありません。

- -
function strict1(str) {
-  'use strict';
-  return eval(str); // str は Strict モードのコードとして扱われます。
-}
-function strict2(f, str) {
-  'use strict';
-  return f(str); // not eval(...): str は Strict モードを
-                 // 呼び出した場合のみ Strict です。
-}
-function nonstrict(str) {
-  return eval(str); // str は Strict モードを
-                    // 呼び出した場合のみ Strict です。
-}
-
-strict1("'Strict モード!'");
-strict1("'use strict'; 'Strict モード!'");
-strict2(eval, "'Strict モードではない'");
-strict2(eval, "'use strict'; 'Strict モード!'");
-nonstrict("'Strict モードではない'");
-nonstrict("'use strict'; 'Strict モード!'");
-
- -

従って、Strict モードの eval 内にある名前は、eval の結果として評価されない Strict モードのコードと同様に動作します。

- -

第三に、Strict モードでは、単純名の削除を禁止します。Strict モードでは delete name を構文エラーにします:

- -
'use strict';
-
-var x;
-delete x; // !!! 構文エラー
-
-eval('var y; delete y;'); // !!! 構文エラー
- -

eval および arguments の単純化

- -

Strict モードでは arguments および eval の奇妙さを低減します。通常のコードではどちらも不思議な動作がかなりあります: バインドの追加や削除およびバインドする値を変更するための eval や、arguments の添字つきプロパティが名前付き引数の別名になることです。Strict モードでは eval および arguments をキーワードとした手当てにより、完全な修正は将来の ECMAScript まで実現しないものの大きな進歩を遂げます。

- -

第一に、eval および arguments という名前に対して言語構文でのバインドや代入を不可にします。以下のような試みはすべて構文エラーになります:

- -
'use strict';
-eval = 17;
-arguments++;
-++eval;
-var obj = { set p(arguments) { } };
-var eval;
-try { } catch (arguments) { }
-function x(eval) { }
-function arguments() { }
-var y = function eval() { };
-var f = new Function('arguments', "'use strict'; return 17;");
-
- -

第二に、Strict モードのコードでは、内部で作成された arguments オブジェクトのプロパティがエイリアスになりません。通常のコードでは第一引数 arg を持つ関数において arg に値を設定すると arguments[0] にも設定され、また逆も同様です (引数が提供されない場合や arguments[0] が削除された場合を除きます)。Strict モードの関数での arguments オブジェクトは、関数が呼び出された当初の引数を保持します。arguments[i] は対応する名前付き引数の値を追跡せず、また名前付き引数も対応する arguments[i] の値を追跡しません。

- -
function f(a) {
-  'use strict';
-  a = 42;
-  return [a, arguments[0]];
-}
-var pair = f(17);
-console.assert(pair[0] === 42);
-console.assert(pair[1] === 17);
-
- -

第三に、arguments.callee をサポートしません。通常のコードでは、arguments.callee は取り囲んでいる関数を参照します。この使用法は脆弱です: 取り囲んでいる関数に名前をつけましょう! さらに、arguments.callee がアクセスされている場合は非インライン関数への参照を提供しなければならないため、arguments.callee はインライン関数のような最適化を実質的に妨害します。Strict モードの関数での arguments.callee は、書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

- -
'use strict';
-var f = function() { return arguments.callee; };
-f(); // TypeError が投げられます
-
- -

JavaScript の "セキュア化"

- -

Strict モードにより"セキュアな" JavaScript の記述がより簡単になります。現在、一部の Web サイトではユーザー向に対し、Web サイトの他のユーザーが実行することができる JavaScript を記述する方法を提供しています。ブラウザー上の JavaScript はユーザーの個人的な情報にアクセスできることから、そのような JavaScript は禁じられた機能へのアクセスを削除するよう、実行前に部分的に変換する必要があります。JavaScript の柔軟性は、ランタイムによる多くのチェックなしにこれを行うことを事実上不可能にします。ある言語機能は、ランタイムのチェック実行にかなりパフォーマンスのコストがかかるとして広まっています。Strict モードのいくつかの調整、そしてユーザーが投稿した JavaScript が Strict モードのコードであることや信頼できる方法で呼び出されることの要求により、ランタイムのチェックの必要性をかなり減らします。

- -

第一に、Strict モードでは、this として関数に渡された値をオブジェクトへボクシングしません。非ストリクトモードでの関数にとって this は常にオブジェクトになります。this の値は、実行時に this オブジェクト値として提供されたオブジェクトであったり、真偽値・文字列・数値などのプリミティブな値が this として呼び出した時はオブジェクトへボクシングした値、{{Glossary("Undefined", "undefined")}} または {{Glossary("Null", "null")}}this で呼び出された時はグローバルオブジェクトとなります。(特定の this を指定するために callapplybind を使用してください)。自動的なボクシングはパフォーマンス上のコストがあり、しかしブラウザーでグローバルオブジェクトを公開することは、"セキュアな" JavaScript 環境へのアクセスを提供するグローバルオブジェクトを制限する必要があるためにセキュリティ上の危険性があります。従って Strict モードの関数では、指定された this を変更せずに使用します:

- -
'use strict';
-function fun() { return this; }
-console.assert(fun() === undefined);
-console.assert(fun.call(2) === 2);
-console.assert(fun.apply(null) === null);
-console.assert(fun.call(undefined) === undefined);
-console.assert(fun.bind(true)() === true);
-
- -

つまり、とりわけブラウザーでは、Strict モード関数の中で、this を介して window オブジェクトを参照することができなくなったことを意味します。

- -

第二に、Strict モードでは、ECMAScript の一般的な実装である拡張を通して JavaScript のスタックを "渡り歩く" ことができません。拡張を用いた通常のコードでは中間にある fun 関数を呼び出すと、fun.callerfun を呼び出した直近の関数を指し、また fun.arguments はその fun の呼び出しにおける arguments を指します。これらの拡張は "セキュア化された" コードにで "特権的に" 関数や (潜在的にセキュアでない) 引数へのアクセスを許すことから、"セキュアな" JavaScript に対して問題があります。fun が Strict モードである場合は、fun.caller および fun.arguments は書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

- -
function restricted() {
-  'use strict';
-  restricted.caller;    // TypeError が投げられます
-  restricted.arguments; // TypeError が投げられます
-}
-function privilegedInvoker() {
-  return restricted();
-}
-privilegedInvoker();
-
- -

第三に、Strict モードの関数での arguments は対応する関数の呼び出し時の変数にアクセスできません。一部の過去の ECMAScript では arguments.caller を、プロパティが関数内の変数のエイリアスになるオブジェクトとして実装しました。これには関数の抽象化を通した特権的な値の隠蔽機能を破ることから、セキュリティ上の危険性があります。以上の理由から、今日のブラウザーはこれらを実装していません。それでも歴史的な機能性から、Strict モードの関数での arguments.caller は書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

- -
'use strict';
-function fun(a, b) {
-  'use strict';
-  var v = 12;
-  return arguments.caller; // TypeError が投げられます
-}
-fun(1, 2); // v を公開しません(または a または b)
-
- -

将来の ECMAScript への準備

- -

将来の ECMAScript では新たな構文を導入する予定であるため、ECMAScript 5 の Strict モードでは移行を容易にする制限事項を適用します。将来の変更点の基礎が Strict モードで禁止されていると、変更が容易になります。

- -

第一に、Strict モードでは、いくつかの識別子を予約語にします。その対象は implements, interface, let, package, private, protected, public, static, yield です。Strict モードでは、これらを変数や引数の名前として使用できません。

- -
function package(protected) { // !!!
-  'use strict';
-  var implements; // !!!
-
-  interface: // !!!
-  while (true) {
-    break interface; // !!!
-  }
-
-  function private() { } // !!!
-}
-function fun(static) { 'use strict'; } // !!!
-
-
- -

Mozilla 特有の注意事項が 2 つあります: 第一に、コードが JavaScript 1.7 以降 (chrome コード、または適切な <script type=""> を使用) かつ Strict モードである場合、let および yield にはそれらのキーワードが最初に導入されてから持っていた機能があります。しかし <script src=""><script>...</script> で読み込む Web の Strict モードのコードでは、let/yield を識別子として使用できません。第二に、ES5 では classenumexportextendsimportsuper を無条件に予約していますが、Firefox 5 以前で Mozilla はこれらを Strict モードでのみ予約します。

- -

第二に、Strict モードでは、スクリプトのトップレベルまたは関数内にない function 文を禁止します。通常のコードでは、function 文はどこにでも置くことが許されます。これは ES5 の仕様に (ES3 でさえも) 含まれていません! ブラウザーにより意味が異なり互換性がない拡張です。将来の ECMAScript では、おそらくスクリプトのトップレベルや関数内以外での funciton 文に新たな意味を定義します。Strict モードではこのような function 文を禁止する ことで将来の ECMAScript の仕様向けの "宣言を取り除きます":

- -
'use strict';
-if (true) {
-  function f() { } // !!! 構文エラー
-  f();
-}
-
-for (var i = 0; i < 5; i++) {
-  function f2() { } // !!! 構文エラー
-  f2();
-}
-
-function baz() { // kosher
-  function eit() { } // also kosher
-}
-
- -

このような function 文は基本的な ES5 の拡張であるため、禁止することは Strict モードとして適切ではありません。しかしこの動作は ECMAScript 委員会の推奨であり、それゆえブラウザーは実装するでしょう。

- -

ブラウザーでの Strict モード

- -

ブラウザーはまだ Strict モードを確実に実装していないため、無条件に依存しないでください。Strict モードは意味を変えます。それら変更点を当てにすると、Strict モードを実装していないブラウザーでミスやエラーが発生する可能性があります。Strict モードの使用時は注意を払い、また Strict モードに関する機能を実装しているかの機能テストにより Strict モードへの信頼を補ってください。最後に、Strict モードをサポートするブラウザーとしないブラウザーでのコードのテスト を行うようにしてください。Strict モードをサポートしないブラウザーでしかテスト行わない場合、Strict モードをサポートするブラウザーで問題が起きる可能性が高くなります。これは逆の場合も同じです。

- -

仕様

- - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-strict-mode-code', 'Strict Mode Code')}}
- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/strict_mode/index.md b/files/ja/web/javascript/reference/strict_mode/index.md new file mode 100644 index 0000000000..5ef5aaf11e --- /dev/null +++ b/files/ja/web/javascript/reference/strict_mode/index.md @@ -0,0 +1,368 @@ +--- +title: Strict モード +slug: Web/JavaScript/Reference/Strict_mode +tags: + - ECMAScript 5 + - Guide + - JavaScript + - Strict Mode +translation_of: Web/JavaScript/Reference/Strict_mode +--- +
{{JsSidebar("More")}}
+ +
デフォルトの厳格でないモードをSloppy モードと呼ぶのを目にすることがあるかもしれません。これは公式な用語ではありません、念のため注意してください。
+ +

ECMAScript 5 で導入された Strict モードは JavaScript にオプトインすることによって幾つかの機能を制限する方法であり、それによって暗黙のうちに "Sloppy モード" からオプトアウトすることができます。Strict モードは単なるサブセットではなく、通常モードとは意図的に異なる意味を持っています。Strict モードをサポートしないブラウザーは、Strict モードをサポートするブラウザーとは異なる動作をする可能性がありますので、Strict モードに関する側面をサポートするかの機能テストを行わずに Strict モードを頼らないでください。Strict モードのコードと非 Strict モードのコードは共存できますので、スクリプトを順次 Strict モードにオプトインすることができます。

+ +

Strict モードでは、通常の JavaScript の意味にいくつかの変更を加えます。

+ +
    +
  1. エラーではないが落とし穴になる一部の事柄を、エラーが発生するように変更することで除去します。
  2. +
  3. JavaScript エンジンによる最適化処理を困難にする誤りを修正します。Strict モードのコードは、非 Strict モードのコードより高速に実行できる可能性があります。
  4. +
  5. 将来の ECMAScript で定義される予定の構文の使用を禁止します。
  6. +
+ +

JavaScript の制限付きバリアントで機能するようにコードを変更する場合は、厳格モードへの移行を参照してください。

+ +

Strict モードの呼び出し

+ +

Strict モードはスクリプト全体または個別の関数に適用できます。括弧 {} で括られるブロック構文には適用できません。そのような場所に適用しようとしても何も起きません。eval コード、Function コード、イベントハンドラ属性、setTimeout コードに渡す文字列、およびこれらに似たものはスクリプト全体であり、Strict モードを呼び出すと期待どおりに動作します。

+ +

スクリプトでの Strict モード

+ +

スクリプト全体で Strict モードを呼び出すには、他のいかなる文よりも前に "use strict"; (または 'use strict';) という文をそのまま追加します。

+ +
// スクリプト全体の Strict モード構文
+'use strict';
+var v = "こんにちは! Strict モードのスクリプト!";
+
+ +

この構文には、著名なサイト悩ませた落とし穴があります。それは、競合しないスクリプトをむやみに連結できないことです。Strict モードのスクリプトと非 Strict モードのスクリプトを連結することを考えてみてください。連結後のスクリプト全体が strict になるのです! これは逆も言えます。非 Strict のスクリプトと Strict のスクリプトを連結すると非 Strict になります。もちろん、スクリプトの連結は決して理想的なものではありませんが、どうしても必要な場合は、機能ごとに Strict を有効にすることを検討してください。

+ +

スクリプトの内容全体を関数でラップし、その外側の関数で Strict モードを使用するという方法もあります。これにより連結の問題が解消され、共有変数を関数スコープから明示的にエクスポートする必要があります。

+ +

関数での Strict モード

+ +

同様に、関数で Strict モードを呼び出すには、関数本体で他のいかなる文よりも前に "use strict"; (または 'use strict';) という文をそのまま追加します。

+ +
function strict() {
+  // 関数レベルの Strict モード構文
+  'use strict';
+  function nested() { return '私もそうです!'; }
+  return "こんにちは! Strict モードの関数です!  " + nested();
+}
+function notStrict() { return "Strict モードではありません"; }
+
+ +

モジュールでの Strict モード

+ +

ECMAScript 2015 では、JavaScript モジュールが導入されたため、Strict モードに入るための第3 の方法が導入されました。JavaScript モジュールの内容全体が自動的に Strict モードになり、それを開始するための宣言は必要ありません。

+ +
function strict() {
+    // これはモジュールなので、既定で Strict モードです
+}
+export default strict;
+
+ +

Strict モードでの変更点

+ +

Strict モードでは構文とランタイムの動作の両方に変更を加えます。変更点は主に以下のカテゴリに分類できます: ミスからエラー (構文エラーまたは実行時エラー) への変更、与えられた名前から特定の変数を算出する方法の単純化、eval および arguments の単純化、セキュアな JavaScript 作成の容易化、将来の ECMAScript の進化への事前対処。

+ +

ミスからエラーへの変換

+ +

Strict モードでは、従来は受け入れていた一部のミスをエラーに変更します。JavaScript は未熟な開発者にも易しいように設計され、またエラーとすべき操作の一部をエラーとして扱いません。これにより当面の問題を解決したことがありますが、後により大きな問題を引き起こしたこともあります。Strict モードではこれらのミスをエラーとして扱うことで、開発者は気づいて修正するようになります。

+ +

第一に、Strict モードでは、偶発的にグローバル変数を作成できないようにします。通常の JavaScript では、代入文で変数名の綴りを間違えるとグローバルオブジェクトに新しいプロパティが作成され、そしてそれは動作し続けます (現在または将来問題になる可能性はありますが)。Strict モードでは、代入文で偶発的にグローバル変数を作成せずにエラーを投げます:

+ +
'use strict';
+                       // グローバル変数 mistypeVariable が存在しないと仮定すると
+mistypeVariable = 17;  // この行は変数のスペルミスによる参照エラーを投げます。
+
+ +

第二に、Strict モードでは、代入文で暗黙的に失敗せずに例外が発生するようにします。例えば、NaN は書き込み不可のグローバル変数です。通常のコードでは NaN に代入しても何も起きません。つまり、開発者は失敗したという通知を受けません。Strict モードでは NaN に代入すると例外が発生します。通常のコードで暗黙的に失敗する代入 (書き込み不可のプロパティへの代入、getter のみのプロパティへの代入、拡張不可 オブジェクトへの新規プロパティ割り当て) について、Strict モードでは例外が発生します:

+ +
'use strict';
+
+// 書き換え不可能なグローバルへの代入
+var undefined = 5; // TypeError を投げます
+var Infinity = 5; // TypeError を投げます
+
+// 書き換え不可能なプロパティへの代入
+var obj1 = {};
+Object.defineProperty(obj1, 'x', { value: 42, writable: false });
+obj1.x = 9; // TypeError を投げます
+
+// ゲッター専用プロパティへの代入
+var obj2 = { get x() { return 17; } };
+obj2.x = 5; // TypeError を投げます
+
+// 拡張不可能なオブジェクトの新しいプロパティへの代入
+var fixed = {};
+Object.preventExtensions(fixed);
+fixed.newProp = 'ohai'; // TypeError を投げます
+
+ +

第三に、Strict モードでは、削除できないプロパティを削除しようとするとエラーが発生します。(非 Strict モードでは何も起きません)

+ +
'use strict';
+delete Object.prototype; // TypeError を投げます
+
+ +

第四に、Strict モードでは、オブジェクトリテラル内のプロパティ名は一意であることを必須にします。通常のコードではプロパティ名が重複してもよく、最後に宣言したものがプロパティの値になります。しかし最後のものだけが有効になることから、例えばプロパティの値を変更するために最後のインスタンス以外を変更する形でコードを書き換える場合など、重複していることがバグになり得ます。Strict モードではプロパティ名の重複が構文エラーになります。

+ +
+

ECMAScript 2015 では、このようなことはなくなりました。 + (bug 1041128).

+
+ +
'use strict';
+var o = { p: 1, p: 2 }; // !!! 構文エラー
+
+ +

第五に、Strict モードでは、関数の引数名が一意であることを必須にします。通常のコードでは、重複した引数がそれより前にある同名の引数を隠します。それら前の引数は arguments[i] を通して利用できますので、アクセスすることは可能です。しかしこのように隠すことはほとんど意味がなく、またおそらく不要なものであるため (例えば綴りの間違いをわかりにくくするかもしれません)、Strict モードでは引数名の重複を構文エラーにします。

+ +
function sum(a, a, c) { // !!! 構文エラー
+  'use strict';
+  return a + a + c; // このコードが実行されると
+}
+
+ +

第六に、ECMAScript 5 の Strict モードでは、8 進数表記を禁止します。8 進数表記は ECMAScript 5 の仕様に含まれていませんが、8 進数の前にゼロを付けることで、すべてのブラウザーでサポートされます: 0644 === 420 および "\045" === "%" のように。ECMAScript 2015 では、8 進数は数字の前に "0o" を付けることでサポートされます。

+ +
var a = 0o10; // ES2015: 8 進数
+ +

未熟な開発者は先頭のゼロに意味がないと考え、それを桁揃えのために用いることがあります。しかし、これでは数値の意味が変わってしまいます。8 進数表記が役立つことはほとんどなく、また誤って使われかねないため、Strict モードでは構文エラーになります。

+ +
'use strict';
+var sum = 015 + // !!! 構文エラー
+          197 +
+          142;
+
+var sumWithOctal = 0o10 + 8;
+console.log(sumWithOctal); // 16
+
+ +

第七に、ECMAScript 2015 の Strict モードでは、プリミティブ値にプロパティを設定することが禁止されます。非 Strict モードではプロパティの設定が単純に無視され、Strict モードでは {{jsxref("TypeError")}} が投げられます。

+ +
(function() {
+'use strict';
+
+false.true = '';         // TypeError
+(14).sailing = 'home';   // TypeError
+'with'.you = 'far away'; // TypeError
+
+})();
+ +

変数の使用の単純化

+ +

Strict モードでは、コード中の変数名と特定の変数定義との対応づけ方法を単純化します。多くのコンパイラの最適化は、変数 Xあの場所に保管している と表現できることに頼ります: これは JavaScript のコードを最大限に最適化するために重要です。JavaScript ではこのようなコード内の名前と変数定義との基本的な対応づけを、実行時まで行うことができない場合があります。Strict モードではこのような事態が起こるケースを取り除くことで、コンパイラが Strict モードのコードをより最適化できるようにします。

+ +

第一に、Strict モードでは、with を禁止します。with の問題点はブロック内にある名前を、渡されたオブジェクトのプロパティまたはブロックの周囲 (あるいはグローバル) のスコープへ実行時に対応づけることです: これは事前に行うことができません。Strict モードでは with をエラーとすることで、with 内にある名前の指す場所が実行時に不明になる可能性をなくします。

+ +
'use strict';
+var x = 17;
+with (obj) { // !!! 構文エラー
+  // Strict モードでなかったら、これは var x になるのでしょうか、
+  // それとも obj.x になるのでしょうか?
+  // コードを実行してみないと一概には言えないので、
+  // 名前を最適化することはできません。
+  x;
+}
+
+ +

with の置き換えとして、オブジェクトに短い名前の変数を割り当てて、その変数を用いて対応するプロパティにアクセスするという代案があります。

+ +

第二に、Strict モードでは、eval は新しい変数を周囲のスコープに広めません。通常 eval("var x;") というコードは、変数 x を周囲の関数やグローバルスコープに広めます。これは通常 eval の呼び出しを含む関数は、引数やローカル変数を指していないすべての名前を実行時に特定の定義へ対応づけることを意味します (eval が外部の変数を隠蔽する新たな変数を生成する可能性があるためです)。Strict モードでは eval で評価されているコードでのみ使用できる変数を作成するので、変数名が外部の変数や一部のローカル変数を指しているかにかかわらず eval は影響を与えません:

+ +
var x = 17;
+var evalX = eval("'use strict'; var x = 42; x;");
+console.assert(x === 17);
+console.assert(evalX === 42);
+
+ +

関連して、Strict モードのコード内で eval(...) という形式で eval 関数を呼び出した場合は、コードは Strict モードとして評価されます。コードを明示的に Strict モードで呼び出してもよいですが、必須ではありません。

+ +
function strict1(str) {
+  'use strict';
+  return eval(str); // str は Strict モードのコードとして扱われます。
+}
+function strict2(f, str) {
+  'use strict';
+  return f(str); // not eval(...): str は Strict モードを
+                 // 呼び出した場合のみ Strict です。
+}
+function nonstrict(str) {
+  return eval(str); // str は Strict モードを
+                    // 呼び出した場合のみ Strict です。
+}
+
+strict1("'Strict モード!'");
+strict1("'use strict'; 'Strict モード!'");
+strict2(eval, "'Strict モードではない'");
+strict2(eval, "'use strict'; 'Strict モード!'");
+nonstrict("'Strict モードではない'");
+nonstrict("'use strict'; 'Strict モード!'");
+
+ +

従って、Strict モードの eval 内にある名前は、eval の結果として評価されない Strict モードのコードと同様に動作します。

+ +

第三に、Strict モードでは、単純名の削除を禁止します。Strict モードでは delete name を構文エラーにします:

+ +
'use strict';
+
+var x;
+delete x; // !!! 構文エラー
+
+eval('var y; delete y;'); // !!! 構文エラー
+ +

eval および arguments の単純化

+ +

Strict モードでは arguments および eval の奇妙さを低減します。通常のコードではどちらも不思議な動作がかなりあります: バインドの追加や削除およびバインドする値を変更するための eval や、arguments の添字つきプロパティが名前付き引数の別名になることです。Strict モードでは eval および arguments をキーワードとした手当てにより、完全な修正は将来の ECMAScript まで実現しないものの大きな進歩を遂げます。

+ +

第一に、eval および arguments という名前に対して言語構文でのバインドや代入を不可にします。以下のような試みはすべて構文エラーになります:

+ +
'use strict';
+eval = 17;
+arguments++;
+++eval;
+var obj = { set p(arguments) { } };
+var eval;
+try { } catch (arguments) { }
+function x(eval) { }
+function arguments() { }
+var y = function eval() { };
+var f = new Function('arguments', "'use strict'; return 17;");
+
+ +

第二に、Strict モードのコードでは、内部で作成された arguments オブジェクトのプロパティがエイリアスになりません。通常のコードでは第一引数 arg を持つ関数において arg に値を設定すると arguments[0] にも設定され、また逆も同様です (引数が提供されない場合や arguments[0] が削除された場合を除きます)。Strict モードの関数での arguments オブジェクトは、関数が呼び出された当初の引数を保持します。arguments[i] は対応する名前付き引数の値を追跡せず、また名前付き引数も対応する arguments[i] の値を追跡しません。

+ +
function f(a) {
+  'use strict';
+  a = 42;
+  return [a, arguments[0]];
+}
+var pair = f(17);
+console.assert(pair[0] === 42);
+console.assert(pair[1] === 17);
+
+ +

第三に、arguments.callee をサポートしません。通常のコードでは、arguments.callee は取り囲んでいる関数を参照します。この使用法は脆弱です: 取り囲んでいる関数に名前をつけましょう! さらに、arguments.callee がアクセスされている場合は非インライン関数への参照を提供しなければならないため、arguments.callee はインライン関数のような最適化を実質的に妨害します。Strict モードの関数での arguments.callee は、書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

+ +
'use strict';
+var f = function() { return arguments.callee; };
+f(); // TypeError が投げられます
+
+ +

JavaScript の "セキュア化"

+ +

Strict モードにより"セキュアな" JavaScript の記述がより簡単になります。現在、一部の Web サイトではユーザー向に対し、Web サイトの他のユーザーが実行することができる JavaScript を記述する方法を提供しています。ブラウザー上の JavaScript はユーザーの個人的な情報にアクセスできることから、そのような JavaScript は禁じられた機能へのアクセスを削除するよう、実行前に部分的に変換する必要があります。JavaScript の柔軟性は、ランタイムによる多くのチェックなしにこれを行うことを事実上不可能にします。ある言語機能は、ランタイムのチェック実行にかなりパフォーマンスのコストがかかるとして広まっています。Strict モードのいくつかの調整、そしてユーザーが投稿した JavaScript が Strict モードのコードであることや信頼できる方法で呼び出されることの要求により、ランタイムのチェックの必要性をかなり減らします。

+ +

第一に、Strict モードでは、this として関数に渡された値をオブジェクトへボクシングしません。非ストリクトモードでの関数にとって this は常にオブジェクトになります。this の値は、実行時に this オブジェクト値として提供されたオブジェクトであったり、真偽値・文字列・数値などのプリミティブな値が this として呼び出した時はオブジェクトへボクシングした値、{{Glossary("Undefined", "undefined")}} または {{Glossary("Null", "null")}}this で呼び出された時はグローバルオブジェクトとなります。(特定の this を指定するために callapplybind を使用してください)。自動的なボクシングはパフォーマンス上のコストがあり、しかしブラウザーでグローバルオブジェクトを公開することは、"セキュアな" JavaScript 環境へのアクセスを提供するグローバルオブジェクトを制限する必要があるためにセキュリティ上の危険性があります。従って Strict モードの関数では、指定された this を変更せずに使用します:

+ +
'use strict';
+function fun() { return this; }
+console.assert(fun() === undefined);
+console.assert(fun.call(2) === 2);
+console.assert(fun.apply(null) === null);
+console.assert(fun.call(undefined) === undefined);
+console.assert(fun.bind(true)() === true);
+
+ +

つまり、とりわけブラウザーでは、Strict モード関数の中で、this を介して window オブジェクトを参照することができなくなったことを意味します。

+ +

第二に、Strict モードでは、ECMAScript の一般的な実装である拡張を通して JavaScript のスタックを "渡り歩く" ことができません。拡張を用いた通常のコードでは中間にある fun 関数を呼び出すと、fun.callerfun を呼び出した直近の関数を指し、また fun.arguments はその fun の呼び出しにおける arguments を指します。これらの拡張は "セキュア化された" コードにで "特権的に" 関数や (潜在的にセキュアでない) 引数へのアクセスを許すことから、"セキュアな" JavaScript に対して問題があります。fun が Strict モードである場合は、fun.caller および fun.arguments は書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

+ +
function restricted() {
+  'use strict';
+  restricted.caller;    // TypeError が投げられます
+  restricted.arguments; // TypeError が投げられます
+}
+function privilegedInvoker() {
+  return restricted();
+}
+privilegedInvoker();
+
+ +

第三に、Strict モードの関数での arguments は対応する関数の呼び出し時の変数にアクセスできません。一部の過去の ECMAScript では arguments.caller を、プロパティが関数内の変数のエイリアスになるオブジェクトとして実装しました。これには関数の抽象化を通した特権的な値の隠蔽機能を破ることから、セキュリティ上の危険性があります。以上の理由から、今日のブラウザーはこれらを実装していません。それでも歴史的な機能性から、Strict モードの関数での arguments.caller は書き込みや読み出し時にエラーが発生する、削除不可のプロパティです:

+ +
'use strict';
+function fun(a, b) {
+  'use strict';
+  var v = 12;
+  return arguments.caller; // TypeError が投げられます
+}
+fun(1, 2); // v を公開しません(または a または b)
+
+ +

将来の ECMAScript への準備

+ +

将来の ECMAScript では新たな構文を導入する予定であるため、ECMAScript 5 の Strict モードでは移行を容易にする制限事項を適用します。将来の変更点の基礎が Strict モードで禁止されていると、変更が容易になります。

+ +

第一に、Strict モードでは、いくつかの識別子を予約語にします。その対象は implements, interface, let, package, private, protected, public, static, yield です。Strict モードでは、これらを変数や引数の名前として使用できません。

+ +
function package(protected) { // !!!
+  'use strict';
+  var implements; // !!!
+
+  interface: // !!!
+  while (true) {
+    break interface; // !!!
+  }
+
+  function private() { } // !!!
+}
+function fun(static) { 'use strict'; } // !!!
+
+
+ +

Mozilla 特有の注意事項が 2 つあります: 第一に、コードが JavaScript 1.7 以降 (chrome コード、または適切な <script type=""> を使用) かつ Strict モードである場合、let および yield にはそれらのキーワードが最初に導入されてから持っていた機能があります。しかし <script src=""><script>...</script> で読み込む Web の Strict モードのコードでは、let/yield を識別子として使用できません。第二に、ES5 では classenumexportextendsimportsuper を無条件に予約していますが、Firefox 5 以前で Mozilla はこれらを Strict モードでのみ予約します。

+ +

第二に、Strict モードでは、スクリプトのトップレベルまたは関数内にない function 文を禁止します。通常のコードでは、function 文はどこにでも置くことが許されます。これは ES5 の仕様に (ES3 でさえも) 含まれていません! ブラウザーにより意味が異なり互換性がない拡張です。将来の ECMAScript では、おそらくスクリプトのトップレベルや関数内以外での funciton 文に新たな意味を定義します。Strict モードではこのような function 文を禁止する ことで将来の ECMAScript の仕様向けの "宣言を取り除きます":

+ +
'use strict';
+if (true) {
+  function f() { } // !!! 構文エラー
+  f();
+}
+
+for (var i = 0; i < 5; i++) {
+  function f2() { } // !!! 構文エラー
+  f2();
+}
+
+function baz() { // kosher
+  function eit() { } // also kosher
+}
+
+ +

このような function 文は基本的な ES5 の拡張であるため、禁止することは Strict モードとして適切ではありません。しかしこの動作は ECMAScript 委員会の推奨であり、それゆえブラウザーは実装するでしょう。

+ +

ブラウザーでの Strict モード

+ +

ブラウザーはまだ Strict モードを確実に実装していないため、無条件に依存しないでください。Strict モードは意味を変えます。それら変更点を当てにすると、Strict モードを実装していないブラウザーでミスやエラーが発生する可能性があります。Strict モードの使用時は注意を払い、また Strict モードに関する機能を実装しているかの機能テストにより Strict モードへの信頼を補ってください。最後に、Strict モードをサポートするブラウザーとしないブラウザーでのコードのテスト を行うようにしてください。Strict モードをサポートしないブラウザーでしかテスト行わない場合、Strict モードをサポートするブラウザーで問題が起きる可能性が高くなります。これは逆の場合も同じです。

+ +

仕様

+ + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-strict-mode-code', 'Strict Mode Code')}}
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html b/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html deleted file mode 100644 index 7db6c16fc1..0000000000 --- a/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.html +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: 厳格モードへの移行 -slug: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode -tags: - - Advanced - - Guide - - JavaScript - - ガイド - - 上級者 -translation_of: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode ---- -
{{jsSidebar("More")}}
- -

ECMAScript 第5版では厳格モード (strict mode) を導入し、主要なブラウザーすべて (IE10 を含む) に実装されました。ウェブブラウザーにコードを厳密モードとして解釈させるのは簡単ですが (ソースコードの先頭に 'use strict'; を追加するだけです)、既存のコードベースを厳格モードに移行するには、もう少し作業が必要です。

- -

この記事の目的は、開発者へのガイダンスを提供することです。

- -

段階的移行

- -

厳格モードは、段階的に移行できるように設計されています。ファイルごとに個別に変更することもできますし、関数の粒度で厳格モードにコードを移行することも可能です。

- -

非厳格モードと厳格モードの違い

- -

構文エラー

- -

'use strict';を追加すると、スクリプトが実行される前に、以下のケースでは{{jsxref("SyntaxError")}} をスローします。

- - - -

単純なエラーや悪習を明らかにするので、こういったエラーは良いものです。これらのエラーは、コードが実行される前に発生します。

- -

新しい実行時エラー

- -

JavaScript は以前、何をしたかがエラーになるような状況では、暗黙に失敗していました。厳格モードでは、そのような場合に例外を発生させます。コードベースにそのようなケースが含まれている場合、何も壊れていないことを確認するためにテストが必要になります。繰り返しになりますが、これは関数の粒度レベルで起こる可能性があります。

- -

宣言していない変数への値設定

- -
function f(x) {
-  'use strict';
-  var a = 12;
-  b = a + x * 35; // エラー!
-}
-f(42);
-
- -

これはグローバルオブジェクトの値を変更するために使われてきましたが、それが期待される効果であることはまれでした。本当にグローバルオブジェクトに値を設定したい場合は、引数として渡し、明示的にプロパティとして代入してください。

- -
var global = this; // 最上位のコンテキストでは、 "this" は常に
-                   // グローバルオブジェクトを参照します
-function f(x) {
-  'use strict';
-  var a = 12;
-  global.b = a + x * 35;
-}
-f(42);
-
- -

設定不可能なプロパティを削除しようとすること

- -
'use strict';
-delete Object.prototype; // エラー!
-
- -

厳格モードでない場合は、ユーザーの予想に反して、暗黙に失敗します。

- -

ポイズン引数と関数プロパティ

- -

厳格モードでは arguments.callee, arguments.caller, anyFunction.caller, anyFunction.arguments にアクセスするとエラーが発生します。唯一の合法的な利用法は、以下のように関数を再利用することでしょう。

- -
// example taken from vanillajs: http://vanilla-js.com/
-var s = document.getElementById('thing').style;
-s.opacity = 1;
-(function() {
-  if ((s.opacity-=.1) < 0)
-    s.display = 'none';
-  else
-    setTimeout(arguments.callee, 40);
-})();
- -

上記は以下のように書き換えられます。

- -
'use strict';
-var s = document.getElementById('thing').style;
-s.opacity = 1;
-(function fadeOut() { // 関数名
-  if((s.opacity-=.1) < 0)
-    s.display = 'none';
-  else
-    setTimeout(fadeOut, 40); // 関数名を使用する
-})();
- -

意味的な違い

- -

以下の違いは非常に微妙な違いです。テストスイートはこの種の微妙な差を捉えない可能性があります。これらの違いがコードの意味に影響を与えないことを確認するためには、コードベースの慎重なレビューが必要になるでしょう。幸いなことに、この慎重なレビューによって機能の粒度を徐々に下げていくことができます。

- -

関数呼び出しにおける this

- -

f() のような関数呼び出しでは、 this の値はグローバルオブジェクトでした。厳格モードでは undefined になりました。関数が {{jsxref("Function/call", "call")}} または {{jsxref("Function/apply", "apply")}} で呼び出されたとき、この値がプリミティブ値であった場合は、オブジェクト (または undefinednull に対してはグローバルオブジェクト) にボックス化されていました。厳格モードでは、値は変換または置換せずに直接渡されます。

- -

arguments は関数の名前付き引数の別名ではない

- -

厳格モードでない場合、 arguments オブジェクト内の値を変更すると、対応する名前付きの引数も変更されます。これは JavaScript エンジンの最適化を複雑にし、コードを呼んだり理解したりするのを難しくしていました。厳格モードでは、 arguments オブジェクトは名前付き引数と同じ値で作成・初期化されますが、 arguments オブジェクトや名前付き引数の変更は互いに反映されません。

- -

eval への変更

- -

厳格モードのコードでは、 eval は呼び出されたスコープ内に新しい変数を作成しません。また厳格モードでは、もちろん文字列は厳格モードの規則で評価されます。何も破綻していないことを確認するためには、徹底的なテストが必要になります。本当に必要ではない場合は eval を使わないというのも現実的な解決策かもしれません。

- -

厳格性に中立なコード

- -

厳格なコードを厳格モードに移行する上での潜在的な「欠点」は、厳密モードを実装していない古いブラウザーでは意味が異なる可能性があることです。まれに起こることですが (連結やミニ化の失敗などで)、コードも書いてテストしたモードで実行されないこともあります。ここでは、コードの厳格性への依存をなくす規則を示します。

- -
    -
  1. コードを厳格モードで書き、厳格モードでしか発生しないエラー (上記の「新しい実行時エラー」の節にあるもの) が発生しないことを確認してください。
  2. -
  3. 意味の違いから離れてみてください。 -
      -
    1. eval: 何をやっているか分かる場合にのみ、使用してください。
    2. -
    3. arguments: 関数の引数へは、常に名前を経由してアクセスするか、 arguments のオブジェクトのコピーを行うために、
      - var args = Array.prototype.slice.call(arguments)
      - を関数の最初の行に追加してください。
    4. -
    5. this: 自ら生成したオブジェクトへ参照するときのみ this を使用してください。
    6. -
    -
  4. -
- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.md b/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.md new file mode 100644 index 0000000000..7db6c16fc1 --- /dev/null +++ b/files/ja/web/javascript/reference/strict_mode/transitioning_to_strict_mode/index.md @@ -0,0 +1,142 @@ +--- +title: 厳格モードへの移行 +slug: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode +tags: + - Advanced + - Guide + - JavaScript + - ガイド + - 上級者 +translation_of: Web/JavaScript/Reference/Strict_mode/Transitioning_to_strict_mode +--- +
{{jsSidebar("More")}}
+ +

ECMAScript 第5版では厳格モード (strict mode) を導入し、主要なブラウザーすべて (IE10 を含む) に実装されました。ウェブブラウザーにコードを厳密モードとして解釈させるのは簡単ですが (ソースコードの先頭に 'use strict'; を追加するだけです)、既存のコードベースを厳格モードに移行するには、もう少し作業が必要です。

+ +

この記事の目的は、開発者へのガイダンスを提供することです。

+ +

段階的移行

+ +

厳格モードは、段階的に移行できるように設計されています。ファイルごとに個別に変更することもできますし、関数の粒度で厳格モードにコードを移行することも可能です。

+ +

非厳格モードと厳格モードの違い

+ +

構文エラー

+ +

'use strict';を追加すると、スクリプトが実行される前に、以下のケースでは{{jsxref("SyntaxError")}} をスローします。

+ + + +

単純なエラーや悪習を明らかにするので、こういったエラーは良いものです。これらのエラーは、コードが実行される前に発生します。

+ +

新しい実行時エラー

+ +

JavaScript は以前、何をしたかがエラーになるような状況では、暗黙に失敗していました。厳格モードでは、そのような場合に例外を発生させます。コードベースにそのようなケースが含まれている場合、何も壊れていないことを確認するためにテストが必要になります。繰り返しになりますが、これは関数の粒度レベルで起こる可能性があります。

+ +

宣言していない変数への値設定

+ +
function f(x) {
+  'use strict';
+  var a = 12;
+  b = a + x * 35; // エラー!
+}
+f(42);
+
+ +

これはグローバルオブジェクトの値を変更するために使われてきましたが、それが期待される効果であることはまれでした。本当にグローバルオブジェクトに値を設定したい場合は、引数として渡し、明示的にプロパティとして代入してください。

+ +
var global = this; // 最上位のコンテキストでは、 "this" は常に
+                   // グローバルオブジェクトを参照します
+function f(x) {
+  'use strict';
+  var a = 12;
+  global.b = a + x * 35;
+}
+f(42);
+
+ +

設定不可能なプロパティを削除しようとすること

+ +
'use strict';
+delete Object.prototype; // エラー!
+
+ +

厳格モードでない場合は、ユーザーの予想に反して、暗黙に失敗します。

+ +

ポイズン引数と関数プロパティ

+ +

厳格モードでは arguments.callee, arguments.caller, anyFunction.caller, anyFunction.arguments にアクセスするとエラーが発生します。唯一の合法的な利用法は、以下のように関数を再利用することでしょう。

+ +
// example taken from vanillajs: http://vanilla-js.com/
+var s = document.getElementById('thing').style;
+s.opacity = 1;
+(function() {
+  if ((s.opacity-=.1) < 0)
+    s.display = 'none';
+  else
+    setTimeout(arguments.callee, 40);
+})();
+ +

上記は以下のように書き換えられます。

+ +
'use strict';
+var s = document.getElementById('thing').style;
+s.opacity = 1;
+(function fadeOut() { // 関数名
+  if((s.opacity-=.1) < 0)
+    s.display = 'none';
+  else
+    setTimeout(fadeOut, 40); // 関数名を使用する
+})();
+ +

意味的な違い

+ +

以下の違いは非常に微妙な違いです。テストスイートはこの種の微妙な差を捉えない可能性があります。これらの違いがコードの意味に影響を与えないことを確認するためには、コードベースの慎重なレビューが必要になるでしょう。幸いなことに、この慎重なレビューによって機能の粒度を徐々に下げていくことができます。

+ +

関数呼び出しにおける this

+ +

f() のような関数呼び出しでは、 this の値はグローバルオブジェクトでした。厳格モードでは undefined になりました。関数が {{jsxref("Function/call", "call")}} または {{jsxref("Function/apply", "apply")}} で呼び出されたとき、この値がプリミティブ値であった場合は、オブジェクト (または undefinednull に対してはグローバルオブジェクト) にボックス化されていました。厳格モードでは、値は変換または置換せずに直接渡されます。

+ +

arguments は関数の名前付き引数の別名ではない

+ +

厳格モードでない場合、 arguments オブジェクト内の値を変更すると、対応する名前付きの引数も変更されます。これは JavaScript エンジンの最適化を複雑にし、コードを呼んだり理解したりするのを難しくしていました。厳格モードでは、 arguments オブジェクトは名前付き引数と同じ値で作成・初期化されますが、 arguments オブジェクトや名前付き引数の変更は互いに反映されません。

+ +

eval への変更

+ +

厳格モードのコードでは、 eval は呼び出されたスコープ内に新しい変数を作成しません。また厳格モードでは、もちろん文字列は厳格モードの規則で評価されます。何も破綻していないことを確認するためには、徹底的なテストが必要になります。本当に必要ではない場合は eval を使わないというのも現実的な解決策かもしれません。

+ +

厳格性に中立なコード

+ +

厳格なコードを厳格モードに移行する上での潜在的な「欠点」は、厳密モードを実装していない古いブラウザーでは意味が異なる可能性があることです。まれに起こることですが (連結やミニ化の失敗などで)、コードも書いてテストしたモードで実行されないこともあります。ここでは、コードの厳格性への依存をなくす規則を示します。

+ +
    +
  1. コードを厳格モードで書き、厳格モードでしか発生しないエラー (上記の「新しい実行時エラー」の節にあるもの) が発生しないことを確認してください。
  2. +
  3. 意味の違いから離れてみてください。 +
      +
    1. eval: 何をやっているか分かる場合にのみ、使用してください。
    2. +
    3. arguments: 関数の引数へは、常に名前を経由してアクセスするか、 arguments のオブジェクトのコピーを行うために、
      + var args = Array.prototype.slice.call(arguments)
      + を関数の最初の行に追加してください。
    4. +
    5. this: 自ら生成したオブジェクトへ参照するときのみ this を使用してください。
    6. +
    +
  4. +
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/reference/template_literals/index.html b/files/ja/web/javascript/reference/template_literals/index.html deleted file mode 100644 index be235fc8bf..0000000000 --- a/files/ja/web/javascript/reference/template_literals/index.html +++ /dev/null @@ -1,271 +0,0 @@ ---- -title: テンプレートリテラル (テンプレート文字列) -slug: Web/JavaScript/Reference/Template_literals -tags: - - ECMAScript 2015 - - Guide - - JavaScript - - React - - String - - Template Strings - - Template literals - - Template string - - strings - - ガイド - - テンプレートリテラル - - テンプレート文字列 - - 文字列 -translation_of: Web/JavaScript/Reference/Template_literals ---- -
{{JsSidebar("More")}}
- -

テンプレートリテラルは、組み込み式を扱うことができる文字列リテラルです。複数行の文字列や文字列挿入機能を使用することができます。

- -

ES2015 仕様書よりも前の版では、"template strings" と呼ばれていました。

- -

構文

- -
`string text`
-
-`string text line 1
- string text line 2`
-
-`string text ${expression} string text`
-
-tag`string text ${expression} string text`
-
- -

解説

- -

テンプレートリテラルは、ダブルクオートやシングルクオートの代わりにバックティック文字 (` `) (グレイヴ・アクセント) で囲みます。

- -

テンプレートリテラルにはプレースホルダーを含めることができます。プレースホルダーはドル記号と波括弧 (${expression}) で示されます。プレースホルダー内の式とバックティック文字 (` `) の間にあるテキストが関数に渡されます。

- -

既定の関数はこれらの部品を 1 つの文字列として繋げるだけです。テンプレートリテラルの前に式 (ここでは tag) がある場合、テンプレートリテラルは タグ付きテンプレート と呼ばれます。この場合、タグ式 (通常は関数) は、テンプレートリテラルと一緒に呼び出され、出力の前に実行できます。

- -

テンプレートリテラル内でバックティック文字をエスケープするには、バックティック文字の前にバックスラッシュ (\) を置きます。

- -
`\`` === '`' // --> true
- -

複数行の文字列

- -

ソースの中に挿入された改行文字は、すべてテンプレートリテラルの一部になります。

- -

通常の文字列を使う場合は、複数行の文字列を取得するために次のような構文を使用する必要があります。

- -
console.log('string text line 1\n' +
-'string text line 2');
-// "string text line 1
-// string text line 2"
- -

テンプレートリテラルを使用すれば、同じものを次のように書くことができます。

- -
console.log(`string text line 1
-string text line 2`);
-// "string text line 1
-// string text line 2"
- -

式の挿入

- -

通常の文字列に式を埋め込むには、以下のような構文を使用していると思います。

- -
let a = 5;
-let b = 10;
-console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
-// "Fifteen is 15 and
-// not 20."
- -

テンプレートリテラルを使用すると、糖衣構文を使用して、このようにもっと読みやすく表記することができます。

- -
let a = 5;
-let b = 10;
-console.log(`Fifteen is ${a + b} and
-not ${2 * a + b}.`);
-// "Fifteen is 15 and
-// not 20."
- -

入れ子のテンプレート

- -

場合によっては、テンプレートを入れ子にすると、構成可能な文字列を得るのにもっとも簡単に (かつ、おそらくより読みやすく) なることがあります。バックティックをつけたテンプレートでは、テンプレート内にあるプレイスホルダー ${ } の内部で内部のバックティックを使用することができます。

- -

例えば、条件式が true の場合、このテンプレートリテラルを return します。

- -

ES5 の場合:

- -
let classes = 'header';
-classes += (isLargeScreen() ?
-  '' : item.isCollapsed ?
-    ' icon-expander' : ' icon-collapser');
-
- -

ES2015 で入れ子なしのテンプレートリテラルの場合:

- -
const classes = `header ${ isLargeScreen() ? '' :
-  (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;
- -

ES2015 で入れ子にしたテンプレートリテラルの場合:

- -
const classes = `header ${ isLargeScreen() ? '' :
-  `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;
- -

タグ付きテンプレート

- -

タグ付きテンプレートは、テンプレートリテラルのより高度な形式です。

- -

タグを使用すると、テンプレートリテラルを関数で解析できます。タグ関数の最初の引数には、文字列リテラルの配列を含みます。残りの引数は式に関連付けられます。

- -

タグ関数は、これらの引数に対して何でも望み通りの操作を実行することができ、加工された文字列を返します。 (または、以下の例の一つで示しているように、まったく異なるものを返すこともできます。)

- -

タグに使用される関数の名前は、自由に指定できます。

- -
let person = 'Mike';
-let age = 28;
-
-function myTag(strings, personExp, ageExp) {
-  let str0 = strings[0]; // "That "
-  let str1 = strings[1]; // " is a "
-
-  // There is technically a string after
-  // the final expression (in our example),
-  // but it is empty (""), so disregard.
-  // let str2 = strings[2];
-
-  let ageStr;
-  if (ageExp > 99){
-    ageStr = 'centenarian';
-  } else {
-    ageStr = 'youngster';
-  }
-
-  // テンプレートリテラルを用いて組み立てた文字列を返すこともできます
-  return `${str0}${personExp}${str1}${ageStr}`;
-}
-
-let output = myTag`That ${ person } is a ${ age }`;
-
-console.log(output);
-// That Mike is a youngster
- -

タグ関数は文字列を返さなくても構いません。

- -
function template(strings, ...keys) {
-  return (function(...values) {
-    let dict = values[values.length - 1] || {};
-    let result = [strings[0]];
-    keys.forEach(function(key, i) {
-      let value = Number.isInteger(key) ? values[key] : dict[key];
-      result.push(value, strings[i + 1]);
-    });
-    return result.join('');
-  });
-}
-
-let t1Closure = template`${0}${1}${0}!`;
-//let t1Closure = template(["","","","!"],0,1,0);
-t1Closure('Y', 'A');                      // "YAY!"
-
-let t2Closure = template`${0} ${'foo'}!`;
-//let t2Closure = template(["","","!"],0,"foo");
-t2Closure('Hello', {foo: 'World'}); // "Hello World!"
-
-let t3Closure = template`I'm ${'name'}. I'm almost ${'age'} years old.`;
-//let t3Closure = template(["I'm ", ". I'm almost ", " years old."], "name", "age");
-t3Closure('foo', {name: 'MDN', age: 30}); //"I'm MDN. I'm almost 30 years old."
-t3Closure({name: 'MDN', age: 30}); //"I'm MDN. I'm almost 30 years old."
-
- -

加工前の文字列

- -

タグ関数に渡される第 1 引数では、特別な raw プロパティが利用できます。このプロパティを通して、エスケープシーケンスを処理する前の、入力された通りの加工前の文字列を参照することができます。

- -
function tag(strings) {
-  console.log(strings.raw[0]);
-}
-
-tag`string text line 1 \n string text line 2`;
-// logs "string text line 1 \n string text line 2" ,
-// including the two characters '\' and 'n'
-
- -

加えて、 {{jsxref("String.raw()")}} メソッドがあり、既定のテンプレート関数のように文字列を連結した形で加工前の文字列を生成することができます。

- -
let str = String.raw`Hi\n${2+3}!`;
-// "Hi\n5!"
-
-str.length;
-// 6
-
-Array.from(str).join(',');
-// "H,i,\,n,5,!"
-
- -

タグ付きテンプレートとエスケープシーケンス

- -

ES2016 での動作

- -

ECMAScript 2016 時点では、タグ付きテンプレートの以下のエスケープシーケンスには、次のようなルールが適用されます。

- - - -

このルールのもとでは、下に示す例のようなタグ付きテンプレートが問題となります。なぜなら、 ECMAScript の文法に従ってこのテキストを解釈しようとすると、パーサーは Unicode の有効のエスケープシーケンスを探そうとするも、不正な構文が検出されてしまうからです。

- -
latex`\unicode`
-// 古い ECMAScript バージョン (ES2016 以前) では、以下のような例外が投げられる
-// SyntaxError: malformed Unicode character escape sequence
- -

ES2018 revision での不正なエスケープシーケンス

- -

タグ付きテンプレートでは、他のエスケープシーケンスが一般的な言語 (DSLLaTeX など) の埋め込みも許容する必要があります。 ECMAScript プロポーザル Template Literal Revision (Stage 4, to be integrated in the ECMAScript 2018 standard) では、タグ付きテンプレートから、ECMAScript のエスケープシーケンスについての構文的な制約が除外されています。

- -

しかし、埋め込んで「加工された」結果の中においても、不正なエスケープシーケンスがあれば、それを提示する必要があります。こうした不正なエスケープシーケンスは、「加工された」の配列の中では、{{jsxref("undefined")}} の要素として表示されます。

- -
function latex(str) {
-  return { "cooked": str[0], "raw": str.raw[0] }
-}
-
-latex`\unicode`
-
-// { cooked: undefined, raw: "\\unicode" }
- -

このエスケープシーケンスの制約は、タグ付きテンプレートのみが除外となります。タグ付きでないテンプレートリテラルの場合は、除外対象ではありません:

- -
let bad = `bad escape sequence: \unicode`;
- -

仕様書

- - - - - - - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-template-literals', 'Template Literals')}}
{{SpecName('ESDraft', '#sec-tagged-templates', 'Tagged templates Literals')}}
- -

ブラウザーの互換性

- -
-

{{Compat("javascript.grammar.template_literals")}}

-
- -

関連情報

- - diff --git a/files/ja/web/javascript/reference/template_literals/index.md b/files/ja/web/javascript/reference/template_literals/index.md new file mode 100644 index 0000000000..be235fc8bf --- /dev/null +++ b/files/ja/web/javascript/reference/template_literals/index.md @@ -0,0 +1,271 @@ +--- +title: テンプレートリテラル (テンプレート文字列) +slug: Web/JavaScript/Reference/Template_literals +tags: + - ECMAScript 2015 + - Guide + - JavaScript + - React + - String + - Template Strings + - Template literals + - Template string + - strings + - ガイド + - テンプレートリテラル + - テンプレート文字列 + - 文字列 +translation_of: Web/JavaScript/Reference/Template_literals +--- +
{{JsSidebar("More")}}
+ +

テンプレートリテラルは、組み込み式を扱うことができる文字列リテラルです。複数行の文字列や文字列挿入機能を使用することができます。

+ +

ES2015 仕様書よりも前の版では、"template strings" と呼ばれていました。

+ +

構文

+ +
`string text`
+
+`string text line 1
+ string text line 2`
+
+`string text ${expression} string text`
+
+tag`string text ${expression} string text`
+
+ +

解説

+ +

テンプレートリテラルは、ダブルクオートやシングルクオートの代わりにバックティック文字 (` `) (グレイヴ・アクセント) で囲みます。

+ +

テンプレートリテラルにはプレースホルダーを含めることができます。プレースホルダーはドル記号と波括弧 (${expression}) で示されます。プレースホルダー内の式とバックティック文字 (` `) の間にあるテキストが関数に渡されます。

+ +

既定の関数はこれらの部品を 1 つの文字列として繋げるだけです。テンプレートリテラルの前に式 (ここでは tag) がある場合、テンプレートリテラルは タグ付きテンプレート と呼ばれます。この場合、タグ式 (通常は関数) は、テンプレートリテラルと一緒に呼び出され、出力の前に実行できます。

+ +

テンプレートリテラル内でバックティック文字をエスケープするには、バックティック文字の前にバックスラッシュ (\) を置きます。

+ +
`\`` === '`' // --> true
+ +

複数行の文字列

+ +

ソースの中に挿入された改行文字は、すべてテンプレートリテラルの一部になります。

+ +

通常の文字列を使う場合は、複数行の文字列を取得するために次のような構文を使用する必要があります。

+ +
console.log('string text line 1\n' +
+'string text line 2');
+// "string text line 1
+// string text line 2"
+ +

テンプレートリテラルを使用すれば、同じものを次のように書くことができます。

+ +
console.log(`string text line 1
+string text line 2`);
+// "string text line 1
+// string text line 2"
+ +

式の挿入

+ +

通常の文字列に式を埋め込むには、以下のような構文を使用していると思います。

+ +
let a = 5;
+let b = 10;
+console.log('Fifteen is ' + (a + b) + ' and\nnot ' + (2 * a + b) + '.');
+// "Fifteen is 15 and
+// not 20."
+ +

テンプレートリテラルを使用すると、糖衣構文を使用して、このようにもっと読みやすく表記することができます。

+ +
let a = 5;
+let b = 10;
+console.log(`Fifteen is ${a + b} and
+not ${2 * a + b}.`);
+// "Fifteen is 15 and
+// not 20."
+ +

入れ子のテンプレート

+ +

場合によっては、テンプレートを入れ子にすると、構成可能な文字列を得るのにもっとも簡単に (かつ、おそらくより読みやすく) なることがあります。バックティックをつけたテンプレートでは、テンプレート内にあるプレイスホルダー ${ } の内部で内部のバックティックを使用することができます。

+ +

例えば、条件式が true の場合、このテンプレートリテラルを return します。

+ +

ES5 の場合:

+ +
let classes = 'header';
+classes += (isLargeScreen() ?
+  '' : item.isCollapsed ?
+    ' icon-expander' : ' icon-collapser');
+
+ +

ES2015 で入れ子なしのテンプレートリテラルの場合:

+ +
const classes = `header ${ isLargeScreen() ? '' :
+  (item.isCollapsed ? 'icon-expander' : 'icon-collapser') }`;
+ +

ES2015 で入れ子にしたテンプレートリテラルの場合:

+ +
const classes = `header ${ isLargeScreen() ? '' :
+  `icon-${item.isCollapsed ? 'expander' : 'collapser'}` }`;
+ +

タグ付きテンプレート

+ +

タグ付きテンプレートは、テンプレートリテラルのより高度な形式です。

+ +

タグを使用すると、テンプレートリテラルを関数で解析できます。タグ関数の最初の引数には、文字列リテラルの配列を含みます。残りの引数は式に関連付けられます。

+ +

タグ関数は、これらの引数に対して何でも望み通りの操作を実行することができ、加工された文字列を返します。 (または、以下の例の一つで示しているように、まったく異なるものを返すこともできます。)

+ +

タグに使用される関数の名前は、自由に指定できます。

+ +
let person = 'Mike';
+let age = 28;
+
+function myTag(strings, personExp, ageExp) {
+  let str0 = strings[0]; // "That "
+  let str1 = strings[1]; // " is a "
+
+  // There is technically a string after
+  // the final expression (in our example),
+  // but it is empty (""), so disregard.
+  // let str2 = strings[2];
+
+  let ageStr;
+  if (ageExp > 99){
+    ageStr = 'centenarian';
+  } else {
+    ageStr = 'youngster';
+  }
+
+  // テンプレートリテラルを用いて組み立てた文字列を返すこともできます
+  return `${str0}${personExp}${str1}${ageStr}`;
+}
+
+let output = myTag`That ${ person } is a ${ age }`;
+
+console.log(output);
+// That Mike is a youngster
+ +

タグ関数は文字列を返さなくても構いません。

+ +
function template(strings, ...keys) {
+  return (function(...values) {
+    let dict = values[values.length - 1] || {};
+    let result = [strings[0]];
+    keys.forEach(function(key, i) {
+      let value = Number.isInteger(key) ? values[key] : dict[key];
+      result.push(value, strings[i + 1]);
+    });
+    return result.join('');
+  });
+}
+
+let t1Closure = template`${0}${1}${0}!`;
+//let t1Closure = template(["","","","!"],0,1,0);
+t1Closure('Y', 'A');                      // "YAY!"
+
+let t2Closure = template`${0} ${'foo'}!`;
+//let t2Closure = template(["","","!"],0,"foo");
+t2Closure('Hello', {foo: 'World'}); // "Hello World!"
+
+let t3Closure = template`I'm ${'name'}. I'm almost ${'age'} years old.`;
+//let t3Closure = template(["I'm ", ". I'm almost ", " years old."], "name", "age");
+t3Closure('foo', {name: 'MDN', age: 30}); //"I'm MDN. I'm almost 30 years old."
+t3Closure({name: 'MDN', age: 30}); //"I'm MDN. I'm almost 30 years old."
+
+ +

加工前の文字列

+ +

タグ関数に渡される第 1 引数では、特別な raw プロパティが利用できます。このプロパティを通して、エスケープシーケンスを処理する前の、入力された通りの加工前の文字列を参照することができます。

+ +
function tag(strings) {
+  console.log(strings.raw[0]);
+}
+
+tag`string text line 1 \n string text line 2`;
+// logs "string text line 1 \n string text line 2" ,
+// including the two characters '\' and 'n'
+
+ +

加えて、 {{jsxref("String.raw()")}} メソッドがあり、既定のテンプレート関数のように文字列を連結した形で加工前の文字列を生成することができます。

+ +
let str = String.raw`Hi\n${2+3}!`;
+// "Hi\n5!"
+
+str.length;
+// 6
+
+Array.from(str).join(',');
+// "H,i,\,n,5,!"
+
+ +

タグ付きテンプレートとエスケープシーケンス

+ +

ES2016 での動作

+ +

ECMAScript 2016 時点では、タグ付きテンプレートの以下のエスケープシーケンスには、次のようなルールが適用されます。

+ + + +

このルールのもとでは、下に示す例のようなタグ付きテンプレートが問題となります。なぜなら、 ECMAScript の文法に従ってこのテキストを解釈しようとすると、パーサーは Unicode の有効のエスケープシーケンスを探そうとするも、不正な構文が検出されてしまうからです。

+ +
latex`\unicode`
+// 古い ECMAScript バージョン (ES2016 以前) では、以下のような例外が投げられる
+// SyntaxError: malformed Unicode character escape sequence
+ +

ES2018 revision での不正なエスケープシーケンス

+ +

タグ付きテンプレートでは、他のエスケープシーケンスが一般的な言語 (DSLLaTeX など) の埋め込みも許容する必要があります。 ECMAScript プロポーザル Template Literal Revision (Stage 4, to be integrated in the ECMAScript 2018 standard) では、タグ付きテンプレートから、ECMAScript のエスケープシーケンスについての構文的な制約が除外されています。

+ +

しかし、埋め込んで「加工された」結果の中においても、不正なエスケープシーケンスがあれば、それを提示する必要があります。こうした不正なエスケープシーケンスは、「加工された」の配列の中では、{{jsxref("undefined")}} の要素として表示されます。

+ +
function latex(str) {
+  return { "cooked": str[0], "raw": str.raw[0] }
+}
+
+latex`\unicode`
+
+// { cooked: undefined, raw: "\\unicode" }
+ +

このエスケープシーケンスの制約は、タグ付きテンプレートのみが除外となります。タグ付きでないテンプレートリテラルの場合は、除外対象ではありません:

+ +
let bad = `bad escape sequence: \unicode`;
+ +

仕様書

+ + + + + + + + + + + + + + + +
仕様書
{{SpecName('ESDraft', '#sec-template-literals', 'Template Literals')}}
{{SpecName('ESDraft', '#sec-tagged-templates', 'Tagged templates Literals')}}
+ +

ブラウザーの互換性

+ +
+

{{Compat("javascript.grammar.template_literals")}}

+
+ +

関連情報

+ + -- cgit v1.2.3-54-g00ecf