From 33058f2b292b3a581333bdfb21b8f671898c5060 Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:40:17 -0500 Subject: initial commit --- .../index.html | 25 + .../control_flow_and_error_handling/index.html | 457 ++++++++++ .../guide/core_language_features/index.html | 10 + .../guide/creating_a_regular_expression/index.html | 31 + .../defining_getters_and_setters/index.html | 89 ++ .../defining_methods/index.html | 39 + .../index.html | 13 + .../deleting_properties/index.html | 20 + .../guide/creating_new_objects/index.html | 17 + .../indexing_object_properties/index.html | 9 + .../using_a_constructor_function/index.html | 57 ++ .../using_object_initializers/index.html | 23 + .../using_this_for_object_references/index.html | 25 + .../guide/details_of_the_object_model/index.html | 728 ++++++++++++++++ .../guide/exception_handling_statements/index.html | 36 + .../throw_statement/index.html | 34 + .../try...catch_statement/index.html | 135 +++ .../ja/web/javascript/guide/expressions/index.html | 16 + .../guide/expressions_and_operators/index.html | 928 +++++++++++++++++++++ files/ja/web/javascript/guide/functions/index.html | 696 ++++++++++++++++ .../javascript/guide/grammar_and_types/index.html | 762 +++++++++++++++++ files/ja/web/javascript/guide/index.html | 138 +++ .../guide/indexed_collections/index.html | 598 +++++++++++++ .../web/javascript/guide/introduction/index.html | 160 ++++ .../guide/iterators_and_generators/index.html | 242 ++++++ .../javascript/guide/keyed_collections/index.html | 161 ++++ .../guide/liveconnect_overview/index.html | 799 ++++++++++++++++++ .../loop_statements/break_statement/index.html | 24 + .../loop_statements/continue_statement/index.html | 46 + .../do...while_statement/index.html | 19 + .../guide/loop_statements/for_statement/index.html | 50 ++ .../javascript/guide/loop_statements/index.html | 17 + .../loop_statements/label_statement/index.html | 19 + .../loop_statements/while_statement/index.html | 35 + .../guide/loops_and_iteration/index.html | 365 ++++++++ .../javascript/guide/meta_programming/index.html | 290 +++++++ files/ja/web/javascript/guide/modules/index.html | 457 ++++++++++ .../javascript/guide/numbers_and_dates/index.html | 395 +++++++++ .../object_manipulation_statements/index.html | 51 ++ .../guide/objects_and_properties/index.html | 32 + .../web/javascript/guide/obsolete_pages/index.html | 9 + .../function_object/index.html | 44 + .../operators/arithmetic_operators/index.html | 47 ++ .../operators/assignment_operators/index.html | 61 ++ .../operators/comparison_operators/index.html | 67 ++ .../guide/operators/logical_operators/index.html | 63 ++ .../guide/operators/special_operators/index.html | 197 +++++ .../guide/operators/string_operators/index.html | 8 + .../escape_and_unescape_functions/index.html | 14 + .../predefined_functions/eval_function/index.html | 12 + .../guide/predefined_functions/index.html | 17 + .../regular_expressions/assertions/index.html | 246 ++++++ .../character_classes/index.html | 216 +++++ .../groups_and_ranges/index.html | 162 ++++ .../guide/regular_expressions/index.html | 800 ++++++++++++++++++ .../regular_expressions/quantifiers/index.html | 152 ++++ .../javascript/guide/text_formatting/index.html | 256 ++++++ .../creating_the_hierarchy/index.html | 134 +++ .../guide/the_employee_example/index.html | 31 + .../object_properties/adding_properties/index.html | 19 + .../object_properties/index.html | 13 + .../inheriting_properties/index.html | 24 + .../web/javascript/guide/using_promises/index.html | 358 ++++++++ .../guide/using_the_arguments_object/index.html | 36 + files/ja/web/javascript/guide/variables/index.html | 62 ++ .../guide/working_with_objects/index.html | 496 +++++++++++ .../index.html | 193 +++++ 67 files changed, 11785 insertions(+) create mode 100644 files/ja/web/javascript/guide/class-based_vs._prototype-based_languages/index.html create mode 100644 files/ja/web/javascript/guide/control_flow_and_error_handling/index.html create mode 100644 files/ja/web/javascript/guide/core_language_features/index.html create mode 100644 files/ja/web/javascript/guide/creating_a_regular_expression/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/defining_getters_and_setters/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/defining_methods/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/defining_properties_for_an_object_type/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/deleting_properties/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/indexing_object_properties/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/using_a_constructor_function/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/using_object_initializers/index.html create mode 100644 files/ja/web/javascript/guide/creating_new_objects/using_this_for_object_references/index.html create mode 100644 files/ja/web/javascript/guide/details_of_the_object_model/index.html create mode 100644 files/ja/web/javascript/guide/exception_handling_statements/index.html create mode 100644 files/ja/web/javascript/guide/exception_handling_statements/throw_statement/index.html create mode 100644 files/ja/web/javascript/guide/exception_handling_statements/try...catch_statement/index.html create mode 100644 files/ja/web/javascript/guide/expressions/index.html create mode 100644 files/ja/web/javascript/guide/expressions_and_operators/index.html create mode 100644 files/ja/web/javascript/guide/functions/index.html create mode 100644 files/ja/web/javascript/guide/grammar_and_types/index.html create mode 100644 files/ja/web/javascript/guide/index.html create mode 100644 files/ja/web/javascript/guide/indexed_collections/index.html create mode 100644 files/ja/web/javascript/guide/introduction/index.html create mode 100644 files/ja/web/javascript/guide/iterators_and_generators/index.html create mode 100644 files/ja/web/javascript/guide/keyed_collections/index.html create mode 100644 files/ja/web/javascript/guide/liveconnect_overview/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/break_statement/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/continue_statement/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/do...while_statement/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/for_statement/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/label_statement/index.html create mode 100644 files/ja/web/javascript/guide/loop_statements/while_statement/index.html create mode 100644 files/ja/web/javascript/guide/loops_and_iteration/index.html create mode 100644 files/ja/web/javascript/guide/meta_programming/index.html create mode 100644 files/ja/web/javascript/guide/modules/index.html create mode 100644 files/ja/web/javascript/guide/numbers_and_dates/index.html create mode 100644 files/ja/web/javascript/guide/object_manipulation_statements/index.html create mode 100644 files/ja/web/javascript/guide/objects_and_properties/index.html create mode 100644 files/ja/web/javascript/guide/obsolete_pages/index.html create mode 100644 files/ja/web/javascript/guide/obsolete_pages/predefined_core_objects/function_object/index.html create mode 100644 files/ja/web/javascript/guide/operators/arithmetic_operators/index.html create mode 100644 files/ja/web/javascript/guide/operators/assignment_operators/index.html create mode 100644 files/ja/web/javascript/guide/operators/comparison_operators/index.html create mode 100644 files/ja/web/javascript/guide/operators/logical_operators/index.html create mode 100644 files/ja/web/javascript/guide/operators/special_operators/index.html create mode 100644 files/ja/web/javascript/guide/operators/string_operators/index.html create mode 100644 files/ja/web/javascript/guide/predefined_functions/escape_and_unescape_functions/index.html create mode 100644 files/ja/web/javascript/guide/predefined_functions/eval_function/index.html create mode 100644 files/ja/web/javascript/guide/predefined_functions/index.html create mode 100644 files/ja/web/javascript/guide/regular_expressions/assertions/index.html create mode 100644 files/ja/web/javascript/guide/regular_expressions/character_classes/index.html create mode 100644 files/ja/web/javascript/guide/regular_expressions/groups_and_ranges/index.html create mode 100644 files/ja/web/javascript/guide/regular_expressions/index.html create mode 100644 files/ja/web/javascript/guide/regular_expressions/quantifiers/index.html create mode 100644 files/ja/web/javascript/guide/text_formatting/index.html create mode 100644 files/ja/web/javascript/guide/the_employee_example/creating_the_hierarchy/index.html create mode 100644 files/ja/web/javascript/guide/the_employee_example/index.html create mode 100644 files/ja/web/javascript/guide/the_employee_example/object_properties/adding_properties/index.html create mode 100644 files/ja/web/javascript/guide/the_employee_example/object_properties/index.html create mode 100644 files/ja/web/javascript/guide/the_employee_example/object_properties/inheriting_properties/index.html create mode 100644 files/ja/web/javascript/guide/using_promises/index.html create mode 100644 files/ja/web/javascript/guide/using_the_arguments_object/index.html create mode 100644 files/ja/web/javascript/guide/variables/index.html create mode 100644 files/ja/web/javascript/guide/working_with_objects/index.html create mode 100644 files/ja/web/javascript/guide/writing_a_regular_expression_pattern/index.html (limited to 'files/ja/web/javascript/guide') diff --git a/files/ja/web/javascript/guide/class-based_vs._prototype-based_languages/index.html b/files/ja/web/javascript/guide/class-based_vs._prototype-based_languages/index.html new file mode 100644 index 0000000000..800f222ea4 --- /dev/null +++ b/files/ja/web/javascript/guide/class-based_vs._prototype-based_languages/index.html @@ -0,0 +1,25 @@ +--- +title: Class-Based vs. Prototype-Based Languages +slug: Web/JavaScript/Guide/Class-Based_vs._Prototype-Based_Languages +--- +

クラスベース言語とプロトタイプベース言語

+

Java や C++ といったクラスベースのオブジェクト指向言語はクラスとインスタンスという 2 つの異なる実体があるという概念に基づいています。

+ +

JavaScript のようなプロトタイプベース言語はこの区別がありません。単にオブジェクトがあるだけです。プロトタイプベース言語には原型的なオブジェクトという概念があります。このオブジェクトは新しいオブジェクトの初期プロパティを取得する元になるテンプレートとして使用されます。どのオブジェクトもそれ独自のプロパティを指定できます。オブジェクト作成時にも実行時にも可能です。さらに、どのオブジェクトも別のオブジェクトに対するプロトタイプとして関連付けることができます。2 つ目のオブジェクトが 1 つ目のオブジェクトのプロトタイプを共有するということもできます。

+

クラスの定義

+

クラスベース言語ではクラス定義ごとにクラスを定義します。定義では特殊なメソッドを指定してそのクラスのインスタンスを作成することができます。そのようなメソッドはコンストラクタと呼びます。コンストラクタメソッドはインスタンスのプロパティに対する初期値を指定することができます。また、作成時に他の適当な処理を実行することもできます。new 演算子をコンストラクタメソッドと一緒に用いることでクラスのインスタンスを作成できます。

+

JavaScript は同様のモデルに従っていますが、コンストラクタと別になっているクラス定義がありません。その代わりに、プロパティと値からなる特定の初期的なセットを持つオブジェクトを作成するコンストラクタ関数を定義します。どの JavaScript 関数もコンストラクタとして使用できます。new 演算子をコンストラクタ関数とともに使用することで新しいオブジェクトを作成します。

+

サブクラスと継承

+

クラスベース言語ではクラス定義を通じてクラスの階層を作ります。クラス定義では新しいクラスがある既存のクラスのサブクラスになるように指定することができます。サブクラスはスーパークラスの全プロパティを継承します。さらに新しくプロパティを追加したり継承したものを変更することもできます。例えば、Employee クラスが name および dept プロパティのみを含んでおり、Manager は reports プロパティを追加する Employee のサブクラスであるとします。この場合、Manager クラスのインスタンスは name、dept、reports という 3 つのプロパティをすべて持つことになります。

+

JavaScript では、原型的なオブジェクトをどのコンストラクタ関数にも結びつけることができるようにして継承を実装しています。そのため、全く同じような Employee と Manager の例を作成することができますが、使用する用語が若干異なります。まず、Employee コンストラクタ関数を定義します。これは name および dept プロパティを指定します。次に Manager コンストラクタ関数を定義します。これは reports プロパティを指定します。最後に新しい Employee オブジェクトを Manager コンストラクタ関数に対するプロトタイプとして代入します。そして新しい Manager を作成すると、このオブジェクトは Employee オブジェクトから name および dept プロパティを継承します。

+

プロパティの追加と削除

+

クラスベース言語では一般的にクラスをコンパイル時に生成し、コンパイル時または実行時にクラスのインスタンスを作成します。クラス定義後にそのクラスのプロパティの数や型を変更することはできません。しかし、JavaScript ではどんなオブジェクトでも実行時にプロパティを追加したり削除したりすることができます。あるオブジェクトのセットでプロトタイプとして使用されているオブジェクトにプロパティを追加すると、そのプロトタイプの使用元であるオブジェクトにも新しいプロパティが追加されます。

+

違いの概要

+

次の表でこれらの違いをいくつか短くまとめてみます。この章の残りで、JavaScript のコンストラクタとプロトタイプを用いてオブジェクト階層を作成することについての詳細を説明していきます。また、この方法が Java ではどう変わるかという比較もします。

+ +
クラスベース (Java) プロトタイプベース (JavaScript)
クラスとインスタンスは異なる実体である。 すべてのオブジェクトはインスタンスである。
クラス定義を用いてクラスを定義する。また、コンストラクタメソッドを用いてクラスをインスタンス化する。 コンストラクタ関数を用いてオブジェクトのセットを定義し、作成する。
new 演算子を用いて単一のオブジェクトを作成する。 同じ。
既存のクラスのサブクラスを定義するクラス定義を用いてオブジェクト階層を構築する。 コンストラクタ関数に結びつけられたプロトタイプとしてオブジェクトを代入することでオブジェクト階層を構築する。
クラスチェーンに従ってプロパティを継承する。 プロトタイプチェーンに従ってプロパティを継承する。
クラス定義がクラスの全インスタンスの全プロパティを指定する。実行時に動的にプロパティを追加することはできない。 コンストラクタ関数またはプロトタイプがプロパティの初期セットを指定する。個々のオブジェクトやオブジェクトの全体のセットに動的にプロパティを追加したり、それらからプロパティを除去したりできる。
+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Predefined_Core_Objects:String_Object", "Core_JavaScript_1.5_Guide:The_Employee_Example") }}

+
+

{{ languages( { "zh-tw": "zh_tw/Core_JavaScript_1.5_教學/以類別為基礎的語言_vs._以原型為基礎的語言", "en": "en/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages", "es": "es/Gu\u00eda_JavaScript_1.5/Lenguajes_basados_en_clases_frente_a_basados_en_prototipos", "fr": "fr/Guide_JavaScript_1.5/Langages_bas\u00e9s_sur_les_classes_et_langages_bas\u00e9s_sur_les_prototypes", "pl": "pl/Przewodnik_po_j\u0119zyku_JavaScript_1.5/J\u0119zyki_oparte_na_klasach_vs._oparte_na_prototypach", "zh-cn": "cn/Core_JavaScript_1.5_Guide/Class-Based_vs._Prototype-Based_Languages" } ) }}

diff --git a/files/ja/web/javascript/guide/control_flow_and_error_handling/index.html b/files/ja/web/javascript/guide/control_flow_and_error_handling/index.html new file mode 100644 index 0000000000..f9c13b952c --- /dev/null +++ b/files/ja/web/javascript/guide/control_flow_and_error_handling/index.html @@ -0,0 +1,457 @@ +--- +title: 制御フローとエラー処理 +slug: Web/JavaScript/Guide/Control_flow_and_error_handling +tags: + - Beginner + - Decision making + - Error Handling + - Flow control + - Guide + - JavaScript + - Logic + - control + - 'l10n:priority' + - statements +translation_of: Web/JavaScript/Guide/Control_flow_and_error_handling +--- +

{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}

+ +

JavaScript は、特に制御フロー文についてはコンパクトな文のセットに対応しており、アプリケーションに多様な対話的機能を組み込むために利用することができます。この節ではこれらの文の概要を説明します。

+ +

JavaScript リファレンスには、この章で紹介する文についての完全な詳細が載っています。また、JavaScript のコードではセミコロン (;) 文字で文を区切ります。

+ +

あらゆる JavaScript の式は、文でもあります。式に関する詳細については式と演算子を参照ください。

+ +

ブロック文

+ +

最も基本的な文はブロック文で、文のグループ化に使います。ブロックは、一組の波括弧で区切られます。

+ +
{
+  statement_1;
+  statement_2;
+  ⋮
+  statement_n;
+}
+
+ +

+ +

ブロック文は一般に制御フロー文 (if, for, while) で用いられます。

+ +
while (x < 10) {
+  x++;
+}
+
+ +

ここでは { x++; } がブロック文となります。

+ +
+

重要: ECMAScript 2015 (6th edition) より前の JavaScript にはブロックスコープがありません。古い JavaScript では、ブロック内で導入された変数のスコープは、そのブロックがある関数やスクリプトになり、それらの変数を設定した影響は、そのブロックを越えて持続します。つまり、ブロック文はスコープを定義しないということです。

+ +

「単独の」ブロックも正しい構文ですが、C や Java のブロックで提供されるものとは異なる結果をもたらします。例えば、

+ +
var x = 1;
+{
+  var x = 2;
+}
+console.log(x); // 2 を出力
+
+ +

ここで 2 が出力されるのは、ブロック内の var x 文がブロックの前の var x 文と同じスコープ内にあるためです。(C や Java では、同様のコードで 1 が出力されます。)

+ +

ECMAScript 2015 からは、let 文や const による変数宣言はブロックスコープとなります。詳しくは {{jsxref("Statements/let", "let")}} 文や {{jsxref("Statements/const", "const")}} のリファレンスページをご覧ください。

+
+ +

条件文

+ +

条件文は、指定した条件が true の場合に実行する命令の集まりです。JavaScript は if...elseswitch の 2 つの条件文に対応しています。

+ +

if...else

+ +

if を使用すると、論理条件が true の場合に文を実行することができます。任意の else 節を使用すると、条件が false の場合にも文を実行することができます。

+ +

if 文は次のように使用します。

+ +
if (condition) {
+  statement_1;
+} else {
+  statement_2;
+}
+ +

条件は、true または false と評価される任意の式にすることができます。(truefalse の評価の説明については、Boolean を参照してください。)

+ +

条件が true と評価された場合、statement_1 が実行されます。そうでなければ、statement_2 が実行されます。statement_1statement_2 は、入れ子になった if 文も含めて、任意の文にすることができます。

+ +

以下のように、else if を使用した文を組み合わせて、複数の条件を順番にテストすることもできます。

+ +
if (condition_1) {
+  statement_1;
+} else if (condition_2) {
+  statement_2;
+} else if (condition_n) {
+  statement_n;
+} else {
+  statement_last;
+}
+
+ +

複数の条件がある場合、true と評価された最初の論理条件のみが実行されます。複数の文を実行するには、ブロックステートメント ({ … }) 内にグループ化します。

+ +

ベストプラクティス

+ +

一般的に、常にブロック文を使用するのが優れた方法です。特に if 文を入れ子にしたコードで有効です。

+ +
if (condition) {
+  statement_1_runs_if_condition_is_true;
+  statement_2_runs_if_condition_is_true;
+} else {
+  statement_3_runs_if_condition_is_false;
+  statement_4_runs_if_condition_is_false;
+}
+
+ +

条件式内で単純な代入を行わないでください。コードを一見した際に、代入を等値条件と見間違えるおそれがあるためです。

+ +

例えば、このようにはコードを書かないでください。

+ +
// "x == y" と読み間違えるおそれがある。
+if (x = y) {
+  /* ここに文が来る */
+}
+
+ +

条件式で代入を行う必要がある場合、一般的な方法は次のように、代入式をさらに丸括弧でくくることです。

+ +
if ((x = y)) {
+  /* ここに文が来る */
+}
+
+ +

false と評価される値

+ +

以下の値は false と評価されます (また、{{Glossary("Falsy")}} な値と呼ばれています)。

+ + + +

上記以外の—オブジェクトを含む—すべての値は、条件文に渡されると true と評価されます。

+ +
+

注意: プリミティブな真偽値の truefalse を、{{jsxref("Boolean")}} オブジェクトの true や false という値と混同しないでください。

+ +

例:

+ +
var b = new Boolean(false);
+if (b)         // この条件は true に評価される
+if (b == true) // この条件は false に評価される
+
+
+ +

+ +

次の例で、関数 checkDataText オブジェクトに含まれている文字数が 3 である場合に true を返し、そうでない場合はアラートを表示して false を返します。

+ +
function checkData() {
+  if (document.form1.threeChar.value.length == 3) {
+    return true;
+  } else {
+    alert(
+        'Enter exactly three characters. ' +
+        `${document.form1.threeChar.value} is not valid.`);
+    return false;
+  }
+}
+
+ +

switch

+ +

switch 文を使うと、プログラムは式を評価し、その式の値を case ラベルと照合します。一致すると、プログラムはそのラベルに関連付けられた文を実行します。

+ +

switch 文は次のようになります。

+ +
switch (expression) {
+  case label_1:
+    statements_1
+    [break;]
+  case label_2:
+    statements_2
+    [break;]
+    …
+  default:
+    statements_def
+    [break;]
+}
+
+ +

JavaScript は上記の switch 文を次のように評価します。

+ + + +

break 文

+ +

オプションの break 文は、それぞれの case 節と関連付けられ、該当する文が実行されるとプログラムが switch から抜け出し、switch の次の文から実行が継続されることを保証します。break が省略されると、プログラムは switch 文の内部の実行を続けます (そして、次の case を順番に評価します)。

+ +

+ +

次の例では、fruittype が 'Bananas' と評価された場合、case 'Bananas' に一致して、それに関連付けら cv れた文を実行します。break 文に出くわすとプログラムは switch から抜けて、switch の後に続く文を実行します。break を省略すると、case 'Cherries' の文も実行されます。

+ +
switch (fruittype) {
+  case 'Oranges':
+    console.log('Oranges are $0.59 a pound.');
+    break;
+  case 'Apples':
+    console.log('Apples are $0.32 a pound.');
+    break;
+  case 'Bananas':
+    console.log('Bananas are $0.48 a pound.');
+    break;
+  case 'Cherries':
+    console.log('Cherries are $3.00 a pound.');
+    break;
+  case 'Mangoes':
+    console.log('Mangoes are $0.56 a pound.');
+    break;
+  case 'Papayas':
+    console.log('Mangoes and papayas are $2.79 a pound.');
+    break;
+  default:
+   console.log(`Sorry, we are out of ${fruittype}.`);
+}
+console.log("Is there anything else you'd like?");
+ +

例外処理文

+ +

throw 文を使用して例外を発生させ、try...catch 文を使用して例外を処理することができます。

+ + + +

例外の型

+ +

JavaScript では、ほぼどのようなオブジェクトでも例外として投げることができます。とはいえ、必ずしも投げられるオブジェクトすべてが同等に作られているわけではありません。数値や文字列をエラーとして投げる方法がよく用いられますが、こうした用途のために特別に作られた例外データ型を使用した方がより効率的な場合もあります。

+ + + +

throw

+ +

throw 文は、例外を投げるために使用します。例外を投げるには、投げたい値を含む式を指定してください。

+ +
throw expression;
+
+ +

特定の型の式だけではなく、あらゆる式を投げることができます。下記のコードでは、さまざまな型の例外を投げています。

+ +
throw 'Error2';   // 文字列型
+throw 42;         // 数値型
+throw true;       // 論理型
+throw {toString: function() { return "これはオブジェクトです!"; } };
+
+ +
+

メモ: 例外を投げる際にオブジェクトを指定することができます。そして、catch ブロックでそのオブジェクトのプロパティを参照することができます。

+
+ +
// UserException というオブジェクト型を作成
+function UserException(message) {
+  this.message = message;
+  this.name = 'UserException';
+}
+
+// 文字列として使用されるとき(例 : エラーコンソール上)に
+// 例外を整形する
+UserException.prototype.toString = function() {
+  return `${this.name}: "${this.message}"`;
+}
+
+// UserException のインスタンスを作成し、それを投げる
+throw new UserException('Value too high');
+ +

try...catch

+ +

try...catch 文はテストしたい文のブロックを指定し、さらに投げられる例外に対する 1 つ以上の対処方法を指定します。例外が投げられると、try...catch 文がそれを受け取ります。

+ +

try...catch 文は 1 つの try ブロックと 0 個以上の catch ブロックで構成されます。try ブロックは 1 つ以上の文を含み、catch ブロックは try ブロックで例外が投げられた場合の処理を指定する文が含まれます。

+ +

要するに、成功した場合に実行したい try ブロックと、失敗した場合に制御を移行させたい catch ブロックで構成されています。try ブロック内(もしくは try ブロック内から呼び出された関数内)のいずれかの文が例外を投げると、制御はすぐに catch ブロックに移ります。try ブロックで例外が投げられなかった場合、catch ブロックはスキップされます。finally ブロックは try および catch ブロックを実行した後に実行しますが、try...catch 文の後に続く文より先に実行されます。

+ +

次の例では try...catch 文を使用しています。この例では渡された値に基づいて、配列から月の名前を取り出す関数を実行します。値に対応する月の数字 (112) が無い場合は "InvalidMonthNo" という値を持つ例外が投げられ、catch ブロックの中の文は monthName という変数に 'unknown' という値をセットします。

+ +
function getMonthName(mo) {
+  mo = mo - 1; // 月の数字を配列のインデックスに合わせる (1 = Jan, 12 = Dec)
+  let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
+                'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+  if (months[mo]) {
+    return months[mo];
+  } else {
+    throw 'InvalidMonthNo'; // throw キーワードが使われている
+  }
+}
+
+try { // 実行を試みる文
+  monthName = getMonthName(myMonth); // この関数が例外を投げる場合がある
+}
+catch (e) {
+  monthName = 'unknown';
+  logMyErrors(e); // 例外オブジェクトをエラーハンドラーに渡す
+}
+
+ +

catch ブロック

+ +

catch ブロックを用いることで、try ブロックで生じうるすべての例外を扱うことができます。

+ +
catch (catchID) {
+  statements
+}
+
+ +

catch ブロックには、throw 文で指定される値を保持しておく識別子 (上記の構文における catchID) を指定します。投げられた例外についての情報を得るのに、この識別子を使います。

+ +

JavaScript は catch ブロックに入るときにこの識別子を作成します。識別子は catch ブロックの区間だけ存続します。つまり、catch ブロックの実行が終わると、その識別子はもう使えなくなります。

+ +

例えば、次のコードは例外を投げます。例外が生じると、制御が catch ブロックに移ります。

+ +
try {
+  throw 'myException'; // 例外を生成
+}
+catch (err) {
+  // ここには例外を扱う文が入る
+  logMyErrors(err);    // 例外オブジェクトをエラーハンドラに渡す
+}
+
+ +
+

ベストプラクティス: catch ブロック内でコンソールにエラーをログ出力する場合は、console.log() よりも console.error() がデバッグ目的では推奨されています。これはメッセージをエラーとして書式化し、ページによって生成されたエラーメッセージの一覧に追加します。

+
+ +

finally ブロック

+ +

finally ブロックは、try および catch ブロックの実行に実行される文が入ります。また、finally ブロックの中のコードは try…catch…finally に続く分が実行されるに実行されます。

+ +

また、finally ブロックは例外が発生するかどうかにかかわらず実行されるということに注意することも大切です。また、例外が発生したら、finally ブロック内の文は発生した例外が catch ブロックで処理されなくても実行されます。

+ +

finally ブロックを使用することで、例外発生時に適切にスクリプトを停止させることができます。例えば、スクリプトで使用していたリソースを解放しなければならない場合などです。

+ +

次の例ではファイルを開き、そのファイルを使用する文を実行します (サーバー側 JavaScript ではファイルにアクセスできます)。ファイルを開いている間に発生すると、スクリプトが停止する前に finally ブロックでそのファイルを閉じます。ここで finally を使用することで、エラーが発生した場合であってもファイルが開かれたままにならないことを保証します。

+ +
openMyFile();
+try {
+  writeMyFile(theData); // ここでエラーが投げられる可能性がある
+} catch(e) {
+  handleError(e); // エラーを受け取り、それを処理する
+} finally {
+  closeMyFile(); // 常にリソースが閉じられる
+}
+
+ +

finally ブロックが値を返す場合、その値は try および catch ブロックの return 文にかかわらず try…catch…finally 全体が生成する返値になります。

+ +
function f() {
+  try {
+    console.log(0);
+    throw 'bogus';
+  } catch(e) {
+    console.log(1);
+    return true;    // この返値は、finally ブロックが
+                    // 完了するまで保留となる
+    console.log(2); // ここまで到達しない
+  } finally {
+    console.log(3);
+    return false;   // 直前の "return" が上書きされる
+    console.log(4); // ここまで到達しない
+  }
+  // ここで "return false" が実行される
+  console.log(5);   // ここまで到達しない
+}
+console.log(f()); // 0, 1, 3, false
+
+ +

finally ブロックによる返値の上書きは、catch ブロック内で発生した、または再発生した例外にも適用されます。

+ +
function f() {
+  try {
+    throw 'bogus';
+  } catch(e) {
+    console.log('caught inner "bogus"');
+    throw e; // この throw 文は finally ブロックが
+             // 完了するまで保留になる
+  } finally {
+    return false; // 直前の "throw" が上書きされる
+  }
+  // ここで "return false" が実行される
+}
+
+try {
+  console.log(f());
+} catch(e) {
+  // ここには到達しない
+  // f() を実行した際、`finally` ブロックが false を返し、
+  // 上記の `catch` の中にある `throw` を上書する
+  console.log('caught outer "bogus"');
+}
+
+// OUTPUT
+// caught inner "bogus"
+// false
+ +

try...catch 文の入れ子

+ +

1 つ以上の try...catch 文を入れ子にすることができます。

+ +

内側の try...catch 文に catch ブロックがない場合は次のようになります。

+ +
    +
  1. finally ブロックを含む必要があります。そして、
  2. +
  3. 囲んでいる try...catch 文の catch ブロックがエラーの照合先としてチェックされます。
  4. +
+ +

詳しくは、try...catch の中の nested try-blocks を参照してください。

+ +

Error オブジェクトの活用

+ +

エラーの種類に応じて、namemessage プロパティを使ってより詳細なメッセージが得られるようにすることができます。

+ +

nameError のクラス全般 (例えば DOMExceptionError) を表し、一方 message は通常、エラーオブジェクトを文字列に変換したものより簡潔なメッセージを表します。

+ +

独自の例外を発生させて、これらのプロパティを有効に活用したい場合 (catch ブロックで独自の例外とシステムの例外とを区別したくない場合など)、Error コンストラクターが使えます。

+ +

例えば、次のようにします。

+ +
function doSomethingErrorProne() {
+  if (ourCodeMakesAMistake()) {
+    throw (new Error('The message'));
+  } else {
+    doSomethingToGetAJavascriptError();
+  }
+}
+⋮
+try {
+  doSomethingErrorProne();
+} catch (e) {               // `console.error()` を実際に使ってログを出力してみます
+  console.error(e.name);    // 'Error' をログ出力
+  console.error(e.message); // 'The message'、または JavaScript のエラーメッセージをログ出力
+}
+
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Grammar_and_types", "Web/JavaScript/Guide/Loops_and_iteration")}}

diff --git a/files/ja/web/javascript/guide/core_language_features/index.html b/files/ja/web/javascript/guide/core_language_features/index.html new file mode 100644 index 0000000000..2161ec589e --- /dev/null +++ b/files/ja/web/javascript/guide/core_language_features/index.html @@ -0,0 +1,10 @@ +--- +title: Core Language Features +slug: Web/JavaScript/Guide/Core_Language_Features +--- +
+{{page("/ja/docs/Core_JavaScript_1.5_Guide/Values()")}} +{{page("/ja/docs/Core_JavaScript_1.5_Guide/Variables()")}} +{{page("/ja/docs/Core_JavaScript_1.5_Guide/Constants()")}} +{{page("/ja/docs/Core_JavaScript_1.5_Guide/Literals()")}} +{{page("/ja/docs/Core_JavaScript_1.5_Guide/Unicode()")}}
diff --git a/files/ja/web/javascript/guide/creating_a_regular_expression/index.html b/files/ja/web/javascript/guide/creating_a_regular_expression/index.html new file mode 100644 index 0000000000..19935b8b55 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_a_regular_expression/index.html @@ -0,0 +1,31 @@ +--- +title: 正規表現の作成 +slug: Web/JavaScript/Guide/Creating_a_Regular_Expression +--- +

正規表現の作成

+

正規表現は 2 つの方法で作ることができます。

+ +
var re = /ab+c/; 
+
+
+
+
+ 正規表現リテラルでは、スクリプトが評価されるときにその正規表現をコンパイルします。正規表現を定数として残しておくときは、この方法を使用するとよりよいパフォーマンスが得られます。
+
+
+
+ +
var re = new RegExp("ab+c"); 
+
+
+
+
+ コンストラクタ関数を使用すると、実行時にその正規表現をコンパイルします。正規表現パターンが変わることがわかっている場合や、パターンがわからない場合、ユーザが入力するなど、別のソースからパターンを取得する場合はコンストラクタ関数を使用してください。
+
+
+
+

{{ PreviousNext("JavaScript/Guide/Operators/Special_Operators", "JavaScript/Guide/Writing_a_Regular_Expression_Pattern") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/defining_getters_and_setters/index.html b/files/ja/web/javascript/guide/creating_new_objects/defining_getters_and_setters/index.html new file mode 100644 index 0000000000..8ee9381575 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/defining_getters_and_setters/index.html @@ -0,0 +1,89 @@ +--- +title: ゲッターとセッターの定義 +slug: Web/JavaScript/Guide/Creating_New_Objects/Defining_Getters_and_Setters +--- +

ゲッターとセッターの定義

+ +

ゲッターはある属性の値を取得するメソッドです。セッターは属性に値を設定するメソッドです。全ての定義済みコアオブジェクトと、新しいプロパティの追加をサポートしているユーザ定義オブジェクトに対してゲッターとセッターを定義できます。ゲッターとセッターの定義にはオブジェクトリテラル構文を使用します。

+ +

以下の例では、ユーザ定義オブジェクト o についてゲッターとセッターがどのように機能するかを説明します。JavaScript シェル とは JavaScript コードをバッチモードで、またはインタラクティブにテストすることができる、開発者向けのアプリケーションのことです。

+ +

o オブジェクトのプロパティは以下のとおりです。

+ + + +
js> o = new Object;
+[object Object]
+js> o = {a:7, get b() {return this.a+1; }, set c(x) {this.a = x/2}};
+[object Object]
+js> o.a
+7
+js> o.b
+8
+js> o.c = 50
+js> o.a
+25
+js>
+
+ +

次の例では、 Date プロトタイプを拡張して定義済み Date クラスの全インスタンスに year プロパティを追加する様子を表しています。Date クラスの既存の getFullYear および setFullYear メソッドを使用して year プロパティのゲッターとセッターを実装します。

+ +

これらの文は year プロパティに対するゲッターとセッターを定義しています。

+ +
js> var d = Date.prototype;
+js> d.__defineGetter__("year", function() { return this.getFullYear(); });
+js> d.__defineSetter__("year", function(y) { this.setFullYear(y); });
+
+ +

これらの文は Date オブジェクトで定義したゲッターとセッターを使用しています。

+ +
js> var now = new Date;
+js> print(now.year);
+2000
+js> now.year=2001;
+987617605170
+js> print(now);
+Wed Apr 18 11:13:25 GMT-0700 (Pacific Daylight Time) 2001
+
+ +
JavaScript 1.5 の開発期間中に getter =setter = といった式を使用して新しいゲッターやセッターを既存のオブジェクトで定義するようになっていた時期がありました。この構文は現在は廃止予定であり、現行の JS 1.5 エンジンでは警告を発します。また、将来的には構文エラーになります。使用を避けるようにしてください
+ +

 

+ +

概要

+ +

原則的にゲッターとセッターは次のどちらかに属します。

+ + + +

オブジェクト初期化子 を用いてゲッターやセッターを定義する際には、ゲッターメソッドの先頭に get を、セッターメソッドの先頭に set をそれぞれ付けなくてはなりません。セッターメソッドはセットする新しい値を受けわたすための引数を 1 つだけ持ちます。ゲッターメソッドはパラメータを受け取るようにしてはいけません。

+ +
o = {
+  a:7,
+  get b() { return this.a+1; },
+  set c(x) { this.a = x/2; }
+};
+
+ +

ゲッターもセッターも、__defineGetter__ および __defineSetter__ という 2 つの特別なメソッドを用いて、オブジェクト作成後でも、そのオブジェクトに追加することができます。両メソッドの第 1 引数にはそのゲッターやセッターの名前を文字列で指定します。第 2 引数にはゲッターやセッターとして呼び出す関数を指定します。前の例を別の方法で実装したものを以下に示します。

+ +
o.__defineGetter__("b", function() { return this.a+1; });
+o.__defineSetter__("c", function(x) { this.a = x/2; });
+
+ +

2 つの形式のうちどちらを選択するかはあなたのプログラミングスタイルや、目の前の課題次第によります。プロトタイプの定義時にオブジェクト初期化子を使用しているのであれば、最初の形式を選択するのがよいでしょう。この形式はよりコンパクトかつ自然です。ゲッターやセッターを後から追加する必要がある場合は、プロトタイプや特定のオブジェクトを書いていないため、第 2 の形式しか使用できません。第 2 の形式は JavaScript の動的性質をおそらく最もよく表していますが、コードが可読性が下がったり、理解しづらいものとなることがあります。

+ +
+

Firefox 3.0 より前のバージョンではゲッターとセッターが DOM 要素に対してサポートされていません。古いバージョンの Firefox では例外を投げることなく失敗します。そのときに例外が必要であれば、HTMLElement のプロトタイプを変更し (HTMLElement.prototype.__define{{ mediawiki.external('SG') }}etter__)、例外を投げるようにして回避してください。

+ +

Firefox 3.0 では、定義済みのプロパティでゲッターとセッターを定義すると例外が投げられます。そのプロパティは事前に削除しておく必要があります。これは古いバージョンの Firefox には当てはまりません。

+
+ +

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Using_this_for_Object_References", "JavaScript/Guide/Creating_New_Objects/Deleting_Properties") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/defining_methods/index.html b/files/ja/web/javascript/guide/creating_new_objects/defining_methods/index.html new file mode 100644 index 0000000000..74731a99d1 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/defining_methods/index.html @@ -0,0 +1,39 @@ +--- +title: メソッドの定義 +slug: Web/JavaScript/Guide/Creating_New_Objects/Defining_Methods +--- +

メソッドの定義

+

メソッドとはあるオブジェクトに結びつけられた関数のことです。メソッドは、通常の関数の定義と同じ方法で定義します。既存のオブジェクトに関数を結びつけるには次の構文を使用します。

+
object.methodname = function_name
+
+

ここで、object は既存のオブジェクトを、methodname はメソッドに割り当てる名前を、function_name は関数の名前をそれぞれ表しています。

+

すると、次のようにしてオブジェクトのコンテキストでそのメソッドを呼び出すことができます。

+
object.methodname(params);
+
+

オブジェクトのコンストラクタ関数にメソッドの定義を含めることで、あるオブジェクトの種類についてのメソッドを定義することができます。例えば、以前に定義した car オブジェクトのプロパティを整形して表示する関数を定義します。

+
function displayCar() {
+   var result = "A Beautiful " + this.year + " " + this.make
+      + " " + this.model;
+   pretty_print(result);
+}
+
+

pretty_print は水平方向の罫線と文字列を表示する関数です。this を使用してそのメソッドを抱えているオブジェクトを参照しています。

+

次の文

+
this.displayCar = displayCar;
+
+

をオブジェクトの定義に加えることで、この関数を car のメソッドにすることができます。そうすると、car の完全な定義は次のようになります。

+
function car(make, model, year, owner) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+   this.owner = owner;
+   this.displayCar = displayCar;
+}
+
+

すると、次のようにして各オブジェクトについて displayCar メソッドを呼び出すことができます。

+
car1.displayCar()
+car2.displayCar()
+
+

こうすると次の図のような出力が得られます。

+

Image:obja.gif 図 7.1:メソッドの出力の表示

+

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Defining_Properties_for_an_Object_Type", "JavaScript/Guide/Creating_New_Objects/Using_this_for_Object_References") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/defining_properties_for_an_object_type/index.html b/files/ja/web/javascript/guide/creating_new_objects/defining_properties_for_an_object_type/index.html new file mode 100644 index 0000000000..b5136b203e --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/defining_properties_for_an_object_type/index.html @@ -0,0 +1,13 @@ +--- +title: Defining Properties for an Object Type +slug: >- + Web/JavaScript/Guide/Creating_New_Objects/Defining_Properties_for_an_Object_Type +--- +

あるオブジェクトの種類に対するプロパティの定義

+

prototype プロパティを用いて、定義済みのオブジェクトの種類にプロパティを追加することができます。この方法では、指定した種類のすべてのオブジェクトで共有されるプロパティを定義することになります。そのオブジェクトのあるインスタンス 1 つだけということではありません。次のコードは color プロパティを car という種類の全オブジェクトに追加し、値をオブジェクト car1color プロパティに代入します。

+
car.prototype.color=null;
+car1.color="black";
+
+

詳しくは コア JavaScript リファレンス 内の Function オブジェクトの prototype プロパティ を参照してください。

+ +

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Indexing_Object_Properties", "JavaScript/Guide/Creating_New_Objects/Defining_Methods") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/deleting_properties/index.html b/files/ja/web/javascript/guide/creating_new_objects/deleting_properties/index.html new file mode 100644 index 0000000000..749ee722f5 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/deleting_properties/index.html @@ -0,0 +1,20 @@ +--- +title: プロパティの削除 +slug: Web/JavaScript/Guide/Creating_New_Objects/Deleting_Properties +--- +

プロパティの削除

+

delete 演算子を用いることでプロパティを除去することができます。次のコードでプロパティの除去方法を示します。

+
// 新しいオブジェクト myobj を作成。2 つのプロパティ、a および b を持つ。
+myobj = new Object;
+myobj.a = 5;
+myobj.b = 12;
+
+// a プロパティを除去。myobj には b プロパティだけが残っている。
+delete myobj.a;
+
+

delete を使用することでグローバル変数を削除することもできます。ただし、これは var キーワードを使用せずにその変数を宣言した場合のみです。

+
g = 17;
+delete g;
+
+

さらなる情報については delete をご覧ください。

+

{{PreviousNext("JavaScript/Guide/Creating_New_Objects/Defining_Getters_and_Setters", "JavaScript/Guide/Predefined_Core_Objects")}}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/index.html b/files/ja/web/javascript/guide/creating_new_objects/index.html new file mode 100644 index 0000000000..0cbbc1753c --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/index.html @@ -0,0 +1,17 @@ +--- +title: 新しいオブジェクトの作成 +slug: Web/JavaScript/Guide/Creating_New_Objects +--- +

新しいオブジェクトの作成

+

JavaScript には多くの定義済みオブジェクトがあります。さらに、自分でオブジェクトを作り出すことができます。JavaScript 1.2 以降では、オブジェクト初期化子を用いてオブジェクトを作成できます。もう 1 つの方法として、まずコンストラクタ関数を作成し、それからその関数と new 演算子を用いてオブジェクトのインスタンスを作成することもできます。

+ +

{{ PreviousNext("JavaScript/Guide/Objects_and_Properties", "JavaScript/Guide/Creating_New_Objects/Using_Object_Initializers") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/indexing_object_properties/index.html b/files/ja/web/javascript/guide/creating_new_objects/indexing_object_properties/index.html new file mode 100644 index 0000000000..024de85654 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/indexing_object_properties/index.html @@ -0,0 +1,9 @@ +--- +title: オブジェクトのプロパティに対するインデックス付け +slug: Web/JavaScript/Guide/Creating_New_Objects/Indexing_Object_Properties +--- +

オブジェクトのプロパティのインデックス付け

+

JavaScript 1.0 では、オブジェクトのプロパティを、そのプロパティ名や順序のインデックスで参照できます。しかしながら、JavaScript 1.1 以降では、最初にプロパティをその名前で定義すると、常にその名前で参照しなければならず、また、最初にプロパティをインデックスで定義すると、常にそのインデックスで参照しなければなりません。

+

先の Car というオブジェクトの種類の例のようにコンストラクタ関数を用いてオブジェクトとそのプロパティを作成したとき、また、それぞれのプロパティを明示的に定義したとき(例:myCar.color = "red")に、これは適用されます。そのため、myCar{{ mediawiki.external(5) }} = "25 mpg" のように、最初にインデックスを用いてオブジェクトのプロパティを定義した場合、myCar{{ mediawiki.external(5) }} のようにそのプロパティを後から参照できるようになります。

+

このルールの例外は、forms 配列のように HTML から反映されたオブジェクトです。これらの配列内のオブジェクトは、その順番を表す数(文書内のどこにあるかに基づく)か、またはその名前(定義されている場合)のどちらかで常に参照できます。例えば、文書内の 2 番目の <FORM> タグが "myForm" という NAME 属性を持っている場合、document.forms{{ mediawiki.external(1) }}document.forms{{ mediawiki.external('\"myForm\"') }}document.myForm とすることでそのフォームを参照できます。

+

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Using_a_Constructor_Function", "JavaScript/Guide/Creating_New_Objects/Defining_Properties_for_an_Object_Type") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/using_a_constructor_function/index.html b/files/ja/web/javascript/guide/creating_new_objects/using_a_constructor_function/index.html new file mode 100644 index 0000000000..f3abc30e89 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/using_a_constructor_function/index.html @@ -0,0 +1,57 @@ +--- +title: コンストラクタ関数の使用 +slug: Web/JavaScript/Guide/Creating_New_Objects/Using_a_Constructor_Function +--- +

コンストラクタ関数の使用

+

もう 1 つの方法として、次の 2 つのステップでオブジェクトを作成することができます。

+
    +
  1. コンストラクタ関数を書くことでオブジェクトの種類を定義する。
  2. +
  3. new を用いてそのオブジェクトのインスタンスを作成する。
  4. +
+

オブジェクトの種類を定義するために、その名前、プロパティ、メソッドを定義する関数を作成する必要があります。例えば、車についてのオブジェクトの種類を作成したいとします。そしてこの種類のオブジェクトに car という名前を付け、make、model、および year というプロパティを持たせたいとします。こうするためには次のような関数を書きます。

+
function car(make, model, year) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+}
+
+

関数に渡された値に基づいてオブジェクトのプロパティに値を代入するために this を使用しています。

+

すると、次のようにして mycar というオブジェクトを作成することができるようになります。

+
mycar = new car("Eagle", "Talon TSi", 1993);
+
+

この文は mycar を作成し、そのプロパティ用に指定した値を代入します。その結果、mycar.make の値は "Eagle" という文字列、mycar.year は 1993 という整数というようになります。

+

new を呼び出すことで car オブジェクトをいくらでも作ることができます。

+
kenscar = new car("Nissan", "300ZX", 1992);
+vpgscar = new car("Mazda", "Miata", 1990);
+
+

それ自身別のオブジェクトであるというようなプロパティを持つオブジェクトを作ることができます。例えば、次のように person というオブジェクトを定義するとします。

+
function person(name, age, sex) {
+   this.name = name;
+   this.age = age;
+   this.sex = sex;
+}
+
+

そして、次のように 2 つの新しい person オブジェクトのインスタンスを作成します。

+
rand = new person("Rand McKinnon", 33, "M");
+ken = new person("Ken Jones", 39, "M");
+
+

次のようにして、car の定義を書き換えて、person オブジェクトをとる owner プロパティを持たせることができます。

+
function car(make, model, year, owner) {
+   this.make = make;
+   this.model = model;
+   this.year = year;
+   this.owner = owner;
+}
+
+

新しいオブジェクトのインスタンスを作成するために、次のようにします。

+
car1 = new car("Eagle", "Talon TSi", 1993, rand);
+car2 = new car("Nissan", "300ZX", 1992, ken);
+
+

新しいオブジェクトの作成時に文字列リテラルや整数値を渡す代わりに、上記の文ではオブジェクト rand および ken を所有者を表す引数として渡しています。car2 の所有者の名前を知りたい場合は次のプロパティにアクセスすることで可能になります。

+
car2.owner.name
+
+

以前に定義したオブジェクトにいつでもプロパティを追加できることに注意してください。例えば次の文

+
car1.color = "black"
+
+

はプロパティ color を car1 に追加し、それに "black" という値を代入します。しかしながら、この方法では他のどのオブジェクトにも影響を与えません。同じ種類の全オブジェクトに新しいプロパティを追加するには、そのプロパティを car というオブジェクトの種類の定義に追加する必要があります。

+

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Using_Object_Initializers", "JavaScript/Guide/Creating_New_Objects/Indexing_Object_Properties") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/using_object_initializers/index.html b/files/ja/web/javascript/guide/creating_new_objects/using_object_initializers/index.html new file mode 100644 index 0000000000..0a817b5407 --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/using_object_initializers/index.html @@ -0,0 +1,23 @@ +--- +title: オブジェクト初期化子の使用 +slug: Web/JavaScript/Guide/Creating_New_Objects/Using_Object_Initializers +--- +

オブジェクト初期化子の使用

+

コンストラクタ関数を使用してオブジェクトを作成する方法だけではなく、オブジェクト初期化子を使用してもオブジェクトを作成することができます。オブジェクト初期化子を使うことはリテラル表示を用いてオブジェクトを作成するということです。「オブジェクト初期化子」は C++ でも同じ意味で使用されている用語です。

+

オブジェクト初期化子を使用したオブジェクトの構文は次のとおりです。

+
var obj = { property_1:   value_1,   // property_# は識別子でもよい
+            2:            value_2,   // あるいは数値でもよい
+            ...,
+            "property_n": value_n }; // あるいは文字列でもよい
+
+

ここで、obj は新しいオブジェクトの名前を、各 property_i は識別子(名前、数値、文字列リテラルのいずれか)を、各 value_i はその値を property_i に代入する式をそれぞれ表しています。obj および代入部分はなくてもかまいません。このオブジェクトを別の場所で参照する必要がないのであれば変数に代入する必要はありません。(文が期待されているところにオブジェクトリテラルを置く場合、リテラルを丸括弧で囲み、ブロック文と間違われないようにする必要があるかもしれません。)

+

トップレベルのスクリプトでオブジェクト初期化子を使用してオブジェクトを作成した場合、JavaScript はオブジェクトリテラルを含む式を評価するたびにそのオブジェクトを解釈します。さらに、関数内で使用された初期化子はその関数が呼び出されるたびに作成されます。

+

次の文は、式 cond が true の場合かつその場合に限り、あるオブジェクトを作成し、それを変数 x に代入します。

+
if (cond) x = {hi:"there"};
+
+

次の例は 3 つのプロパティを持つ myHonda を作成します。engine プロパティは自らもプロパティを持つオブジェクトでもあることに注意してください。

+
myHonda = {color:"red",wheels:4,engine:{cylinders:4,size:2.2}};
+
+

オブジェクト初期化子を使用して配列を作成することもできます。配列リテラル を参照してください。

+

JavaScript 1.1 以前ではオブジェクト初期化子を使用することはできません。コンストラクタ関数を使用するか、他のオブジェクトが備えているそのような用途の関数を使用しないとオブジェクトを作成できません。コンストラクタ関数の使用 をご覧ください。

+

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects", "JavaScript/Guide/Creating_New_Objects/Using_a_Constructor_Function") }}

diff --git a/files/ja/web/javascript/guide/creating_new_objects/using_this_for_object_references/index.html b/files/ja/web/javascript/guide/creating_new_objects/using_this_for_object_references/index.html new file mode 100644 index 0000000000..5fbd3b8aff --- /dev/null +++ b/files/ja/web/javascript/guide/creating_new_objects/using_this_for_object_references/index.html @@ -0,0 +1,25 @@ +--- +title: this を用いたオブジェクト参照 +slug: Web/JavaScript/Guide/Creating_New_Objects/Using_this_for_Object_References +--- +

this を用いたオブジェクト参照

+

JavaScript にはカレントオブジェクトを参照するメソッド内で使用できる特殊なキーワード、this があります。例えば、あるオブジェクトの value プロパティの妥当性を確認する validate という関数があるとします。関数にはそのオブジェクトと、上限および下限の値を渡します。

+
function validate(obj, lowval, hival) {
+   if ((obj.value < lowval) || (obj.value > hival))
+      alert("Invalid Value!");
+}
+
+

各フォーム要素の onchange イベントハンドラにおいて validate を呼び出します。this を使うことで form 要素を渡すことができます。次の例をご覧ください。

+
<input type="text" name="age" size="3"
+   onChange="validate(this, 18, 99)">
+
+

一般に this はあるメソッド内でそのメソッドを呼び出したオブジェクトを参照します。

+

form プロパティと組み合わせることで、this はカレントオブジェクトの親のフォームを参照できます。次の例では、myForm というフォームに Text オブジェクトとボタンが格納されています。ユーザがボタンをクリックすると、Text オブジェクトの値にフォーム名がセットされます。ボタンの onclick イベントハンドラは this.form を利用して親のフォームである myForm を参照します。

+
<form name="myForm">
+<p><label>Form name:<input type="text" name="text1" value="Beluga"></label>
+<p><input name="button1" type="button" value="Show Form Name"
+      onclick="this.form.text1.value=this.form.name">
+</p>
+</form>
+
+

{{ PreviousNext("JavaScript/Guide/Creating_New_Objects/Defining_Methods", "JavaScript/Guide/Creating_New_Objects/Defining_Getters_and_Setters") }}

diff --git a/files/ja/web/javascript/guide/details_of_the_object_model/index.html b/files/ja/web/javascript/guide/details_of_the_object_model/index.html new file mode 100644 index 0000000000..80ea36d1ca --- /dev/null +++ b/files/ja/web/javascript/guide/details_of_the_object_model/index.html @@ -0,0 +1,728 @@ +--- +title: オブジェクトモデルの詳細 +slug: Web/JavaScript/Guide/Details_of_the_Object_Model +tags: + - Guide + - Intermediate + - JavaScript + - Object + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Details_of_the_Object_Model +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

JavaScript は、クラスではなく、プロトタイプに基づいたオブジェクトベースの言語です。この基本的な違いにより、JavaScript がオブジェクト階層構造をどのように作り上げているか、またプロパティやその値の継承方法が表面上分かりにくいものとなっています。本章ではこれらの実態を明らかにしていきます。

+ +

本章では、読者が JavaScript をある程度理解している、および単純なオブジェクトを作成するために JavaScript の関数を使用したことがあると想定しています。

+ +

クラスベース言語とプロトタイプベース言語

+ +

Java や C++ といったクラスベースのオブジェクト指向言語は、クラスとインスタンスという 2種類の異なる実体があるという概念に基づいています。

+ + + +

JavaScript のようなプロトタイプベースの言語は、この区別がありません。単にオブジェクトがあるだけです。プロトタイプベース言語には、{{原語併記("プロトタイプオブジェクト", "prototypical object")}} という概念があります。このオブジェクトは、新しいオブジェクトの初期プロパティの取得元になるテンプレートとして使用されます。どのオブジェクトも独自のプロパティを指定できます。これはオブジェクト作成時にも実行時にも可能です。さらに、どのオブジェクトも別のオブジェクトに対するプロトタイプとして関連づけることができます。2 つ目のオブジェクトに対し 1 つ目のオブジェクトのプロパティを共有させることもできます。

+ +

クラスの定義

+ +

クラスベース言語では、独立したクラス定義でクラスを定義します。定義ではコンストラクターと呼ばれる特殊なメソッドを使用して、そのクラスのインスタンスを作成することができます。コンストラクターメソッドは、インスタンスのプロパティに対する初期値を指定することができます。また、作成時に他の適切な処理を実行することもできます。new 演算子をコンストラクターメソッドと一緒に用いることで、クラスのインスタンスを作成できます。

+ +

JavaScript は同様のモデルに従っていますが、コンストラクターとは別のクラス定義はありません。その代わりに、プロパティと値からなる特別な初期セットを持つオブジェクトを作成する、コンストラクター関数を定義します。どの JavaScript 関数もコンストラクターとして使用できます。new 演算子をコンストラクター関数とともに使用することで、新しいオブジェクトを作成します。

+ +
+

ECMAScript 2015 で導入されたクラス宣言について。

+ +
+

ECMAScript 2015 で導入された JavaScript のクラスは、主に JavaScript の既存のプロトタイプベースの継承に対する糖衣構文です。クラス構文は、JavaScript に新しいオブジェクト指向の継承モデルを導入するものではありません

+
+
+ +

サブクラスと継承

+ +

クラスベース言語では、クラス定義を通してクラスの階層を作ります。クラス定義では、新しいクラスが既存のクラスのサブクラスになるよう指定することができます。サブクラスはスーパークラスの全プロパティを継承します。さらに、新たなプロパティの追加や継承したプロパティの変更もできます。例えば、Employee クラスが name および dept プロパティのみを含み、Managerreports プロパティが追加された Employee のサブクラスであるとします。この場合、Manager クラスのインスタンスは namedeptreports の 3 つのプロパティをすべて持つことになります。

+ +

JavaScript では、プロトタイプオブジェクトを何らかのコンストラクター関数に結びつけられるようにすることで、継承を実装しています。そのため、全く同じように EmployeeManager の例を作成できますが、使用する用語が若干異なります。まず、Employee コンストラクター関数を定義し、name および dept プロパティを定義します。次に Manager コンストラクター関数を定義し、Employee コンストラクター関数を呼び出して reports プロパティを定義します。最後に、Manager コンストラクト関数の prototypeEmployee.prototype から派生した新しいオブジェクトを代入します。そして新しい Manager を作成すると、このオブジェクトは Employee オブジェクトから name および dept プロパティを継承します。

+ +

プロパティの追加と削除

+ +

クラスベース言語では一般的にクラスをコンパイル時に生成し、コンパイル時または実行時にクラスのインスタンスを作成します。クラス定義後に、そのクラスのプロパティの数や型を変更することはできません。しかし JavaScript では、どのオブジェクトでも実行時にプロパティの追加や削除ができます。ある一連のオブジェクトでプロトタイプとして使用されているオブジェクトにプロパティを追加すると、それをプロトタイプとするオブジェクトにも新しいプロパティが追加されます。

+ +

相違点の概要

+ +

こうした相違点の要約を以下の表にまとめています。本章では後ほど、JavaScript のコンストラクターとプロトタイプを用いたオブジェクト階層作成の詳細を説明し、Java における手法との比較も行っていきます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
クラスベース (Java) とプロトタイプベース (JavaScript) のオブジェクトシステムの比較
クラスベース (Java)プロトタイプベース (JavaScript)
クラスとインスタンスは異なる実体です。すべてのオブジェクトは別のオブジェクトを継承できます。
クラス定義を用いてクラスを定義します。また、コンストラクターメソッドを用いてクラスをインスタンス化します。コンストラクター関数を用いて一連のオブジェクトを定義および作成します。
new 演算子を用いて単一のオブジェクトを生成します。同様です。
既存のクラスのサブクラスを定義するクラス定義を用いて、オブジェクト階層を構築します。コンストラクター関数に結びつけられたプロトタイプとしてオブジェクトを代入することで、オブジェクト階層を構築します。
クラスチェーンに従ってプロパティを継承します。プロトタイプチェーンに従ってプロパティを継承します。
クラス定義が、クラスから作られた全インスタンスすべてのプロパティを定義します。実行時に動的にプロパティを追加することはできません。コンストラクター関数またはプロトタイプによって、一連の初期化されたプロパティが指定されます。個々のオブジェクトやオブジェクトのセット全体へ動的にプロパティを追加したり、それらからプロパティを削除したりできます。
+ +

事例 : 従業員モデル

+ +

ここからは、次の図で示す従業員の階層を使用していきます。

+ +
+
+

例で使用するオブジェクトの簡単な階層図 :

+ +

+
+ +
+
    +
  • Employee には、プロパティ name(デフォルト値は空文字列)および dept(既定値は "general")があります。
  • +
  • ManagerEmployee をベースとしています。reports プロパティ(デフォルト値は空の配列、値として Employee オブジェクトの配列を保持する)が追加されています。
  • +
  • WorkerBeeEmployee をベースとしています。projects プロパティ(デフォルト値は空の配列、値として文字列の配列を保持する)が追加されています。
  • +
  • SalesPersonWorkerBee をベースとしています。quota プロパティ(デフォルトの値は 100)が追加され、さらに dept プロパティを "sales" という値で上書きします。これは、販売員が全員同じ部署に所属していることを示します。
  • +
  • EngineerWorkerBee をベースとしています。machine プロパティ(デフォルトの値は空文字列)が追加され、さらに dept プロパティを "engineering" という値で上書きします。
  • +
+
+
+ +

階層の作成

+ +

Employee の階層を実装するための、適切なコンストラクター関数を定義する方法はいくつかあります。どの方法で定義するかは、アプリケーションで何を実現したいかに大きく依存します。

+ +

この章では、継承がどのように機能するかを表現するため、とても単純な(かつ比較的柔軟でない)定義の使い方でこれを説明していきます。この定義方法では、オブジェクト作成時にプロパティの値を指定することはできません。新しく作成されるオブジェクトには単に既定値が割り当てられるだけで、値は後から変更できます。

+ +

実際のアプリケーションでは、オブジェクト作成時にプロパティの値を指定できるコンストラクターを定義することになるでしょう(詳しくはより柔軟なコンストラクターをご覧ください)。今回はこれらの単純な定義を使用して、継承はどのようにして起こるのかを実際に示していくことにします。

+ +

以下に示すように、Java と JavaScript の Employee の定義は似ています。両者の相違点は、Java では各プロパティに型を指定する必要があるのに対して、JavaScript ではその必要がないことです(これは JavaScript が弱い型付けの言語であるのに対して Java が 強い型付け言語だからです)。

+ +

JavaScript (これを使用すると、以下の例でエラーが発生する可能性があります)

+ +
class Employee {
+  constructor() {
+    this.name = '';
+    this.dept = 'general';
+  }
+}
+
+
+ +

JavaScript ** (かわりにこれを使う)

+ +
function Employee() {
+    this.name = '';
+    this.dept = 'general';
+}
+
+
+ +

Java

+ +
public class Employee {
+   public String name = "";
+   public String dept = "general";
+}
+
+ +

Manager および WorkerBee の定義では、継承チェーンにおいて隣接する上位オブジェクトの指定方法に違いがあります。JavaScript では、プロトタイプインスタンスをコンストラクター関数の prototype プロパティの値として追加し、さらに prototype.constructor をコンストラクター関数で上書きします。コンストラクターを定義した後なら、いつでもこれを行うことができます。Java では、クラス定義内でスーパークラスを指定します。クラス定義の外部でスーパークラスを変更することはできません。

+ +

JavaScript

+ +
function Manager() {
+  Employee.call(this);
+  this.reports = [];
+}
+Manager.prototype = Object.create(Employee.prototype);
+Manager.prototype.constructor = Manager;
+
+function WorkerBee() {
+  Employee.call(this);
+  this.projects = [];
+}
+WorkerBee.prototype = Object.create(Employee.prototype);
+WorkerBee.prototype.constructor = WorkerBee;
+
+ +

Java

+ +
public class Manager extends Employee {
+   public Employee[] reports =
+       new Employee[0];
+}
+
+
+
+public class WorkerBee extends Employee {
+   public String[] projects = new String[0];
+}
+
+
+
+ +

Engineer および SalesPerson の定義は、WorkerBee の子孫、したがって Employee の子孫でもあるオブジェクトを作成します。こうした種類のオブジェクトは、チェーンの上位にある全オブジェクトのプロパティを持ちます。さらに、これらの定義によって、継承された dept のプロパティ値を、自身のオブジェクト固有の新しい値に上書きしています。

+ +

JavaScript

+ +
function SalesPerson() {
+   WorkerBee.call(this);
+   this.dept = 'sales';
+   this.quota = 100;
+}
+SalesPerson.prototype = Object.create(WorkerBee.prototype);
+SalesPerson.prototype.constructor = SalesPerson;
+
+function Engineer() {
+   WorkerBee.call(this);
+   this.dept = 'engineering';
+   this.machine = '';
+}
+Engineer.prototype = Object.create(WorkerBee.prototype)
+Engineer.prototype.constructor = Engineer;
+
+ +

Java

+ +
public class SalesPerson extends WorkerBee {
+   public String dept = "sales";
+   public double quota = 100.0;
+}
+
+
+public class Engineer extends WorkerBee {
+   public String dept = "engineering";
+   public String machine = "";
+}
+
+
+ +

これらの定義を使用して、プロパティがデフォルト値をとる、オブジェクトのインスタンスを作成することができます。下記の図は、これらの JavaScript の定義を使用して新しいオブジェクトを作成する方法を示しています。また、新しいオブジェクトのプロパティの値も示しています。

+ +
+

注: インスタンスという用語は、クラスベースの言語においては特定の技術的な意味を持っています。これらの言語では、インスタンスとはクラスの個々のメンバであり、クラスとは根本的に異なるものです。JavaScript では、「インスタンス」にこのような技術的な意味はありません。なぜならば、JavaScript ではクラスとインスタンスとの間にそのような違いがないためです。しかしながら、JavaScript について話す際に「インスタンス」を、個々のコンストラクター関数を用いて作成されたオブジェクトを意味する言葉として、非公式に使用することがあります。例えば jane は非公式に Engineer のインスタンスであると言うこともできます。同様に、「親」、「子」、「祖先」、「子孫」という用語は JavaScript において公式な意味を持ちませんが、プロトタイプチェーンにおいて上や下にあるオブジェクトについて言及する際に、それらを非公式に使用してもかまいません。

+
+ +

簡単な定義によるオブジェクトの作成

+ +
+

オブジェクト階層

+ +

下記のような階層が、右に書かれたコードを使って作成されます。

+ +

+
+
+
+
+
+
+
+
+
+
+
+ +

個別のオブジェクト = Jim, Sally, Mark, Fred, Jane, など。
+ コンストラクターから生成された「インスタンス」

+ +
var jim = new Employee;
+// Parentheses can be omitted if the
+// constructor takes no arguments.
+// jim.name is ''
+// jim.dept is 'general'
+
+var sally = new Manager;
+// sally.name is ''
+// sally.dept is 'general'
+// sally.reports is []
+
+var mark = new WorkerBee;
+// mark.name is ''
+// mark.dept is 'general'
+// mark.projects is []
+
+var fred = new SalesPerson;
+// fred.name is ''
+// fred.dept is 'sales'
+// fred.projects is []
+// fred.quota is 100
+
+var jane = new Engineer;
+// jane.name is ''
+// jane.dept is 'engineering'
+// jane.projects is []
+// jane.machine is ''
+
+
+ +

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

+ +

この章では、オブジェクトがどのようにしてプロトタイプチェーンにより他のオブジェクトからプロパティを継承するのか、また実行時にプロパティを追加すると何が起きるのかについて考察します。

+ +

プロパティの継承

+ +

次の文を用いて、mark オブジェクトを WorkerBee として生成するとしましょう。

+ +
var mark = new WorkerBee;
+
+ +

JavaScript は new 演算子に出会うと、新しく汎用オブジェクトを作成し、暗黙に内部プロパティ [[Prototype]] の値を WorkerBee.prototype の値に設定し、その新しいオブジェクトを this キーワードの値として WorkerBee コンストラクター関数に渡します。内部の [[Prototype]] プロパティはプロパティ値を返すために使用されるプロトタイプチェーンを決定します。これらのプロパティが設定されると JavaScript は新しいオブジェクトを返し、代入文によって変数 mark にそのオブジェクトが設定されます。

+ +

このプロセスでは、mark がプロトタイプチェーンによって継承するプロパティは、mark オブジェクトの値には(ローカル値としては)明示的に格納されません。プロパティの値を使用するときは、JavaScript はまずその値がオブジェクトに存在しているかを確認します。存在する場合は、その値が返されます。値がローカルには存在しない場合、JavaScript はプロトタイプチェーンを確認します(内部的な [[Prototype]] プロパティを使用)。プロトタイプチェーン内のオブジェクトがそのプロパティの値を持っている場合は、その値が返されます。そのようなプロパティが見つからない場合、JavaScript はオブジェクトにそのプロパティがないと報告します。このようにして、mark オブジェクトは次のようなプロパティと値を持つことになります。

+ +
mark.name = '';
+mark.dept = 'general';
+mark.projects = [];
+
+ +

mark オブジェクトは、Employee コンストラクターによって name および dept プロパティのローカル値が割り当てられます。projects プロパティには、WorkerBee コンストラクターによってローカル値が代入されます。JavaScript ではこのようにプロパティとその値の継承を行います。このプロセスの詳細はプロパティの継承、再びにて説明します。

+ +

これらのコンストラクターはインスタンス固有の値を渡せないため、この情報は汎用的になります。プロパティの値は、WorkerBee によって作成されるすべての新しいオブジェクトに共通の既定値になります。もちろん、これらのどのプロパティでも値を変更することができます。そのためには、次のようにして mark に固有の情報を与えます。

+ +
mark.name = 'Doe, Mark';
+mark.dept = 'admin';
+mark.projects = ['navigator'];
+ +

プロパティの追加

+ +

JavaScript では、実行時にどんなオブジェクトにもプロパティを追加することができます。コンストラクター関数で与えられるプロパティだけしか使えないわけではありません。単一のオブジェクトに特化してプロパティを追加するには、次のようにオブジェクトに値を代入します。

+ +
mark.bonus = 3000;
+
+ +

すると、mark オブジェクトに bonus プロパティができます。しかし WorkerBee にはこのプロパティは存在しません。

+ +

あるコンストラクター関数のプロトタイプとして使用されているオブジェクトに新しいプロパティを追加すると、プロトタイプからプロパティを継承する全オブジェクトにそのプロパティを追加します。例えば、次の文を使用すると specialty プロパティをすべての従業員に対して追加することができます。

+ +
Employee.prototype.specialty = 'none';
+
+ +

JavaScript でこの文が実行されると、即座に mark オブジェクトも specialty プロパティを "none" という値で持つようになります。次の図では、プロパティを Employee プロトタイプに追加し、さらに Engineer プロトタイプに存在するプロパティを上書きしたときの効果を示しています。

+ +


+ プロパティの追加

+ +

より柔軟なコンストラクター

+ +

これまでに見てきたコンストラクター関数は、インスタンス作成時にプロパティの値を指定することができませんでした。Java のようにコンストラクターに引数を与えて、インスタンスのプロパティの値を初期化することができます。以下の図はこれを実現する方法の一つの方法です。

+ +


+ コンストラクターでのプロパティの指定方法、その 1

+ +

Java および JavaScript におけるこれらのオブジェクト定義を次表に示します。

+ +
function Employee(name, dept) {
+  this.name = name || '';
+  this.dept = dept || 'general';
+}
+
+ +
public class Employee {
+   public String name;
+   public String dept;
+   public Employee () {
+      this("", "general");
+   }
+   public Employee (String name) {
+      this(name, "general");
+   }
+   public Employee (String name, String dept) {
+      this.name = name;
+      this.dept = dept;
+   }
+}
+
+ +
function WorkerBee(projs) {
+  this.projects = projs || [];
+}
+WorkerBee.prototype = new Employee;
+
+ +
public class WorkerBee extends Employee {
+   public String[] projects;
+   public WorkerBee () {
+      this(new String[0]);
+   }
+   public WorkerBee (String[] projs) {
+      projects = projs;
+   }
+}
+
+ +
+function Engineer(mach) {
+  this.dept = 'engineering';
+  this.machine = mach || '';
+}
+Engineer.prototype = new WorkerBee;
+
+ +
public class Engineer extends WorkerBee {
+   public String machine;
+   public Engineer () {
+      dept = "engineering";
+      machine = "";
+   }
+   public Engineer (String mach) {
+      dept = "engineering";
+      machine = mach;
+   }
+}
+
+ +

これらの JavaScript の定義では、既定値の設定に特殊な構文を使用しています。

+ +
this.name = name || '';
+
+ +

JavaScript の論理和 (OR) 演算子 (||) は、その最初の引数を評価します。その引数が true に評価される場合、演算子はその引数を返します。そうでない場合、第2引数の値を返します。したがって、このコードは namename プロパティの値に使用できる値かどうかを確認します。使用できると確認されれば this.name にその値を設定します。そうでなければ this.name に空文字列をセットします。本章ではこの方法がより簡潔なのでこの構文を使用していますが、一目見ただけでは不可解に思えるかもしれません。

+ +
+

注: ご想像の通り、この構文はコンストラクターが false に変換される引数(0 や空文字列 ("") など)と共に呼び出された場合は動作しません。その場合は既定値が選択されます。

+
+ +

これらの定義を用いると、オブジェクトのインスタンスを作成するときに、局所的に定義されたプロパティに対する値を指定することができます。次の文を使用すると新しい Engineer を作成できます。

+ +
var jane = new Engineer('belau');
+
+ +

すると Jane のプロパティは次のようになります。

+ +
jane.name == '';
+jane.dept == 'engineering';
+jane.projects == [];
+jane.machine == 'belau';
+
+ +

これらの定義では、name のような継承されたプロパティに対して初期値を指定することはできない点に注意してください。JavaScript で継承されるプロパティに対し初期値を指定したいのであれば、コンストラクター関数にさらにコードを追加する必要があります。

+ +

ここまでは、コンストラクター関数は汎用オブジェクトを生成し、その後で新しいオブジェクトに対してローカルプロパティと値を定義していました。プロトタイプチェーンのより上位のオブジェクトのコンストラクター関数を直接呼び出すことで、コンストラクターへさらにプロパティを追加することができます。次の図はこの新しい定義方法です。

+ +


+ コンストラクターでのプロパティの指定方法、その 2

+ +

これらの定義の一つを詳しく見ていきましょう。これは Engineer コンストラクターの新しい定義です。

+ +
function Engineer(name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, 'engineering', projs);
+  this.machine = mach || '';
+}
+
+ +

次のようにして新しい Engineer オブジェクトを作成するとします。

+ +
var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau');
+
+ +

JavaScript は次の手順を踏みます。

+ +
    +
  1. new 演算子が汎用オブジェクトを生成し、その __proto__ プロパティに Engineer.prototype を設定します。
  2. +
  3. new 演算子が this キーワードの値としてこの新しい汎用オブジェクトを Engineer コンストラクターに渡します。
  4. +
  5. コンストラクターがそのオブジェクトに base という新しいプロパティを生成し、WorkerBee コンストラクターの値を base プロパティに代入します。これにより、WorkerBee コンストラクターは Engineer オブジェクトのメソッドになります。base というプロパティ名は特別なものではありません。あらゆる正当なプロパティ名を使用できますが、ここで base という名前を使うのは、その目的をたやすくイメージさせるためです。
  6. +
  7. コンストラクターが base メソッドを呼び出します。その引数として、コンストラクターに渡された引数のうち 2 つ("Doe, Jane" および ["navigator", "javascript"])と、さらに文字列 "engineering" を渡します。コンストラクターで "engineering" を明示的に使用するのは、すべての Engineer オブジェクトは継承により dept プロパティは同じ値となっていて、Employee から継承された値を指定値に上書きするためです。
  8. +
  9. baseEngineer のメソッドであるため、base を呼び出す際に、JavaScript によって this キーワードをステップ 1 で作成したオブジェクトにバインドします。これにより、WorkerBee 関数は順に "Doe, Jane" および "engineering" という引数を Employee コンストラクター関数に渡します。Employee コンストラクター関数から戻ると、WorkerBee 関数は残りの引数を使用して projects プロパティをセットします。
  10. +
  11. base メソッドから戻ると、Engineer コンストラクターがオブジェクトの machine プロパティを "belau" に初期化します。
  12. +
  13. コンストラクターから戻ると、JavaScript は新しいオブジェクトを jane という変数に代入します。
  14. +
+ +

Engineer コンストラクターの内部から WorkerBee コンストラクターを呼び出しさえすれば、きちんと Engineer オブジェクトに継承が設定されるように思うかもしれません。しかし実際はそうではありません。WorkerBee コンストラクターを呼び出すことで、呼び出されるすべてのコンストラクター関数によって指定されたプロパティを持つ Engineer オブジェクトは確かに作成されます。しかし、後からプロパティを Employee または WorkerBee のプロトタイプに追加しても、それらのプロパティは Engineer オブジェクトに継承されません。例えば、次のような文を書いたとします。

+ +
function Engineer(name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, 'engineering', projs);
+  this.machine = mach || '';
+}
+var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau');
+Employee.prototype.specialty = 'none';
+
+ +

jane オブジェクトは specialty プロパティを継承しません。動的な継承を確実にするには、やはりプロトタイプを明示的に示す必要があります。代わりに次の文を使用しましょう。

+ +
function Engineer(name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, 'engineering', projs);
+  this.machine = mach || '';
+}
+Engineer.prototype = new WorkerBee;
+var jane = new Engineer('Doe, Jane', ['navigator', 'javascript'], 'belau');
+Employee.prototype.specialty = 'none';
+
+ +

すると、jane オブジェクトの specialty プロパティの値は "none" になります。

+ +

もう一つの継承方法は、call() / apply() メソッドを使うことです。以下の二つは同等です。

+ +
function Engineer(name, projs, mach) {
+  this.base = WorkerBee;
+  this.base(name, 'engineering', projs);
+  this.machine = mach || '';
+}
+
+ +
function Engineer(name, projs, mach) {
+  WorkerBee.call(this, name, 'engineering', projs);
+  this.machine = mach || '';
+}
+
+ +

JavaScript の call() メソッドを使うことで、実装がよりきれいになります。base が全く必要ないからです。

+ +

プロパティの継承、再び

+ +

これまでの節では、JavaScript のコンストラクターとプロトタイプが階層をどのように実現しているかを説明してきました。この節では、これまでの議論では必ずしも明白ではなかった、細かい部分について議論していきます。

+ +

ローカル値と継承値

+ +

オブジェクトのプロパティにアクセスすると、この章で先に説明したように、JavaScript は次のステップを実行します。

+ +
    +
  1. プロパティの値がローカルに存在するかを確かめます。存在している場合は、その値を返します。
  2. +
  3. 値がローカルに存在していない場合は、プロトタイプチェーンを確認します(__proto__ プロパティを使用)。
  4. +
  5. プロトタイプチェーン内のオブジェクトが指定したプロパティの値を持っている場合は、その値を返します。
  6. +
  7. そのようなプロパティが見つからない場合は、オブジェクトにそのプロパティは存在しません。
  8. +
+ +

このステップの結果は、それまでにどのようにオブジェクトを定義したかによります。元の例では次の定義を用いました。

+ +
function Employee() {
+  this.name = '';
+  this.dept = 'general';
+}
+
+function WorkerBee() {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+ +

この定義を前提とし、次の文を用いて WorkerBee のインスタンスとして amy を作成するとします。

+ +
var amy = new WorkerBee;
+
+ +

amy オブジェクトにはローカルプロパティが 1 つあります。それは projects です。name および dept プロパティの値は amy にとってローカルではないため、amy オブジェクトの __proto__ プロパティから取得します。その結果、amy には次のプロパティが存在することになります。

+ +
amy.name == '';
+amy.dept == 'general';
+amy.projects == [];
+
+ +

ここで、Employee に結びつけられたプロトタイプの name プロパティの値を変えてみましょう :

+ +
Employee.prototype.name = 'Unknown';
+
+ +

一見、Employee の全インスタンスに新しい値が反映されるように思われます。しかし、そうはなりません。

+ +

Employee オブジェクトからなるいかなるインスタンスを作成しても、そのインスタンスは name プロパティのローカル値(空文字列)を持つことになります。つまり、新しい Employee オブジェクトの作成に WorkerBee プロトタイプを設定すれば、WorkerBee.prototypename プロパティのためのローカル値を持つことになる、ということです。そのため、JavaScript が amy オブジェクト(WorkerBee のインスタンス)の name プロパティを探すと、JavaScript はそのプロパティのローカル値を WorkerBee.prototype 内で発見します。結果、Employee.prototype まではチェーンの検索は行われません。

+ +

実行時にオブジェクトのプロパティの値を変更し、新しい値がそのオブジェクトのすべての子孫に継承するようにしたい場合は、オブジェクトのコンストラクター関数内でそのプロパティを定義してはいけません。その代わりに、コンストラクター関数に結びつけられたプロトタイプにプロパティを追加します。例えば、先のコードを次のように変更しましょう。

+ +
function Employee() {
+  this.dept = 'general';    // Note that this.name (a local variable) does not appear here
+}
+Employee.prototype.name = '';    // A single copy
+
+function WorkerBee() {
+  this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+var amy = new WorkerBee;
+
+Employee.prototype.name = 'Unknown';
+
+ +

こうすれば、amyname プロパティは "Unknown" になります。

+ +

この例で示したように、オブジェクトのプロパティにデフォルトの値を持たせて、実行時にデフォルト値を変更したいのであれば、コンストラクター関数内でなく、コンストラクターのプロトタイプ内でプロパティを設定するようにしてください。

+ +

インスタンス関係の決定

+ +

JavaScript でのプロパティ探索は、まずオブジェクト自身のプロパティ内で探索し、そのプロパティ名が存在しない場合は特殊なオブジェクトプロパティである __proto__ で探索します。これは再帰的に継続されます。このプロセスを「プロトタイプチェーンの探索」と呼びます。

+ +

この特別なプロパティ __proto__ は、オブジェクトが構築される際に設定されて、コンストラクターの prototype プロパティを構成する値となります。よって、式 new Foo()__proto__ == Foo.prototype となるオブジェクトを作成します。その結果、Foo.prototype のプロパティの変更により、new Foo() で作成されたすべてのオブジェクトのプロパティ探索が変更されます。

+ +

すべてのオブジェクトは(Object を除いて) __proto__ オブジェクトプロパティを持ちます。また、すべての関数は prototype オブジェクトプロパティを持ちます。したがって、「プロトタイプ継承」を用いてオブジェクトを別のオブジェクトへ関連づけられます。オブジェクトの __proto__ と関数の prototype オブジェクトを比較することで、継承状態の確認ができます。これを行う手っ取り早い方法が JavaScript にはあります。instanceof 演算子はオブジェクトと関数を検査して、オブジェクトが関数のプロトタイプから継承している場合に true を返します。例えば、

+ +
var f = new Foo();
+var isTrue = (f instanceof Foo);
+ +

もっと詳しい例として、プロパティの継承で利用した定義を使ってみましょう。以下のようにして Engineer オブジェクトを作成しましょう。

+ +
var chris = new Engineer('Pigman, Chris', ['jsd'], 'fiji');
+
+ +

このオブジェクトでは、以下の文はすべて true になります。

+ +
chris.__proto__ == Engineer.prototype;
+chris.__proto__.__proto__ == WorkerBee.prototype;
+chris.__proto__.__proto__.__proto__ == Employee.prototype;
+chris.__proto__.__proto__.__proto__.__proto__ == Object.prototype;
+chris.__proto__.__proto__.__proto__.__proto__.__proto__ == null;
+
+ +

ここで次のような instanceOf 関数を書いてみましょう。

+ +
function instanceOf(object, constructor) {
+   object = object.__proto__;
+   while (object != null) {
+      if (object == constructor.prototype)
+         return true;
+      if (typeof object == 'xml') {
+        return constructor.prototype == XML.prototype;
+      }
+      object = object.__proto__;
+   }
+   return false;
+}
+
+ +
注: 上記の実装では、最近のバージョンでの JavaScript における XML オブジェクト表現法の癖を回避するために、オブジェクトの型と "xml" とを照合しています。具体的な詳細を知りたい場合は {{bug(634150)}} をご覧ください。
+ +

この定義を用いると、以下の式はすべて true になります。

+ +
instanceOf(chris, Engineer)
+instanceOf(chris, WorkerBee)
+instanceOf(chris, Employee)
+instanceOf(chris, Object)
+
+ +

しかし、次の式は false になります :

+ +
instanceOf(chris, SalesPerson)
+
+ +

コンストラクターにおけるグローバル情報

+ +

コンストラクターを作成する際、コンストラクター内でグローバルな情報を設定する場合は注意が必要です。例えば、一意的な ID をそれぞれの新しい従業員情報へ自動的に代入したいとします。そこで、以下のように Employee を定義できます :

+ +
var idCounter = 1;
+
+function Employee(name, dept) {
+   this.name = name || '';
+   this.dept = dept || 'general';
+   this.id = idCounter++;
+}
+
+ +

この定義を用いると、新しい Employee を作成するたびに、コンストラクターが次の ID を順々に代入し、グローバルな ID カウンターをインクリメントします。その結果、続けて以下の文を置くと victoria.id は 1 に、harry.id は 2 となります :

+ +
var victoria = new Employee('Pigbert, Victoria', 'pubs');
+var harry = new Employee('Tschopik, Harry', 'sales');
+
+ +

一見、これは申し分なさそうです。しかし、idCounter はどのような用途であろうと、Employee オブジェクトが作成されるたびにインクリメントされます。この章で示した Employee の階層全体を作成すると、Employee コンストラクターはプロトタイプをセットアップするたびに呼び出されます。次のようなコードがあるとします :

+ +
var idCounter = 1;
+
+function Employee(name, dept) {
+   this.name = name || '';
+   this.dept = dept || 'general';
+   this.id = idCounter++;
+}
+
+function Manager(name, dept, reports) {...}
+Manager.prototype = new Employee;
+
+function WorkerBee(name, dept, projs) {...}
+WorkerBee.prototype = new Employee;
+
+function Engineer(name, projs, mach) {...}
+Engineer.prototype = new WorkerBee;
+
+function SalesPerson(name, projs, quota) {...}
+SalesPerson.prototype = new WorkerBee;
+
+var mac = new Engineer('Wood, Mac');
+
+ +

さらに、ここでは省かれている定義に base プロパティがあり、その定義がプロトタイプチェーンにおいて上位のコンストラクターを呼び出すとします。この場合、mac オブジェクトが作成されるまでに mac.id は 5 になってしまいます。

+ +

カウンターが余計にインクリメントされることが問題になるかどうかは、そのアプリケーション次第です。このカウンターの正確な値を気にするのであれば、代わりに一つの解決策として以下のようなコンストラクターが考えられます。

+ +
function Employee(name, dept) {
+   this.name = name || '';
+   this.dept = dept || 'general';
+   if (name)
+      this.id = idCounter++;
+}
+
+ +

プロトタイプとして使用する Employee のインスタンスを作成するときに、コンストラクターに引数を与えてはいけません。このコンストラクターの定義を使用すれば、引数を渡さないときはコンストラクターが ID に値を代入せず、カウンターの更新も行いません。そのため、割り当てられる id を Employee に付与したい場合は、従業員の名前を指定する必要があります。この例では mac.id は 1 になります。

+ +

それ以外に、WorkerBee に割り当てるために Employee のプロトタイプオブジェクトのコピーを作成することもできます。

+ +
WorkerBee.prototype = Object.create(Employee.prototype);
+// instead of WorkerBee.prototype = new Employee
+
+ +

多重継承はなし

+ +

オブジェクト指向言語の中には、多重継承を許容するものがあります。つまり、オブジェクトが無関係な親オブジェクトから、プロパティと値を継承できるということです。JavaScript は多重継承をサポートしていません。

+ +

実行時のプロパティの値の継承は、JavaScript が値を見つけようとしてオブジェクトのプロトタイプチェーンを探索することで行われます。オブジェクトに結びつけられたプロトタイプは 1 つであるため、JavaScript は複数のプロトタイプチェーンから動的に継承することはできません。

+ +

JavaScript では、コンストラクター関数がその中で複数の別のコンストラクター関数を呼び出すようにすることができます。これによって多重継承状のものが実現できます。例えば以下の文があるとします。

+ +
function Hobbyist(hobby) {
+   this.hobby = hobby || 'scuba';
+}
+
+function Engineer(name, projs, mach, hobby) {
+   this.base1 = WorkerBee;
+   this.base1(name, 'engineering', projs);
+   this.base2 = Hobbyist;
+   this.base2(hobby);
+   this.machine = mach || '';
+}
+Engineer.prototype = new WorkerBee;
+
+var dennis = new Engineer('Doe, Dennis', ['collabra'], 'hugo');
+
+ +

さらに、WorkerBee の定義はこの章で先に使用したものであるとします。この場合、dennis オブジェクトにはこれらのプロパティが存在します。

+ +
dennis.name == 'Doe, Dennis';
+dennis.dept == 'engineering';
+dennis.projects == ['collabra'];
+dennis.machine == 'hugo';
+dennis.hobby == 'scuba';
+
+ +

dennisHobbyist コンストラクターから hobby プロパティを取得しているのです。ここで、Hobbyist コンストラクターのプロトタイプにプロパティを追加してみましょう。

+ +
Hobbyist.prototype.equipment = ['mask', 'fins', 'regulator', 'bcd'];
+
+ +

このようにしても dennis オブジェクトはこの新しいプロパティを継承しません。

+ +
{{PreviousNext("Web/JavaScript/Guide/Working_with_Objects", "Web/JavaScript/Guide/Using_promises")}}
diff --git a/files/ja/web/javascript/guide/exception_handling_statements/index.html b/files/ja/web/javascript/guide/exception_handling_statements/index.html new file mode 100644 index 0000000000..fddf6c4181 --- /dev/null +++ b/files/ja/web/javascript/guide/exception_handling_statements/index.html @@ -0,0 +1,36 @@ +--- +title: 例外処理文 +slug: Web/JavaScript/Guide/Exception_Handling_Statements +--- +

例外処理文

+

throw 文を使用すると例外を投げることができます。また、try...catch 文を使用すると例外を処理することができます。

+

try...catch 文を使用して Java の例外を処理することもできます。この情報については JavaScript での Java の例外の処理 および Java と JavaScript との通信 をご覧ください。

+ +

例外の種類

+

JavaScript ではほとんどどんなオブジェクトでも投げることができます。とは言っても、必ずしもすべての投げられたオブジェクトが同等に作られているわけではありません。数値や文字列をエラーとして投げる方法はよく用いられますが、特にこの用途のために作られている例外の種類のうちのどれかを使用したほうがより効率的であることがよくあります。

+ +

{{ PreviousNext("JavaScript/Guide/Comments", "JavaScript/Guide/Exception_Handling_Statements/throw_Statement") }}

diff --git a/files/ja/web/javascript/guide/exception_handling_statements/throw_statement/index.html b/files/ja/web/javascript/guide/exception_handling_statements/throw_statement/index.html new file mode 100644 index 0000000000..9d98321883 --- /dev/null +++ b/files/ja/web/javascript/guide/exception_handling_statements/throw_statement/index.html @@ -0,0 +1,34 @@ +--- +title: throw 文 +slug: Web/JavaScript/Guide/Exception_Handling_Statements/throw_Statement +--- +

throw 文

+

throw 文は例外を投げるために使用します。例外を投げるときは、投げたい値からなる式を指定してください。

+
throw expression;
+
+

特定の型の式だけではなく、あらゆる式を投げることができます。下記のコードは様々な型の例外を投げています。

+
throw "Error2";
+throw 42;
+throw true;
+throw {toString: function() { return "I'm an object!"; } };
+
+
+ 注意:例外を投げる際にオブジェクトを指定することができます。すると、catch ブロックでそのオブジェクトのプロパティを参照できるようになります。次の例では UserException という種類の myUserException というオブジェクトを作ります。また、このオブジェクトを throw 文で使用します。
+
// UserException という種類のオブジェクトを作成
+function UserException (message)
+{
+  this.message=message;
+  this.name="UserException";
+}
+
+// 文字列として使用されるとき(例:エラーコンソール上)に
+// 例外を整形する
+UserException.prototype.toString = function ()
+{
+  return this.name + ': "' + this.message + '"';
+}
+
+// そのオブジェクトの種類のインスタンスを作成し、それを投げる
+throw new UserException("Value too high");
+
+

{{ PreviousNext("JavaScript/Guide/Exception_Handling_Statements", "JavaScript/Guide/Exception_Handling_Statements/try...catch_Statement") }}

diff --git a/files/ja/web/javascript/guide/exception_handling_statements/try...catch_statement/index.html b/files/ja/web/javascript/guide/exception_handling_statements/try...catch_statement/index.html new file mode 100644 index 0000000000..678cd3f38e --- /dev/null +++ b/files/ja/web/javascript/guide/exception_handling_statements/try...catch_statement/index.html @@ -0,0 +1,135 @@ +--- +title: try...catch 文 +slug: Web/JavaScript/Guide/Exception_Handling_Statements/try...catch_Statement +--- +

try...catch 文

+ +

try...catch 文はテストしたい文のブロックを指定し、さらに投げられるであろう例外に対する 1 つ以上の対処方法を指定します。例外が投げられると try...catch 文がそれを受け取ります。

+ +

try...catch 文は 1 つの try ブロックと 0 個以上の catch ブロックからなります。前者は 1 つ以上の文からなります。後者は try ブロックで例外が投げられた場合にどうするかを指定する文からなります。すなわち、成功させたい try ブロックと、失敗した場合にコントロールを渡す catch ブロックからなります。try ブロック内(もしくは try ブロック内から呼び出された関数内)のいずれかの文が例外を投げた場合、コントロールはすぐに catch ブロックに移ります。try ブロックで例外が投げられなかった場合は catch ブロックは飛ばされます。finally ブロックは try および catch ブロックが実行された後に実行されます。ただし try...catch 文の後に続く文より先に実行されます。

+ +

次の例では try...catch 文を使用しています。この例では渡された値に基づいて配列から月の名前を取り出す関数を呼び出します。値に対応する月の数字 (1-12) がなかったら、InvalidMonthNo という値を持つ例外が投げられ、catch ブロックの中の文は monthName という変数に unknown という値をセットします。

+ +
function getMonthName (mo) {
+    mo=mo-1; // 月の数字を配列のインデックスに合わせる (1=Jan, 12=Dec)
+    var months=new Array("Jan","Feb","Mar","Apr","May","Jun","Jul",
+          "Aug","Sep","Oct","Nov","Dec");
+    if (months[mo] != null) {
+       return months[mo]
+    } else {
+       throw "InvalidMonthNo"
+    }
+}
+
+try {
+// テストする文
+    monthName=getMonthName(myMonth) // 関数は例外を投げることがある
+}
+catch (e) {
+    monthName="unknown"
+    logMyErrors(e) // 例外オブジェクトをエラー処理部分に渡す
+}
+
+ +

catch ブロック

+ +

単一の catch ブロックを使用すると、try ブロックで生じうるすべての例外を扱うことができます。また、扱う例外の種類によって catch ブロックをそれぞれに分けることもできます。

+ +

単一の catch ブロック
+ try ブロックで投げられるいかなる例外にも対応したエラー処理コードを実行するには、try...catch 文で catch を 1 つ使用してください。

+ +

単一の catch ブロックは次のように使用します。

+ +
catch (catchID) {
+  statements
+}
+
+ +

catch ブロックは、throw 文で指定された値を持つ識別子(上記の構文における catchID)を指定します。この識別子を使用することで投げられた例外についての情報を得ることができます。JavaScript は catch ブロックに入るときにこの識別子を作成します。識別子は catch ブロックにいる間だけ持続します。つまり、catch ブロックの実行が終了するとその識別子はもう使えなくなります。

+ +

例えば、次のコードは例外を投げます。例外が生じるとコントロールが catch ブロックに移ります。

+ +
try {
+   throw "myException" // 例外を生成
+}
+catch (e) {
+// どんな例外も扱う文
+   logMyErrors(e) // 例外オブジェクトをエラー処理部分に渡す
+}
+
+ +

複数の catch ブロック
+ 1 つの try 文に対して、複数の条件についての catch ブロックを使うことができます。そして、そのそれぞれがそれぞれの種類の例外を担当します。この場合、そのブロックで指定されている例外が投げられたときだけ、適切な条件の catch ブロックに入ることになります。すべての未指定の例外のために、すべての例外に対応した catch ブロックをその文の最後の catch ブロックとしてオプション的に設けることもできます。

+ +

例えば、次の関数は 3 つの別の関数(どこかで定義済み)を呼び出します。この関数はその引数が妥当であるかを確かめます。妥当性確認関数が確認対象の構成要素が妥当でないと決定した場合、その関数は 0 を返し、該当する例外を呼び出し元に投げさせます。

+ +
function getCustInfo(name, id, email)
+{
+   var n, i, e;
+
+   if (!validate_name(name))
+       throw "InvalidNameException"
+   else
+       n = name;
+       if (!validate_id(id))
+          throw "InvalidIdException"
+       else
+          i = id;
+       if (!validate_email(email))
+          throw "InvalidEmailException"
+       else
+          e = email;
+       cust = (n + " " + i + " " + e);
+       return (cust);
+}
+
+ +

おのおのの条件の catch ブロックは適当な例外処理部分にコントロールを渡します。

+ +
try {
+// 関数は 3 つの例外を投げうる
+   getCustInfo("Lee", 1234, "lee@netscape.com")
+}
+
+catch (e if e == "InvalidNameException") {
+// 不正な名前に対しての処理部分を呼び出す
+   bad_name_handler(e)
+}
+
+catch (e if e == "InvalidIdException") {
+// 不正な ID に対しての処理部分を呼び出す
+   bad_id_handler(e)
+}
+
+catch (e if e == "InvalidEmailException") {
+// 不正なメールアドレスに対しての処理部分を呼び出す
+   bad_email_handler(e)
+}
+
+catch (e){
+// 何が起きるかはわからないが、そのログをとる
+   logError(e)
+}
+
+ +

finally ブロック

+ +

finally ブロックは、try および catch ブロックの実行が終わった後に実行される文からなります。ただし try...catch 文の後に続く文より前に実行されます。finally ブロックは例外が投げられても投げられなくても実行されます。例外が投げられた場合、finally ブロック内の文はたとえ例外処理をする catch ブロックがなくても実行されます。

+ +

finally ブロックを使用することで、例外発生時に適切にスクリプトを停止させることができます。例えば、スクリプトで使用していたリソースを解放する必要があるかもしれません。次の例ではファイルを開き、そのファイルを使用する文を実行します(サーバサイド JavaScript ではファイルにアクセスできます)。ファイルを開いている間に例外が投げられると、スクリプトが停止する前に finally ブロックがそのファイルを閉じます。

+ +
openMyFile();
+try {
+   writeMyFile(theData); // エラーを投げる可能性がある
+} catch(e) {
+   handleError(e); // エラーを受け取り、それを処理する
+} finally {
+   closeMyFile(); // 常にリソースを閉じる
+}
+
+ +

try...catch 文のネスト

+ +

1 つ以上の try...catch 文を入れ子にすることができます。内側の try...catch 文に catch ブロックがない場合、囲んでいる try...catch 文の catch ブロックがマッチしているか確認されます。

+ +

{{ PreviousNext("JavaScript/Guide/Exception_Handling_Statements/throw_Statement", "JavaScript/Guide/Defining_Functions") }}

diff --git a/files/ja/web/javascript/guide/expressions/index.html b/files/ja/web/javascript/guide/expressions/index.html new file mode 100644 index 0000000000..4feb2b1aa8 --- /dev/null +++ b/files/ja/web/javascript/guide/expressions/index.html @@ -0,0 +1,16 @@ +--- +title: Expressions +slug: Web/JavaScript/Guide/Expressions +--- +
{{ 英語版章題("Expressions") }}
+

+

とは、リテラル、変数、演算子、そして単一の値に評価する式からなる有効なセットです。この値には数値、文字列、論理値が使用できます。

+

概念的に、式は 2 つの種類に分けることができます。ある値を変数に代入するものと、単純にある値を持つものです。例えば、x = 7 という式は x に 7 という値を代入する式です。この式自体の評価結果は 7 です。このような式では代入演算子を用います。一方、3 + 4 という式では単純に評価結果が 7 になります。この式は代入を行いません。このような式で用いられる演算子は単に演算子と呼ばれます。

+

JavaScript には以下の種類の式があります。

+ +

{{ PreviousNext("JavaScript/Guide/Unicode", "JavaScript/Guide/Operators") }}

diff --git a/files/ja/web/javascript/guide/expressions_and_operators/index.html b/files/ja/web/javascript/guide/expressions_and_operators/index.html new file mode 100644 index 0000000000..884497548c --- /dev/null +++ b/files/ja/web/javascript/guide/expressions_and_operators/index.html @@ -0,0 +1,928 @@ +--- +title: 式と演算子 +slug: Web/JavaScript/Guide/Expressions_and_Operators +tags: + - Beginner + - Expressions + - Guide + - JavaScript + - Operators + - 'l10n:priority' + - 演算子 +translation_of: Web/JavaScript/Guide/Expressions_and_Operators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}
+ +

この章では 代入、比較、算術、ビット、論理、文字列、三項演算子などに関わる JavaScript の式 (expression) や演算子 (operator) について説明しています。

+ +

演算子と式について網羅した詳しいリストはリファレンスでもご覧いただけます。

+ +

演算子

+ +

JavaScript では以下の種類の演算子を使用できます。この節では演算子の優先順位についての説明も含めて演算子について説明します。

+ + + +

JavaScript は二項演算子単項演算子を実装しており、さらには三項演算子や条件演算子も実装しています。二項演算子は以下のような形で演算子 (operator) を一つ、その前後となるようにオペランド (operand) が二つ必要となります。

+ +
operand1 operator operand2
+
+ +

例えば 3+4x*y です。

+ +

単項演算子は演算子の前後いずれかに、一つのオペランドが必要です。

+ +
operator operand
+ +

もしくは

+ +
operand operator
+ +

例えば x++++x です。

+ +

代入演算子

+ +

代入演算子は右オペランドの値を元に、左のオペランドへ値を代入するものです。簡単なものでは equal (=) があり、右オペランドの値を左オペランドへ代入します。つまり、x = y では y の値を x へ代入することになります。

+ +

次の表にまとめられているように演算子を省略した複合代入演算子というものもあります。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
複合代入演算子
名称略記演算子意味
代入x = yx = y
加算代入x += yx = x + y
減算代入x -= yx = x - y
乗算代入x *= yx = x * y
除算代入x /= yx = x / y
剰余代入x %= yx = x % y
べき乗代入x **= yx = x ** y
左シフト代入x <<= yx = x << y
右シフト代入x >>= yx = x >> y
符号なし右シフト代入x >>>= yx = x >>> y
ビット論理積 (AND) 代入x &= yx = x & y
ビット排他的論理和 (XOR) 代入x ^= yx = x ^ y
ビット論理和 (OR) 代入x |= yx = x | y
論理積代入x &&= yx && (x = y)
論理和代入x ||= yx || (x = y)
Null 合体代入x ??= yx ?? (x = y)
+ +

戻り値と連鎖

+ +

ほとんどの式と同様に、x = y のような代入には戻り値があります。戻り値は式の代入やロギング等により取得することができます。

+ +
const z = (x = y); // 右記と等価 const z = x = y;
+
+console.log(z); // 代入 x = y の戻り値をログする。
+console.log(x = y); // または、戻り値を直接ログする。
+ +

戻り値は上の表の「意味」列の = 記号の右側の式と一致します。つまり (x = y)y を返し、(x += y) は加算 x + y の結果を返し、(x **= y) はべき乗 x ** y の結果を返します。

+ +

論理代入、(x &&= y)(x ||= y) および (x ??= y) の場合、戻り値は代入を除いた論理演算の結果であり、それぞれ x && yx || y および x ?? y を返します。

+ +

戻り値は常に演算のオペランドの値に基づくことに注意してください。

+ +

これらの式を連鎖させると、それぞれの代入は右から左に評価されます。以下の例で考えてみましょう。

+ + + +

分割代入

+ +

より複雑な代入方法、分割代入構文は、配列やオブジェクトのリテラル構造を反映した構文を用いて、配列やオブジェクトからデータを抽出することができる JavaScript の式です。

+ + + + + +
var foo = ['one', 'two', 'three'];
+
+// 分割を行わない代入
+var one   = foo[0];
+var two   = foo[1];
+var three = foo[2];
+
+// 分割代入
+var [one, two, three] = foo;
+ +

比較演算子

+ +

比較演算子は被演算子を比較して、その結果が真であるかに基づいて論理値を返します。被演算子には数値、文字列、論理値、オブジェクトを使用できます。文字列は Unicode を用い、標準的な辞書順に基づいて比較されます。ほとんどの場合、2 つの被演算子が異なる型ならば JavaScript はその被演算子を比較に適した型に変換しようとします。こうした挙動により、一般的に被演算子は数値的に比較される結果となります。このルールの唯一の例外は === および !== で、これらは「厳密に」等値か否かを判断し、等値性をチェックする前に被演算子を適合する型に変換しません。次の表では、以下のサンプルコードで定義された変数を前提として比較演算子を説明していきます。

+ +
var var1 = 3;
+var var2 = 4;
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
比較演算子
演算子説明true を返す例
等価 (==)被演算子が等しい場合に true を返します。3 == var1 +

"3" == var1

+ 3 == '3'
不等価 (!=)被演算子が等しくない場合に true を返します。var1 != 4
+ var2 != "3"
厳密等価 (===)被演算子が等しく、かつ同じ型である場合に true を返します。{{jsxref("Object.is")}} や JavsScript での等価も参照してください。3 === var1
厳密不等価 (!==)被演算子が等しくなく、かつ/または同じ型でない場合に true を返します。var1 !== "3"
+ 3 !== '3'
より大きい (>)左の被演算子が右の被演算子よりも大きい場合に true を返します。var2 > var1
+ "12" > 2
以上 (>=)左の被演算子が右の被演算子以上である場合に true を返します。var2 >= var1
+ var1 >= 3
より小さい (<)左の被演算子が右の被演算子よりも小さい場合に true を返します。var1 < var2
+ "2" < 12
以下 (<=)左の被演算子が右の被演算子以下である場合に true を返します。var1 <= var2
+ var2 <= 5
+ +
+

メモ: (=>) は演算子ではなく、アロー関数を表す記法です。

+
+ +

算術演算子

+ +

算術演算子は被演算子として数値(リテラルまたは変数)をとり、1 つの数値を返します。標準的な算術演算子は、加算 (+)、減算 (-)、乗算 (*)、除算 (/) です。これらの演算子は、他のほとんどのプログラミング言語で浮動小数点数を用いた場合と同じように機能します(特に、0 で除算をすると {{jsxref("Infinity")}} になることに注意してください)。例えば以下のようになります。

+ +
1 / 2; // 0.5
+1 / 2 == 1.0 / 2.0; // true になります
+
+ +

標準的な算術演算子に加え、さらに JavaScript では、以下の表で示す算術演算子も使用できます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
算術演算子
演算子説明
剰余 (%)二項演算子です。2 つの被演算子で除算したときの、整数の余りを返します。12 % 5 は 2 を返します。
インクリメント (++)単項演算子です。被演算子に 1 を加えます。前置演算子 (++x) として用いると、被演算子に 1 を加えた後にその値を返します。後置演算子 (x++) として用いると、被演算子に 1 を加える前にその値を返します。x が 3 の場合、++xx に 4 を設定して 4 を返します。一方、x++ は 3 を返したあと x に 4 を設定します。
デクリメント (--)単項演算子です。被演算子から 1 を引きます。戻り値はインクリメント演算子のものと同様です。x が 3 の場合、--xx に 2 を設定して 2 を返します。一方、x-- は 3 を返したあと x に 2 を設定します。
単項符号反転 (-)単項演算子です。被演算子の符号を反転して、その値を返します。x が 3 のとき、-x は -3 を返します。
単項プラス (+)単項演算子です。数値でない被演算子の数値への変換を試みます。+"3"3 を返します。
+ +true1 を返します。
べき乗演算子 (**) {{experimental_inline}}基数部指数部乗したものを計算します、つまり、基数部指数部 となります。2 ** 38 を返します。
+ 10 ** -10.1 を返します。
+ +

ビット演算子

+ +

ビット演算子はその被演算子を 10進数や 16進数や 8進数ではなく、32 個のビットの集合(0 と 1)として扱います。例えば、10進数の 9 の 2進表現は 1001 です。ビット演算子はこのように 2進表現にした上で演算を行いますが、JavaScript において標準的な 10進数表現の数値を返します。

+ +

次の表は JavaScript のビット演算子の概要です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ビット演算子
演算子使用法説明
ビット論理積 (AND)a & b被演算子の対応するビットがともに 1 である各ビットについて 1 を返します。
ビット論理和 (OR)a | b被演算子の対応するビットがともに 0 である各ビットについて 0 を返します。
ビット排他的論理和 (XOR)a ^ b被演算子の対応するビットが同じ各ビットについて 0 を返します。
+ [被演算子の対応するビットが異なる各ビットについて 1 を返します。]
ビット否定 (NOT)~ a被演算子の各ビットを反転します。
左シフトa << b +

2進表現の ab ビット分だけ左にシフトします。右から 0 で詰めます。

+
符号維持右シフトa >> b2進表現の ab ビット分だけ右にシフトします。溢れたビットは破棄します。
ゼロ埋め右シフトa >>> b2進表現の ab ビット分だけ右にシフトします。溢れたビットは破棄し、左から 0 で詰めます。
+ +

ビット論理演算子

+ +

概念上、ビット論理演算子は以下のように機能します。

+ + + +

例えば 9 の 2進表現は 1001 で、15 の 2進表現は 1111 です。したがって、ビット演算子がこれらの値に適用されたときの結果は以下のようになります。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ビット演算子の例
演算式結果2進数での説明
15 & 991111 & 1001 = 1001
15 | 9151111 | 1001 = 1111
15 ^ 961111 ^ 1001 = 0110
~15-16~00000000...00001111 = 11111111...11110000
~9-10~00000000...00001001 = 11111111...11110110
+ +

ビット否定演算子を使うと 32 ビットすべてが反転し、その値の最上位(最左)ビットは負数を表す 1 に設定される(2 の補数表現)ことに注意してください。~x-x - 1 と同じ値に評価されます。

+ +

ビットシフト演算子

+ +

ビットシフト演算子は 2 つの被演算子をとります。第1被演算子はシフトされる数を指定し、第2被演算子は、第1被演算子をシフトさせるビット数を指定します。シフト演算の方向は使用する演算子によって決まります。

+ +

シフト演算子はその被演算子を 32 ビット整数に変換し、左の被演算子と同じ型で結果を返します。

+ +

シフト演算子の種類は次表のとおりです。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
ビットシフト演算子
演算子説明
左シフト
+ (<<)
この演算子は、第1被演算子を指定したビット数分だけ左にシフトします。左に溢れたビットは破棄されます。0 のビットを右から詰めます。9<<2 の結果は 36 になります。1001 を 2 ビット左にシフトすると 100100 になり、これは 36 となるからです。
符号維持右シフト (>>)この演算子は、第1被演算子を指定したビット数分だけ右にシフトします。右に溢れたビットは破棄されます。左端のビットのコピーを左から詰めます。9>>2 の結果は 2 になります。1001 を 2 ビット右にシフトすると 10 であり、これは 2 となるからです。同様に、-9>>2 の結果は、符号が維持されるため -3 になります。
ゼロ埋め右シフト (>>>)この演算子は、第1被演算子を指定したビット数分だけ右にシフトします。右に溢れたビットは破棄されます。0 のビットを左から詰めます。19>>>2 の結果は 4 になります。10011 を 2 ビット右にシフトすると 100 になり、これは 4 となるからです。非負数では、0 埋め右シフトと符号を維持した右シフトは同じ結果になります。
+ +

論理演算子

+ +

論理演算子では、基本的に{{原語併記("ブール値","Boolean value")}}(論理)値を用います。つまりブール値を取ると、ブール値を返します。しかし && および || 演算子については、実際には指定された被演算子の一方の値を返します。そのため、非ブール値とともに論理演算子が使われた場合、非ブール値を返す可能性があります。次表で論理演算子について説明します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
論理演算子
演算子使用法説明
論理積 (AND) (&&)expr1 && expr2expr1 を false と見ることができる場合は、expr1 を返します。そうでない場合は expr2 を返します。したがってブール値を用いた場合、両被演算子が true であれば && は true を返し、そうでなければ false を返します。
論理和 (OR) (||)expr1 || expr2expr1 を true と見ることができる場合は、expr1 を返します。そうでない場合は expr2 を返します。したがってブール値を用いた場合、どちらかの被演算子が true であれば || は true を返し、両方とも false であれば false を返します。
論理否定 (NOT) (!)!expr単一の被演算子を true と見ることができる場合は、false を返します。そうでない場合は true を返します。
+ +

false に変換される式としては、null、0、NaN、空文字列 ("")、undefined に評価される式が挙げられます。

+ +

以下のコードで && (論理 AND) 演算子の例を示します。

+ +
var a1 =  true && true;     // t && t は true を返す
+var a2 =  true && false;    // t && f は false を返す
+var a3 = false && true;     // f && t は false を返す
+var a4 = false && (3 == 4); // f && f は false を返す
+var a5 = 'Cat' && 'Dog';    // t && t は Dog を返す
+var a6 = false && 'Cat';    // f && t は false を返す
+var a7 = 'Cat' && false;    // t && f は false を返す
+
+ +

以下のコードで || (論理 OR) 演算子の例を示します。

+ +
var o1 =  true || true;     // t || t は true を返す
+var o2 = false || true;     // f || t は true を返す
+var o3 =  true || false;    // t || f は true を返す
+var o4 = false || (3 == 4); // f || f は false を返す
+var o5 = 'Cat' || 'Dog';    // t || t は Cat を返す
+var o6 = false || 'Cat';    // f || t は Cat を返す
+var o7 = 'Cat' || false;    // t || f は Cat を返す
+
+ +

以下のコードで !(論理 NOT) 演算子の例を示します。

+ +
var n1 = !true;  // !t は false を返す
+var n2 = !false; // !f は true を返す
+var n3 = !'Cat'; // !t は false を返す
+
+ +

短絡評価

+ +

論理式は左から右に評価されるため、以下のルールを用いた「{{原語併記("短絡","short-circuit")}}」評価によるテストが実行できます。

+ + + +

論理的なルールにより、これらの評価が常に正確であることが保証されます。上記の式で anything の部分は評価されないため、どのようにしても副作用が生じないことに注意してください。

+ +

2 番目のケースでは、最新のコードで || のように機能する新しい Null 合体演算子 (??) を使用できますが、最初の式が "nullish"、つまり null または undefined の場合にのみ 2 番目の式を返すことに注意してください。したがって、''0 などの値が最初の式の有効な値である場合は、デフォルトを提供することをお勧めします。

+ +

文字列演算子

+ +

文字列に対して使用することができる演算子には、比較演算子に加えて、2 つの文字列を結合する結合演算子 (+) があり、2 つの被演算子の文字列を結合した文字列を返します。

+ +

例えば、

+ +
console.log('my ' + 'string'); // 文字列 "my string" がログに表示される。
+ +

短縮表記した代入演算子 += も文字列の結合に使用できます。

+ +

例えば、

+ +
var mystring = 'alpha';
+mystring += 'bet'; // "alphabet" と評価されて、mystring にその値を代入します。
+ +

条件(三項)演算子

+ +

条件演算子は JavaScript で唯一 3 つの被演算子を取る演算子です。条件に基づいて 2 つの値のうち 1 つを選択します。構文は以下の通りです。

+ +
条件 ? 値1 : 値2
+
+ +

条件が真の場合、演算子は値1 の値を選択します。そうでない場合、値2 の値を選択します。標準的な演算子を使用できる場所ならどこでも条件演算子を使用できます。

+ +

例えば、

+ +
var status = (age >= 18) ? 'adult' : 'minor';
+
+ +

この文では、age が 18 以上の場合、変数 status に "adult" の値が代入されます。そうでない場合 status には "minor" が代入されます。

+ +

カンマ演算子

+ +

カンマ演算子 (,) は両側の被演算子を単純に評価し、最後の被演算子の値を返します。この演算子は主に for ループ内で使用され、これによりループのたびに複数の変数を更新できます。

+ +

例えば、一辺が 10 要素の 2 次元配列 a があったとして、以下のコードでカンマ演算子を用いて 2 つの変数を同時にインクリメントしています。このコードでは配列の対角成分の値を出力します。

+ +
var x = [0,1,2,3,4,5,6,7,8,9]
+var a = [x, x, x, x, x];
+
+for (var i = 0, j = 9; i <= j; i++, j--)
+//                                ^
+  console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
+
+ +

単項演算子

+ +

単項演算は被演算子を 1 つだけ取る演算です。

+ +

delete

+ +

delete 演算子はオブジェクトやオブジェクトのプロパティ、配列の指定されたインデックスの要素を削除します。構文は以下のとおりです。

+ +
delete object.property;
+delete object[propertyKey];
+delete objectName[index];
+delete property; // legal only within a with statement
+
+ +

ここで object はオブジェクトの名前を、property は既存のプロパティを、propertyKey は配列の要素の位置を示す整数をそれぞれ表しています。

+ +

4番目の形式は with 文内でのみ有効で、これはあるオブジェクトからプロパティを削除します。

+ +

delete を用いて暗黙的に宣言された変数を削除できますが、var 文で宣言された変数は削除できません。

+ +

delete 演算が成功すると、そのプロパティや要素には undefined がセットされます。また、演算が可能だった場合に delete 演算子は true を返します。演算が不可能である場合は false を返します。

+ +
x = 42; // 暗黙のうちに window.x を作成
+var y = 43;
+var myobj = {h: 4}; // プロパティ h を持つオブジェクトを作成
+
+delete x;       // false を返す (暗黙的に作成された場合は削除不可能)
+delete y;       // false を返す (var つきで宣言された場合は削除不可能)
+delete Math.PI; // false を返す (定義済みプロパティは削除不可能)
+delete myobj.h; // true を返す (ユーザー定義プロパティは削除可能)
+
+ +
配列要素の削除
+ +

配列は単なるオブジェクトの集まりであるため、技術的には各要素を削除することが可能です。しかしそれは悪しき慣例とみなされており、使用しないでください。配列の要素を削除したとき、配列の長さは影響を受けず、他の要素は再インデックスされません。この振る舞いを達成するのであれば、単に要素を undefined で上書きするほうがはるかに良い方法です。実際に配列を操作するためには、splice のようなさまざまな配列のメソッドを使用してください。

+ +

typeof

+ +

typeof 演算子は次の方法のうち、どちらかの方法で使用します。

+ +
typeof 被演算子
+typeof (被演算子)
+
+ +

typeof 演算子は、未評価の被演算子の型を指す文字列を返します。被演算子には返される型を調べる対象となる文字列、キーワード、オブジェクトを指定します。括弧はあってもなくてもかまいません。

+ +

以下の変数を定義することにしましょう。

+ +
var myFun = new Function('5 + 2');
+var shape = 'round';
+var size = 1;
+var foo = ['Apple', 'Mango', 'Orange'];
+var today = new Date();
+
+ +

typeof 演算子は、変数の型に応じて以下の値を返します。

+ +
typeof myFun;       // "function" を返す
+typeof shape;       // "string" を返す
+typeof size;        // "number" を返す
+typeof foo;         // "object" を返す
+typeof today;       // "object" を返す
+typeof doesntExist; // "undefined" を返す
+
+ +

truenull というキーワードに対して、typeof 演算子は以下の結果を返します。

+ +
typeof true; // "boolean" を返す
+typeof null; // "object" を返す
+
+ +

数値や文字列に対して、typeof 演算子は以下の結果を返します。

+ +
typeof 62;            // "number" を返す
+typeof 'Hello world'; // "string" を返す
+
+ +

プロパティ値に対して、typeof 演算子はプロパティが持つ値の型を返します。

+ +
typeof document.lastModified; // "string" を返す
+typeof window.length;         // "number" を返す
+typeof Math.LN2;              // "number" を返す
+
+ +

メソッドや関数に対して、typeof 演算子は以下の結果を返します。

+ +
typeof blur;        // "function" を返す
+typeof eval;        // "function" を返す
+typeof parseInt;    // "function" を返す
+typeof shape.split; // "function" を返す
+
+ +

定義済みオブジェクトに対して、typeof 演算子は以下の結果を返します。

+ +
typeof Date;     // "function" を返す
+typeof Function; // "function" を返す
+typeof Math;     // "object" を返す
+typeof Option;   // "function" を返す
+typeof String;   // "function" を返す
+
+ +

void

+ +

void 演算子は以下のどちらかの方法で使用します。

+ +
void (式)
+void 式
+
+ +

void 演算子は、値を返さずに評価する式を指定します。は評価する JavaScript の式となります。式の周りの括弧はあってもなくてもかまいませんが、使用する方が見た目がよいです。

+ +

関係演算子

+ +

関係演算子は被演算子を比較し、比較結果が真かどうかに基づいて Boolean の値を返します。

+ +

in

+ +

in 演算子は、指定したプロパティが指定のオブジェクトにある場合に true を返します。構文は以下のとおりです。

+ +
プロパティ名または数値 in オブジェクト名
+
+ +

ここで プロパティ名または数値はプロパティ名または配列のインデックスを表す文字列、数値または記号式を、オブジェクト名はオブジェクトの名前をそれぞれ表します。

+ +

次の例で in 演算子の使用法を示します。

+ +
// 配列
+var trees = ['redwood', 'bay', 'cedar', 'oak', 'maple'];
+0 in trees;        // true を返す
+3 in trees;        // true を返す
+6 in trees;        // false を返す
+'bay' in trees;    // false を返す(インデックスの指す値ではなく、
+                   // インデックスの数字を指定しなければならない)
+'length' in trees; // true を返す(length は Array のプロパティ)
+
+// 定義済みオブジェクト
+'PI' in Math;          // true を返す
+var myString = new String('coral');
+'length' in myString;  // true を返す
+
+// ユーザー定義オブジェクト
+var mycar = { make: 'Honda', model: 'Accord', year: 1998 };
+'make' in mycar;  // returns true
+'model' in mycar; // returns true
+
+ +

instanceof

+ +

instanceof 演算子は、指定されたオブジェクトが指定されたオブジェクトの種類である場合に true を返します。構文は以下のとおりです。

+ +
オブジェクト名 instanceof オブジェクト型
+
+ +

ここでオブジェクト名オブジェクト型と比較するオブジェクトの名前を、オブジェクト型は {{jsxref("Date")}} や {{jsxref("Array")}} のようなオブジェクトの種類をそれぞれ表します。

+ +

実行時にオブジェクトの種類を確認する必要があるときは instanceof を使用してください。例えば例外を受け取るとき、発生した例外の種類に応じて、別々の例外を扱うコードに分岐することができます。

+ +

例えば次のコードでは、instanceof を使用して theDayDate オブジェクトであるかを判断しています。theDayDate オブジェクトであるため、if 文中の文が実行されます。

+ +
var theDay = new Date(1995, 12, 17);
+if (theDay instanceof Date) {
+  // 実行する文
+}
+
+ +

演算子の優先順位

+ +

演算子の優先順位によって、式評価の際に演算子が適用される順番が定義されています。括弧を用いることで演算子の優先順位を上書きすることができます。

+ +

次の表では演算子の優先順位を、高いものから低い順に並べています。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子の優先順位
演算子の種類対応する演算子
メンバー. []
インスタンスの呼び出し/作成() new
否定/インクリメント! ~ - + ++ -- typeof void delete
乗算/除算* / %
加算/減算+ -
ビットシフト<< >> >>>
関係< <= > >= in instanceof
等値== != === !==
ビット論理積&
ビット排他的論理和^
ビット論理和|
論理積&&
論理和||
条件?:
代入= += -= *= /= %= <<= >>= >>>= &= ^= |= &&= ||= ??=
カンマ,
+ +

それぞれの演算子についてのリンクを含むこの表の詳細版に関しては JavaScript リファレンスを参照してください。

+ +

+ +

とは、ある値へと決定される有効なコードの単位のことです。

+ +

文法的に正しい式は必ず何らかの値に決定されますが、概念的に、副作用の有無によって 2種類にわけられます。代入演算は副作用のあるものの代表です。副作用の無いものは、式そのものが評価されその値が決定されます。

+ +

x = 7 という式が前者の例です。この式では x に 7 という値を代入するのに = 演算子を使っています。この式自体は 7 と評価されます。

+ +

3 + 4 という式は後者の例です。この式では 3 と 4 を加算するのに + 演算子を使っており、計算結果の 7 を変数に代入していません。
+
+ JavaScript には、以下の種類の式があります。

+ + + +

基本式

+ +

JavaScript における基本のキーワードと一般的な式です。

+ +

this

+ +

this キーワードを使用することで現在のオブジェクトを参照できます。一般的に this は、あるメソッド内で呼び出されるオブジェクトを参照します。this の使用法は以下のとおりです。

+ +
this['propertyName']
+this.propertyName
+
+ +

オブジェクトと上限および下限の値を渡し、そのオブジェクトの value プロパティを検証する validate という関数があるとしましょう。

+ +
function validate(obj, lowval, hival) {
+  if ((obj.value < lowval) || (obj.value > hival))
+    console.log('Invalid Value!');
+}
+
+ +

次の例のように、各フォーム要素の onChange イベントハンドラにおいて validate を呼び出し、その関数にフォーム要素を渡すのに this を使うことができます。

+ +
<p>Enter a number between 18 and 99:</p>
+<input type="text" name="age" size=3 onChange="validate(this, 18, 99);">
+
+ +

グループ化演算子

+ +

グループ化演算子 ( ) は式内での評価の優先順位を制御します。例えば、加算が最初に評価されるよう、最初に行われる演算を乗算と除算から加算と減算へと上書きすることができます。

+ +
var a = 1;
+var b = 2;
+var c = 3;
+
+// デフォルトの優先順位
+a + b * c     // 7
+// デフォルトではこのように評価される
+a + (b * c)   // 7
+
+// 優先順位を上書きし、
+// 乗算の前に加算を行う
+(a + b) * c   // 9
+
+// この式と同等となる
+a * c + b * c // 9
+
+ +

左辺式

+ +

左辺値は、代入する宛先です。

+ +

new

+ +

new 演算子は、ユーザー定義オブジェクトやビルトインオブジェクトのインスタンス作成に使用します。new の使用法は以下のとおりです。

+ +
var オブジェクト名 = new objectType([引数1, 引数2, ..., 引数N]);
+
+ +

super

+ +

super キーワードは自分の親のオブジェクトに関数を呼び出すのに使います。これは下の例のように、クラスと共に使って親のコンストラクタを呼び出すのに便利です。

+ +
super([引数]); // 親のコンストラクタを呼び出す。
+super.親の関数([引数]);
+
+ +
{{PreviousNext("Web/JavaScript/Guide/Functions", "Web/JavaScript/Guide/Numbers_and_dates")}}
diff --git a/files/ja/web/javascript/guide/functions/index.html b/files/ja/web/javascript/guide/functions/index.html new file mode 100644 index 0000000000..c519b43ae3 --- /dev/null +++ b/files/ja/web/javascript/guide/functions/index.html @@ -0,0 +1,696 @@ +--- +title: 関数 +slug: Web/JavaScript/Guide/Functions +tags: + - Beginner + - Functions + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Functions +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}
+ +

関数は JavaScript の基本的な構成要素のひとつです。また関数は、JavaScript の手続き ― つまり、タスクや値計算を実行する文の集まりです。関数を使うには、呼び出したいスコープ内のどこかでそれを定義する必要があります。

+ +

より詳しくは JavaScript の関数に関する完全なリファレンスについての章をご覧ください。

+ +

関数を定義する

+ +

関数の宣言

+ +

関数の定義関数の宣言や{{原語併記("関数定義文","function statement")}} とも呼ばれます)は function キーワードと、それに続く以下の内容で構成されます。

+ + + +

例えば、次のコードは square という名前の簡単な関数を定義します :

+ +
function square(number) {
+  return number * number;
+}
+
+ +

関数 squarenumber という名前の引数を 1 つとります。この関数は、引数(すなわち number)の 2 乗を返すように指示する 1 つの文で構成されています。return 文は、関数が返す値を指定します。

+ +
return number * number;
+
+ +

プリミティブなパラメータ(数値など)は値渡しで関数に渡されます。つまり、値は関数に渡されますが、関数がパラメータの値を変更しても、この変更はグローバルな値や関数の呼び出し元の値には影響を与えません

+ +

オブジェクト(すなわち非プリミティブ値、例えば {{jsxref("Array")}} オブジェクトやユーザー定義オブジェクトなど)をパラメータとして渡すと、関数がオブジェクトのプロパティを変更した場合、その変更が関数外でも有効になります。次の例をご覧ください :

+ +
function myFunc(theObject) {
+  theObject.make = 'Toyota';
+}
+
+var mycar = {make: 'Honda', model: 'Accord', year: 1998};
+var x, y;
+
+x = mycar.make; // x は "Honda" という値になる
+
+myFunc(mycar);
+y = mycar.make; // y は "Toyota" という値になる
+                //(プロパティが関数で変更されている)
+
+ +

関数式

+ +

ここまでの関数宣言はすべて構文的な文でしたが、関数は関数式によって作成することもできます。このような関数は{{原語併記("無名","anonymous")}} にできます。名前をつけなくてもよいのです。例えば、関数 square は次のように定義できます :

+ +
const square = function(number) { return number * number }
+var x = square(4) // x の値は 16 となる
+ +

ただし関数式は名前をつけることもでき、関数内で自身を参照することや、デバッガーのスタックトレースで関数を特定することに利用できます:

+ +
const factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) }
+
+console.log(factorial(3))
+
+ +

関数式は、ある関数を別の関数の引数として渡すときに便利です。次の例では map 関数を定義し、第 1 引数に関数を取り、第 2 引数に配列を取ります:

+ +
function map(f, a) {
+  let result = []; // 新しい配列を作成
+  let i; // 変数の宣言
+  for (i = 0; i != a.length; i++)
+    result[i] = f(a[i]);
+  return result;
+}
+
+ +

下記のコードでは、この関数は関数式で定義された関数を受け取って、2 つ目の引数で受け取った配列の各要素に対して実行しています。

+ +
function map(f, a) {
+  let result = []; // 新しい配列を作成
+  let i; // 変数の宣言
+  for (i = 0; i != a.length; i++)
+    result[i] = f(a[i]);
+  return result;
+}
+var f = function(x) {
+   return x * x * x;
+}
+let numbers = [0, 1, 2, 5, 10];
+let cube = map(f,numbers);
+console.log(cube);
+ +

これは [0, 1, 8, 125, 1000] を返します。

+ +

JavaScript では、条件に基づいて関数を定義することもできます。例えば次の関数の定義は、変数 num が 0 に等しい場合のみ myFunc という関数を定義します :

+ +
var myFunc;
+if (num === 0) {
+  myFunc = function(theObject) {
+    theObject.make = 'Toyota';
+  }
+}
+ +

これまで説明してきた関数の定義に加えて、{{jsxref("Function")}} コンストラクタを、{{jsxref( "eval", "eval()")}} のように文字列からの関数作成に用いることができます。

+ +

メソッドは、オブジェクトのプロパティである関数のことです。オブジェクトとメソッドについて詳しくは、「オブジェクトを利用する」の章をご覧ください。

+ +

関数を呼び出す

+ +

関数を定義しても、その関数が実行されるわけではありません。関数の定義とは、ただ単に関数に名前をつけ、その関数が呼び出されたときに何をするかを指定することです。関数の呼び出しは、実際に指定したパラメータを用いて指定された動作を実行するということです。例えば、関数 square を定義した場合、次のようにしてそれを呼び出すことができます:

+ +
square(5);
+
+ +

この文は 5 という引数とともに関数を呼び出します。関数は自身の文を実行し、25 という値を返します。

+ +

関数は呼び出されるスコープ内になければいけませんが、次の例のように、関数の宣言は呼び出しより後に置くことができます :

+ +
console.log(square(5));
+/* ... */
+function square(n) { return n * n }
+
+ +

関数のスコープは自身が宣言された関数内、あるいはトップレベルで宣言されたのであればプログラム全体になります。

+ +
+

注: この動作は、上記の構文(すなわち function funcName(){})を用いて関数を定義したときに限ることに注意してください。次のコードは動作しません。

+ +

これは、関数の巻き上げが関数式ではなく関数宣言でしか機能しないことを意味しています。

+ +
console.log(square)    // square は初期値が undefined の状態で巻き上げられています。
+console.log(square(5)) // Uncaught TypeError: square is not a function
+const square = function(n) {
+  return n * n;
+}
+
+
+ +

関数の引数は、文字列や数値に限られてはいません。オブジェクト全体を関数に渡すこともできます。show_props 関数(「オブジェクトを利用する」の章で定義)は、オブジェクトを引数にとる関数の例です。

+ +

関数はその関数自身を呼び出すこともできます。例えば、ここに階乗を計算する関数を示します:

+ +
function factorial(n) {
+  if ((n === 0) || (n === 1))
+    return 1;
+  else
+    return (n * factorial(n - 1));
+}
+
+ +

1 から 5 までの階乗の計算は、次のようになります:

+ +
var a, b, c, d, e;
+a = factorial(1); // a の値は 1 となる
+b = factorial(2); // b の値は 2 となる
+c = factorial(3); // c の値は 6 となる
+d = factorial(4); // d の値は 24 となる
+e = factorial(5); // e の値は 120 となる
+
+ +

関数を呼び出す方法は他にもあります。関数を動的に呼び出す、関数の引数の数を変える、関数を呼び出すコンテキストを実行時に決まる特定のオブジェクトにセットするといった場合があります。

+ +

関数は関数であるとともにオブジェクトでもあり、また結果としてそれらのオブジェクトはメソッドを持っています({{jsxref("Function")}} オブジェクトをご覧ください)。そうしたメソッドのひとつ、{{jsxref("Function/apply","apply()")}} メソッドを用いることでこの目的を実現できます。

+ +

関数のスコープ

+ +

関数の内部で宣言された変数は、関数の外部からアクセスすることができません。これは、変数が関数のスコープ内でのみ定義されているためです。その一方、関数は自身が定義されたスコープ内で定義されているすべての変数や関数にアクセスできます。

+ +

言い換えると、グローバルスコープで定義された関数は、グローバルスコープで定義されたすべての変数にアクセスできます。ある関数の内部で宣言された関数は、自身の親となる関数内で定義されたすべての変数や、その関数がアクセス権を持つ他の変数にもアクセスできます。

+ +
// 以下の変数はグローバルスコープで定義
+var num1 = 20,
+    num2 = 3,
+    name = 'Chamahk';
+
+// この関数はグローバルスコープで定義
+function multiply() {
+  return num1 * num2;
+}
+
+multiply(); // 60 を返す
+
+// 入れ子になっている関数の例
+function getScore () {
+  var num1 = 2,
+      num2 = 3;
+
+  function add() {
+    return name + ' scored ' + (num1 + num2);
+  }
+
+  return add();
+}
+
+getScore(); // "Chamahk scored 5" を返す
+
+ +

スコープと関数スタック

+ +

再帰

+ +

関数は自身を参照し、そして呼び出すことができます。関数が自身を参照する方法は 3 種類あります :

+ +
    +
  1. 関数名
  2. +
  3. arguments.callee
  4. +
  5. 関数を参照したスコープ内変数
  6. +
+ +

例えば、以下のような関数定義を考えてみましょう :

+ +
var foo = function bar() {
+   // ここには文が来る
+}
+
+ +

関数本体の中で、以下のものはすべて同様の意味となります :

+ +
    +
  1. bar()
  2. +
  3. arguments.callee()
  4. +
  5. foo()
  6. +
+ +

自身を呼び出す関数のことを再帰関数と言います。いくつかの点で、再帰はループに似ています。どちらも同じコードを何度も実行しますし、条件(無限ループを防ぐため、というより無限再帰を防ぐため)が必要です。例えば、以下のループは、:

+ +
var x = 0;
+while (x < 10) { // "x < 10" がループ条件
+   // 何らかの処理を行う
+   x++;
+}
+
+ +

再帰関数とその呼び出しとに置き換えることができます :

+ +
function loop(x) {
+  if (x >= 10) // "x >= 10" が終了条件 ("!(x < 10)" と同等)
+    return;
+  // 何らかの処理を行う
+  loop(x + 1); // 再帰呼出し
+}
+loop(0);
+
+ +

一方で、単純な反復ループでは行えないアルゴリズムもあります。例えば、ツリー構造のすべてのノード(例えば DOM )を取得するのに、再帰を使うとより簡単に行えます :

+ +
function walkTree(node) {
+  if (node == null) //
+    return;
+  // ノードに対し処理を行う
+  for (var i = 0; i < node.childNodes.length; i++) {
+    walkTree(node.childNodes[i]);
+  }
+}
+
+ +

関数 loop と比較して、それぞれの再帰呼出しによってさらに多数の再帰呼出しが行われています。

+ +

どんな再帰アルゴリズムも再帰でないものに書き換えることが可能です、しかしロジックはより複雑になり、データをスタックしておく必要がたびたび出てきます。実際、再帰自体がスタックを使用しています。それが関数スタックです。

+ +

以下の例で、スタックとはどういったふるまいをするのか見ることができます :

+ +
function foo(i) {
+  if (i < 0)
+    return;
+  console.log('begin: ' + i);
+  foo(i - 1);
+  console.log('end: ' + i);
+}
+foo(3);
+
+// 出力:
+
+// begin: 3
+// begin: 2
+// begin: 1
+// begin: 0
+// end: 0
+// end: 1
+// end: 2
+// end: 3
+ +

入れ子の関数とクロージャ

+ +

関数の中に関数を入れ子に(ネスト)することができます。入れ子になった(内部の)関数は、それを含んでいる(外部の)関数からはプライベートとなります。

+ +

これによりクロージャが作られます。クロージャとは、環境に束縛された(式によって「閉じ込められた」)変数を自由に持たせることができる式(通常は一つの関数)のことです。

+ +

入れ子になった関数はクロージャなので、これはつまり、入れ子になった関数は内包する関数の引数と変数を「継承」することができるということです。別の言い方をすれば、内部の関数は外部の関数のスコープを持っているということです。

+ +

まとめると :

+ + + +

以下の実例では入れ子になった関数が示されています :

+ +
function addSquares(a, b) {
+  function square(x) {
+    return x * x;
+  }
+  return square(a) + square(b);
+}
+a = addSquares(2, 3); // 13 を返す
+b = addSquares(3, 4); // 25 を返す
+c = addSquares(4, 5); // 41 を返す
+
+ +

内部の関数はクロージャとなるので、外部の関数からクロージャを呼び出し、外部と内部両方の関数に対し引数を指定することができます :

+ +
function outside(x) {
+  function inside(y) {
+    return x + y;
+  }
+  return inside;
+}
+fn_inside = outside(3); // このように考えてください : 与えられたものに 3 を加算する関数を代入します
+
+result = fn_inside(5); // 8 を返す
+
+result1 = outside(3)(5); // 8 を返す
+
+ +

変数の保護

+ +

inside が返されるとき、変数 x がどのように保護されるのかに注目してください。クロージャはそれ自身が参照しているすべてのスコープ内の引数と変数を保護することになります。それぞれの呼び出しには異なる引数が渡される可能性があるので、それぞれの outside の呼び出しに対し新しいクロージャが作られます。返された inside がもはやアクセスできなくなった時にのみメモリーは開放されます。

+ +

これはその他のオブジェクトの内部で参照を保持する場合と違いはないのですが、クロージャの場合は直接参照を設定せず、また情報を取得できないので、明白さは劣ります。

+ +

多重入れ子関数

+ +

関数は多重に入れ子にすることができます。例えば :

+ + + +

このようにして、クロージャは多重スコープを導入できます。つまり関数のスコープが再帰的に包含されているのです。これをスコープチェーンと呼びます。(なぜ「チェーン」と呼ぶのかは後で説明します。)

+ +

次の例を見てみましょう :

+ +
function A(x) {
+  function B(y) {
+    function C(z) {
+      console.log(x + y + z);
+    }
+    C(3);
+  }
+  B(2);
+}
+A(1); // 6 がログに出力される (1 + 2 + 3)
+
+ +

この例では、関数 C は関数 B の引数 y と関数 A の引数 x にアクセスしています。

+ +

なぜこれが可能かというと :

+ +
    +
  1. 関数 B は関数 A に含まれたクロージャとなっています、言い換えると BA の引数と変数にアクセスできます。
  2. +
  3. 関数 C は関数 B に含まれたクロージャとなっています。
  4. +
  5. クロージャ BA の中にあり、クロージャ CA の中にあるので、CBそしてさらに A の引数と変数にアクセスできます。言い換えれば、CBA の順でスコープが{{原語併記("つながっている","chain")}} のです。
  6. +
+ +

その一方で、逆は成り立ちません。AC にアクセスできません、なぜなら A は、C を変数の一つとして持っている B の引数や変数にはアクセスできないからです。このように CB からのみプライベートとなっています。

+ +

名前衝突

+ +

クロージャ中のスコープに同じ名前の 2 つの引数や変数がある場合、名前衝突が生じます。より内部のスコープが優先されるので、最内部にあるスコープが最優先に、一方最も外側のスコープが最も低い優先度となります。これがスコープチェーンです。チェーンの最初は最内部のスコープ、そして最後は最外部のスコープとなります。次の例を見てみましょう :

+ +
function outside() {
+  var x = 5;
+  function inside(x) {
+    return x * 2;
+  }
+  return inside;
+}
+
+outside()(10); // 10 ではなく 20 を返す
+
+ +

return x の箇所で、inside の引数 xoutside の変数 x との間に名前衝突が起きています。ここでのスコープチェーンは、{ inside, outside, グローバルオブジェクト } です。したがって insidexoutsidex より優先され、結果 10 (outsidex)ではなく、20 (insidex)が返されます。

+ +

クロージャ

+ +

クロージャは、JavaScript でもっとも強力な機能のひとつです。JavaScript では関数の入れ子が可能であることに加えて、内側の関数が外側の関数内で定義されたすべての変数や関数に対し(外側の関数がアクセスできる、他の変数や関数すべてにも)自由にアクセスできます。

+ +

しかし、外側の関数は内側の関数内で定義された変数や関数にアクセスできません。これは、内側の関数の変数に対する一種のセキュリティ機構を提供します。

+ +

また、内側の関数は外側の関数のスコープにアクセスできることから、もし内側の関数が外側の関数よりも長く生存できた場合、外側の関数内で定義された変数や関数は外側の関数よりも長く残る可能性があります。クロージャは、内側の関数が何かしらの形で外側の関数のスコープ外のどこかで使用可能になった場合に作られます。

+ +
var pet = function(name) {      // 外側の関数は変数 "name" を定義
+  var getName = function() {
+    return name;                // 内側の関数は外側の関数の変数 "name" にアクセス可能
+  }
+  return getName;               // 内側の関数を返すことで、外側の関数に公開する
+}
+myPet = pet('Vivie');
+
+myPet();                        // "Vivie" を返す
+
+ +

上記のコードより複雑なコードにすることもできます。外側の関数の内部にある変数を操作するメソッドを含む、オブジェクトを返すことができます。

+ +
var createPet = function(name) {
+  var sex;
+
+  return {
+    setName: function(newName) {
+      name = newName;
+    },
+
+    getName: function() {
+      return name;
+    },
+
+    getSex: function() {
+      return sex;
+    },
+
+    setSex: function(newSex) {
+      if(typeof newSex === 'string' && (newSex.toLowerCase() === 'male' ||
+        newSex.toLowerCase() === 'female')) {
+        sex = newSex;
+      }
+    }
+  }
+}
+
+var pet = createPet('Vivie');
+pet.getName();                  // Vivie
+
+pet.setName('Oliver');
+pet.setSex('male');
+pet.getSex();                   // male
+pet.getName();                  // Oliver
+
+ +

上記の例で、外側の関数の変数 name は内側の関数からアクセスでき、また内側の関数を通さずに内側の変数へアクセスする他の方法はありません。内側の関数の内部変数は、内側の関数の安全な保存領域として振る舞います。それらは内側の関数と連動するデータを、「永続的」かつ「安全に」保持します。関数は変数を割り当てる必要さえなく、また名前を持つ必要もありません。

+ +
var getCode = (function(){
+  var apiCode = '0]Eal(eh&2';    // 外部の関数が変更できないようにしたいコード
+
+  return function() {
+    return apiCode;
+  };
+})();
+
+getCode();    // シークレットコードを返す
+
+ +
+

警告: クロージャーを使用する際に注意すべき落とし穴がいくつかあります。

+ +取り囲まれている関数で外部スコープの変数と同じ名前の変数を定義した場合、外部スコープにある変数を再び参照する方法がなくなります。(プログラムが内部スコープを終了するまで、内部スコープ変数は外部変数を「上書き」します。) + +
var createPet = function(name) {  // 外側の関数で "name" という変数を定義します。
+  return {
+    setName: function(name) {    // 内側の関数も "name" という変数を定義します
+      name = name;               // 外側の関数で定義した "name" へどのようにしてアクセスするのか?
+    }
+  }
+}
+
+
+ +

arguments オブジェクトの使用

+ +

関数の{{原語併記("引数", "argument")}}は、配列状オブジェクトで管理されます。関数内では、次のようにして渡された引数を指定することができます :

+ +
arguments[i]
+
+ +

ここで i は引数の順序を表す数で、0 から始まります。関数に渡された第 1 引数は arguments[0] となります。引数のトータルの数は arguments.length で表されます。

+ +

arguments オブジェクトを使用すると、宣言時の引数の数よりも多くの引数を用いて関数を呼び出すことができます。これによって関数に渡す引数の数が前もってわからない場合にしばしば役立ちます。arguments.length を使用することで、実際に関数に渡された引数の数を特定することができます。そして、arguments オブジェクトを使用して各引数にアクセスできます。

+ +

例えば、複数の文字列を連結する関数を考えます。この関数の引数は、連結するアイテムを区切るのに用いる文字列のみです。この関数は次のように定義されています :

+ +
function myConcat(separator) {
+   var result = '', // リストを初期化する
+   var i;
+   // 引数について繰り返し
+   for (i = 1; i < arguments.length; i++) {
+      result += arguments[i] + separator;
+   }
+   return result;
+}
+
+ +

この関数に引数をいくつも渡すことができます。そして、各引数を文字列の "リスト" に連結します:

+ +
// "red, orange, blue, " を返す
+myConcat(', ', 'red', 'orange', 'blue');
+
+// "elephant; giraffe; lion; cheetah; " を返す
+myConcat('; ', 'elephant', 'giraffe', 'lion', 'cheetah');
+
+// "sage. basil. oregano. pepper. parsley. " を返す
+myConcat('. ', 'sage', 'basil', 'oregano', 'pepper', 'parsley');
+
+ +
+

注記 : 変数 arguments は "配列状の変数" であり、配列ではありません。これは数値のインデックスと length プロパティがあることで、配列状となってはいます。しかし、配列操作のメソッドのすべては持っていません。

+
+ +

さらなる情報については、JavaScript リファレンスの {{jsxref("Function")}} オブジェクトをご覧ください。

+ +

関数の引数

+ +

ECMAScript 2015 から、新しい形の引数が 2 つあります。それがデフォルト引数残余引数です。

+ +

デフォルト引数

+ +

JavaScript では、関数の引数はデフォルトで undefined となります。しかし、別のデフォルト値が設定されていれば便利だという状況もあるでしょう。デフォルト引数がここで役に立ちます。

+ +

デフォルト引数なし(ECMAScript 2015 以前)

+ +

以前、デフォルト値を設定する一般的な方法は、関数の本体で引数の値をテストし、undefined だった場合にある値を割り当てる、というものでした。

+ +

以下の例では、呼び出しの際に b に値が割り当てられない場合、a*b の評価の際に b の値は undefined となるため、multiply を呼び出すと NaN が返されます。しかしながら、例の 2 行目でこの問題を回避しています :

+ +
function multiply(a, b) {
+  b = typeof b !== 'undefined' ?  b : 1;
+
+  return a * b;
+}
+
+multiply(5); // 5
+
+ +

デフォルト引数あり(ECMAScript 2015 以降)

+ +

デフォルト引数を使えば、関数本体での引数チェックはもう必要ありません。これからは、関数の最初で単純に b1 を代入することができます :

+ +
function multiply(a, b = 1) {
+  return a * b;
+}
+
+multiply(5); // 5
+ +

詳細については、リファレンスの「デフォルト引数」をご覧ください。

+ +

残余引数

+ +

残余引数の構文によって、不特定多数の引数を配列のように表すことができます。

+ + +

次の例では、2 つ目から最後までの引数をまとめるのに残余引数を使っています。そして最初の引数を使って乗算します。(ここでは次の章で紹介するアロー関数を使っています。)

+ +
function multiply(multiplier, ...theArgs) {
+  return theArgs.map(x => multiplier * x);
+}
+
+var arr = multiply(2, 1, 2, 3);
+console.log(arr); // [2, 4, 6]
+ +

アロー関数

+ +

アロー関数式(以前は、そして現在は正しくないがファットアロー関数としても知られる)は関数式と比較してより短い構文を持ち、thisargumentssupernew.target の値を持ちません。アロー関数は常に無名関数です。hacks.mozilla.org によるこのブログ記事もご覧ください : "ES6 In Depth: Arrow functions"

+ +

アロー関数の導入には 2 つの要素が絡んでいます。それは短縮形の関数this束縛しないことです。

+ +

短縮形の関数

+ +

関数パターンによっては、短縮形の関数がうってつけです。比較してみましょう :

+ +
var a = [
+  'Hydrogen',
+  'Helium',
+  'Lithium',
+  'Beryllium'
+];
+
+var a2 = a.map(function(s) { return s.length; });
+
+console.log(a2); // logs [8, 6, 7, 9]
+
+var a3 = a.map(s => s.length);
+
+console.log(a3); // logs [8, 6, 7, 9]
+
+ +

別々の this はない

+ +

アロー関数の導入以前は、すべての新しい関数には自身の this 値が定義されています(コンストラクターの場合は新しいオブジェクトに、strict モード の関数呼び出しの場合は undefined に、関数が「オブジェクトのメソッド」として呼び出された場合はその基底オブジェクトに、といったように)。これはオブジェクト指向プログラミングにとっては厄介です。

+ +
function Person() {
+  // この Person() コンストラクタは自身を `this` と定義します。
+  this.age = 0;
+
+  setInterval(function growUp() {
+    // Strict モードでない場合、この growUp() 関数は
+    // Person() コンストラクタによる定義とは異なり、
+    // グローバルオブジェクトを `this` として定義します。
+    this.age++;
+  }, 1000);
+}
+
+var p = new Person();
+ +

ECMAScript 3/5 では、this の値をアクセス可能な別の値に割り当てることでこの問題を解決します。

+ +
function Person() {
+  var self = this; // `self` の代わりに `that` を選ぶ人もいます。
+                   // どちらか一方を選び、そちらだけを使うようにしましょう。
+  self.age = 0;
+
+  setInterval(function growUp() {
+    // このコールバックは、その値が期待通りのオブジェクトを指す
+    // 変数 `self` を参照している。
+    self.age++;
+  }, 1000);
+}
+ +

代わりに、束縛関数を使って変数を束縛すれば growUp() 関数に適切な this を渡すことができます。

+ +

アロー関数は自身の this を持ちません、つまり関数を取り囲む実行コンテキストの this の値が使われます。このため、下記のコードでは、setInterval に渡される関数内の this は、それを取り囲む関数の this と同じ値を持ちます:

+ +
function Person(){
+  this.age = 0;
+
+  setInterval(() => {
+    this.age++; // `this` は的確に person オブジェクトを参照する
+  }, 1000);
+}
+
+var p = new Person();
+ +

定義済み関数

+ +

JavaScript には、定義済みのトップレベル関数が数種類あります :

+ +
+
{{jsxref("Global_Objects/eval", "eval()")}}
+
+

eval() メソッドは文字列として書き表された JavaScript のコードを評価します。

+
+
{{jsxref("Global_Objects/uneval", "uneval()")}}
+
+

uneval() メソッドは{{jsxref("Object","オブジェクト","","true")}}のソースコードを表す文字列を生成します。

+
+
{{jsxref("Global_Objects/isFinite", "isFinite()")}}
+
+

このグローバル関数 isFinite() は渡された値が有限数であるかを判定します。必要であれば、引数は初めに数へと変換されます。

+
+
{{jsxref("Global_Objects/isNaN", "isNaN()")}}
+
+

isNaN() 関数は値が {{jsxref("Global_Objects/NaN", "NaN")}}(非数)であるかどうかを判定します。注記 : isNaN 関数内での強制型変換は変わったルールを持っています。値が非数であるかを判定するには、代わりに ECMAScript 2015 で定義された {{jsxref("Number.isNaN()")}} か、typeof を使うことができます。

+
+
{{jsxref("Global_Objects/parseFloat", "parseFloat()")}}
+
+

parseFloat() 関数は引数の文字列をパースして浮動小数点数を返します。

+
+
{{jsxref("Global_Objects/parseInt", "parseInt()")}}
+
+

parseInt() 関数は引数の文字列をパースして指定された基数(数学的記数法における基数)による整数を返します。

+
+
{{jsxref("Global_Objects/decodeURI", "decodeURI()")}}
+
+

decodeURI() 関数は前もって {{jsxref("Global_Objects/encodeURI", "encodeURI")}} 関数によって、あるいは同様の方法で作られた{原語併記("統一資源識別子","Uniform Resource Identifier, URI"}} をデコードします。

+
+
{{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent()")}}
+
+

decodeURIComponent() メソッドは前もって {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} によって、あるいは同様の方法で作られた統一資源識別子 (URI) をデコードします。

+
+
{{jsxref("Global_Objects/encodeURI", "encodeURI()")}}
+
+

encodeURI() メソッドは特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 文字から 4 文字のエスケープシーケンス(サロゲートペア文字からなる文字にのみ 4 文字のエスケープシーケンスが必要)に置き換えることで統一資源識別子 (URI) をエンコードします。

+
+
{{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent()")}}
+
+

encodeURIComponent() メソッドは特定の文字をそれぞれ UTF-8 文字エンコーディングで表された 1 文字から 4 文字のエスケープシーケンス(サロゲートペア文字からなる文字にのみ 4 文字のエスケープシーケンスが必要)に置き換えることで統一資源識別子 (URI) コンポーネントをエンコードします。

+
+
{{jsxref("Global_Objects/escape", "escape()")}}
+
+

廃止予定の escape() メソッドはある文字列を 16 進数によるエスケープシーケンスで置換した新しい文字列を計算します。代わりに {{jsxref("Global_Objects/encodeURI", "encodeURI")}} か {{jsxref("Global_Objects/encodeURIComponent", "encodeURIComponent")}} を使用してください。

+
+
{{jsxref("Global_Objects/unescape", "unescape()")}}
+
+

廃止予定の unescape() メソッドはある文字列中の 16 進数によるエスケープシーケンスを、それが表す所定の文字に置換した新しい文字列を計算します。エスケープシーケンスは {{jsxref("Global_Objects/escape", "escape")}} といった関数によって提供されているかもしれません。unescape() は廃止予定なので、代わりに {{jsxref("Global_Objects/decodeURI", "decodeURI()")}} か {{jsxref("Global_Objects/decodeURIComponent", "decodeURIComponent")}} を使用してください。

+
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Loops_and_iteration", "Web/JavaScript/Guide/Expressions_and_Operators")}}

diff --git a/files/ja/web/javascript/guide/grammar_and_types/index.html b/files/ja/web/javascript/guide/grammar_and_types/index.html new file mode 100644 index 0000000000..b32688e6d7 --- /dev/null +++ b/files/ja/web/javascript/guide/grammar_and_types/index.html @@ -0,0 +1,762 @@ +--- +title: 文法とデータ型 +slug: Web/JavaScript/Guide/Grammar_and_types +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Grammar_and_types +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}
+ +

この節では JavaScript の基本文法、変数宣言、データ型、リテラルについて説明します。

+ +

基本

+ +

JavaScript は Java, C, C++ から構文の多くを取り入れていますが、Awk, Perl, Python からも影響を受けています。

+ +

また、JavaScript は大文字と小文字を区別し、また Unicode 文字セットを使用しています。例えば、Früh という単語 (ドイツ語で "early" という意味) を変数名として使用することができます。

+ +
let Früh = "foobar"
+ +

ただし、JavaScript は大文字と小文字を区別するので、früh という変数は Früh と同じではありません。

+ +

JavaScript では、命令は{{Glossary("Statement", "文")}} (statement) と呼ばれ、セミコロン (;) によって区切られています。

+ +

文が単独の行で書かれている場合、文の後にセミコロンは必要ではありません。しかし、行の中に複数の文が必要な場合は、セミコロンで区切る必要があります。

+ +
+

ECMAScript も文末に自動的にセミコロンを挿入する規則があります (ASI)。(詳しくは、JavaScript の 字句文法についての詳細なリファレンスを参照してください。)

+
+ +

必須ではないとしても、文の後に常にセミコロンを記述することをお勧めします。これによって、コード中にバグが発生する機会を減らすことができます。

+ +

JavaScript のソーステキストは左から右にスキャンされ、トークン制御文字改行文字コメント、{{glossary("whitespace", "ホワイトスペース")}}等の入力要素の並びに変換されます。(空白、タブ、改行はホワイトスペースとみなされます。)

+ +

コメント

+ +

コメントの構文は C++ やその他の多くの言語と一緒です。

+ +
// 一行のコメント
+
+/* もっと長い、
+   複数行からなるコメント
+ */
+
+/* ただし、/* 入れ子のコメントは */ できず、SyntaxError となります */
+
+ +

コメントはホワイトスペースのように扱われ、スクリプトの実行から除外されます。

+ +
+

: 一部の JavaScript ファイルの先頭で、#!/usr/bin/env node のような第三の種類のコメントを見かけることもあるかもしれません。

+ +

これはハッシュバンコメント構文と呼ばれ、スクリプトの実行に使用したい特定の JavaScript エンジンへのパスを指定するのに使用される特殊なコメントです。詳しくはハッシュバンコメントを参照してください。

+
+ +

宣言

+ +

JavaScript には変数を宣言する方法が 3種類あります。

+ +
+
{{jsxref("Statements/var", "var")}}
+
変数を宣言し、ある値に初期化することもできる。
+
{{jsxref("Statements/let", "let")}}
+
ブロックスコープのローカル変数を宣言し、ある値に初期化することもできる。
+
{{jsxref("Statements/const", "const")}}
+
ブロックスコープで読み取り専用の名前付き定数を宣言する。
+
+ +

変数

+ +

変数はアプリケーションで値を表す記号的な名前として使用します。変数の名前は{{Glossary("Identifier", "識別子")}}とも呼ばれ、一定のルールに従わなくてはなりません。

+ +

JavaScript の識別子は必ず文字、アンダースコア (_)、あるいはドル記号 ($) から始まらなくてはなりません。続く文字には数字 (09) も使用できます。

+ +

JavaScript は大文字・小文字を区別するため、使用できる文字には "A" から "Z" (大文字) に加えて "a" から "z" (小文字) も含まれます。

+ +

åü などの ISO 8859-1 や Unicode 文字 (詳しくはこのブログ記事を参照) も識別子に使用することができます。Unicode エスケープシーケンスも識別子に使用することができます。

+ +

Number_hitstemp99_name などは、正しい名前の一例です。

+ +

変数の宣言

+ +

変数を宣言する方法は 2通りあります。

+ + + +

分割代入構文を使用して、オブジェクトリテラルから値を展開する変数を宣言することができます。例えば、let { bar } = foo とします。これは bar という名前の変数を作成し、オブジェクト foo の同名キーから対応する値を代入します。

+ +

また、x = 42 のように、単純に値を変数に代入することもできます。この形は、未宣言のグローバル変数を生成します。strict モードの JavaScript では警告が発生します。未宣言のグローバル変数は、よく予期しない動作を引き起こします。したがって、宣言されていないグローバル変数を使用することはお勧めしません。

+ +

変数の評価

+ +

var または let 文を使用して初期値なしで宣言された変数は、{{jsxref("undefined")}} の値をとります。

+ +

未宣言の変数にアクセスしようとすると、{{jsxref("ReferenceError")}} 例外が発生します。

+ +
var a;
+console.log('変数 a の値は ' + a); // 変数 a の値は undefined
+
+console.log('変数 b の値は ' + b); // 変数 b の値は undefined
+var b;
+// これは後述の「変数の巻き上げ」を読むまでは謎かもしれません
+
+console.log('変数 c の値は ' + c); // キャッチされない ReferenceError: c が定義されていない
+
+let x;
+console.log('変数 x の値は ' + x); // 変数 x の値は undefined
+
+console.log('変数 y の値は ' + y); // キャッチされない ReferenceError: y が定義されていない
+let y; 
+ +

undefined を使うと変数に値が入っているかは確認できます。以下のコードでは変数 input に値が代入されておらず、if 文は true と評価されます。

+ +
var input;
+if (input === undefined) {
+  doThis();
+} else {
+  doThat();
+}
+
+ +

undefined は真偽値のコンテキストで使用されると false としてふるまいます。例えば以下のコードでは、myArray の要素が undefined であるために関数 myFunction が実行されます。

+ +
var myArray = [];
+if (!myArray[0]) myFunction();
+
+ +

undefined は数値のコンテキストで使用されると NaN に変換されます。

+ +
var a;
+a + 2;  // NaN と評価される
+ +

{{jsxref("null")}} を評価する際、数値のコンテキストでは null 値は 0 としてふるまいます。また真偽値のコンテキストでは false としてふるまいます。例えば、

+ +
var n = null;
+console.log(n * 32); // log 0 をコンソールに出力
+
+ +

変数のスコープ

+ +

変数を関数の外側で宣言すると、その変数はその文書のどのコードからも使用できるようになるため、グローバル (大域) 変数と呼ばれます。変数を関数の内部で宣言すると、その変数はその関数の中でしか使用できないため、ローカル (局所) 変数と呼ばれます。

+ +

ECMAScript 2015 より前の JavaScript にはブロック文のスコープがありません。正確に言えば、ブロック内で宣言した変数はブロックを内包している関数 (あるいはグローバルスコープ) に対して局所化されます。

+ +

例えば、以下のコードでは 5 が出力されます。これは、x のスコープがグローバルコンテキスト (または以下のコードが関数の中であれば関数) だからです。x のスコープは中間の if 文のブロックに限定されません。

+ +
if (true) {
+  var x = 5;
+}
+console.log(x);  // x は 5
+
+ +

このふるまいは、let (ECMAScript 2015 で導入) を使うことで変わります。

+ +
if (true) {
+  let y = 5;
+}
+console.log(y);  // ReferenceError: y が定義されていない
+
+ +

変数の巻き上げ

+ +

もうひとつ、JavaScript の変数にまつわる独特な点として、例外を発生させることなく後に宣言した変数を参照できる点が挙げられます。

+ +

この考え方は巻き上げとして知られています。JavaScript の変数は、ある意味「巻き上げられ」、関数や文の先頭まで持ち上げられます。しかし、巻き上げられた変数は undefined 値を返します。そのため、変数を使用したり参照した後に宣言や初期化を行うと、undefined が返されたままになります。

+ +
/**
+ * 例 1
+ */
+console.log(x === undefined); // true
+var x = 3;
+
+/**
+ * 例 2
+ */
+// undefined 値が返される
+var myvar = 'my value';
+
+(function() {
+  console.log(myvar); // undefined
+  var myvar = 'local value';
+})();
+
+ +

上記の例は以下と同様に解釈されます。

+ +
/**
+ * 例 1
+ */
+var x;
+console.log(x === undefined); // true
+x = 3;
+
+/**
+ * 例 2
+ */
+var myvar = 'my value';
+
+(function() {
+  var myvar;
+  console.log(myvar); // undefined
+  myvar = 'local value';
+})();
+
+ +

巻き上げがあるため、関数内にあるすべての var 文は関数内で可能な限り先頭に近い位置に置くべきです。これはコードの明確さを高める最善の方法です。

+ +

ECMAScript 2015 では、let および const巻き上げが行われますが、初期化されません。ブロック内の変数宣言前に変数を参照すると、変数はブロックの先頭から宣言が処理されるまでの間、「一時的なデッドゾーン」にあるため、{{jsxref("ReferenceError")}} になります。

+ +
console.log(x); // ReferenceError
+let x = 3;
+ +

関数の巻き上げ

+ +

関数の場合、関数宣言のみが巻き上げられますが、関数は巻き上げられません

+ +
/* 関数宣言 */
+
+foo(); // "bar"
+
+function foo() {
+  console.log('bar');
+}
+
+
+/* 関数式 */
+
+baz(); // TypeError: baz は関数ではない
+
+var baz = function() {
+  console.log('bar2');
+};
+
+ +

グローバル変数

+ +

グローバル変数は、実際にはグローバルオブジェクトのプロパティです。

+ +

ウェブページでのグローバルオブジェクトは {{domxref("window")}} になります、そのため window.変数名 という構文を用いてグローバル変数の設定やアクセスができます。

+ +

したがって、あるウィンドウやフレームで宣言したグローバル変数は、そのウィンドウやフレームの名前を指定することで別の windowframe からアクセスできます。例えば phoneNumber 変数を文書内で宣言すると、iframe から parent.phoneNumber としてその変数を参照できます。

+ +

定数

+ +

{{jsxref("Statements/const", "const")}} キーワードを用いて、読み取り専用の名前付き定数を作成できます。

+ +

定数の識別子の構文は、変数の識別子の構文と同じです。識別子は文字、アンダースコア、ドル記号 ($) から始めなくてはならず、アルファベット、数値、アンダースコアを含めることができます。

+ +
const PI = 3.14;
+
+ +

定数は代入によって値を変えたり、スクリプト実行中に再宣言したりすることはできません。定数はある値に初期化しなければなりません。

+ +

定数のスコープルールは、let によるブロックスコープ変数と同じです。const キーワードを省略すると、その識別子は変数を表すとみなされます。

+ +

以下の例のように、同一スコープ内で関数や変数と同じ名前の定数を宣言することはできません。

+ +
// THIS WILL CAUSE AN ERROR
+function f() {};
+const f = 5;
+
+// この場合もエラーが発生
+function f() {
+  const g = 5;
+  var g;
+
+  // ここには文が来る
+}
+
+ +

しかし、定数が代入されたオブジェクトのプロパティは保護されず、以下の文は問題なく実行できます。

+ +
const MY_OBJECT = {'key': 'value'};
+MY_OBJECT.key = 'otherValue';
+ +

また、配列の中身は保護されませんので、以下の文は問題なく実行できます。

+ +
const MY_ARRAY = ['HTML','CSS'];
+MY_ARRAY.push('JAVASCRIPT');
+console.log(MY_ARRAY); //logs ['HTML','CSS','JAVASCRIPT'];
+
+ +

データ構造とデータ型

+ +

データ型

+ +

最新の ECMAScript 標準では、以下の 8 つのデータ型が定義されています。

+ + + +

このようにデータ型の種類は比較的少ないですが、アプリケーションで便利な関数を実行することができます。整数と実数の間に明確な違いはありません。{{jsxref("Object", "オブジェクト","","true")}}と{{jsxref("Function", "関数","","true")}}も言語において基本的な要素です。オブジェクトは値を収める名前付きコンテナとして、関数はスクリプトを実行可能にする手続きとして考えることができます。

+ +

データ型の変換

+ +

JavaScript は動的型付け言語です。そのため変数宣言時にデータ型を指定する必要がなく、またスクリプト実行時に必要に応じてデータ型が自動的に変換されます。

+ +

例えば以下のように変数を定義したとします。

+ +
var answer = 42;
+
+ +

その後、同じ変数に文字列を代入できます。

+ +
answer = 'Thanks for all the fish...';
+
+ +

JavaScript は動的型付け方式であるため、この代入を行ってもにエラーメッセージは表示されません。

+ +

数値と '+' 演算子

+ +

数値と文字列を + 演算子で結合する式では、JavaScript は数値を文字列に変換します。以下の式を見てみましょう。

+ +
x = '答えは ' + 42 // "答えは 42"
+y = 42 + ' が答え' // "42 が答え"
+
+ +

それ以外の演算子がある式では、JavaScript は数値を文字列に変換しません。例えば以下のようになります。

+ +
'37' - 7 // 30
+'37' + 7 // "377"
+
+ +

文字列から数値への変換

+ +

数値を表す値が文字列として記憶されている場合、それを変換するメソッドがあります。

+ + + +

parseInt は整数のみを返すので、小数は切り捨てられます。

+ +
+

さらに、parseInt を使う最も良い方法は、常に基数を引数に含めるようにすることです。基数の引数は使用されている基数法を指定するのに使われます。

+
+ +
parseInt('101', 2) // 5
+ +

文字列から数値を取り出す代替手段は、+ (単項プラス) 演算子を使う方法です。

+ +
'1.1' + '1.1' // '1.11.1'
+(+'1.1') + (+'1.1') // 2.2
+// 注: 括弧は明確さのために追加したもので、必須ではありません
+ +

リテラル

+ +

JavaScript では値の表現にリテラルを使います。これらは固定値であり変数ではなく、スクリプト中に直接記述します。本章では、以下のリテラルについて説明します :

+ + + +

配列リテラル

+ +

配列リテラルとは、0 個以上の式のリストであり、各々の式は配列の要素を表し、角括弧 ([]) で括られているもののことです。配列リテラルを用いて配列を作成すると、指定された値が要素として初期化され、また配列の長さ (length) は指定された引数の個数に設定されます。

+ +

以下の例では 3 つの要素を持ち、配列 coffees を長さ (length) 3 で作成します。

+ +
let coffees = ['French Roast', 'Colombian', 'Kona'];
+
+ +
+

注: 配列リテラルはオブジェクト初期化子の一種です。オブジェクト初期化子の使用を参照してください。

+
+ +

トップレベルのスクリプト内でリテラルを用いて配列を作成した場合、JavaScript は配列リテラルを含む式を評価するたびに配列を解釈します。さらに関数内で使用されたリテラルは、関数が呼び出されるたびに生成されます。

+ +
+

配列リテラルは Array オブジェクトでもあります。Array オブジェクトの詳細は {{jsxref("Array")}} とインデックス付きコレクションをご覧ください。

+
+ +

配列リテラルでの余分なカンマ

+ +

配列リテラルですべての要素を指定する必要はありません。立て続けに 2 つのカンマを置くと、配列は未指定の要素を undefined の値で埋めます。次の例では fish という配列を作成します。

+ +
let fish = ['Lion', , 'Angel'];
+
+ +

この配列は、値を持つ要素を 2 つと空の要素を 1 つ持っています。

+ + + +

要素のリストの最後にカンマを付けた場合、そのカンマは無視されます。

+ +

次の例では、配列の長さ (length) は 3 です。myList[3] は存在しません。リスト内の他のカンマはすべて、新しい要素を示します。

+ +
+

注: 末尾にカンマを置くと古いブラウザーでエラーになる場合があるので、取り除くのが最善です。

+
+ +
let myList = ['home', , 'school', ];
+
+ +

次の例では、配列の長さ (length) は 4 になります。myList[0]myList[2] が抜けています。

+ +
let myList = [ ,'home', , 'school'];
+
+ +

次の例では、配列の長さ (length) は 4 です。myList[1]myList[3] が抜けています。最後のカンマのみが無視されます。

+ +
let myList = ['home', , 'school', , ];
+
+ +

余分なカンマの動作を理解することは、言語としての JavaScript を理解するために重要です。

+ +

しかし、コードを記述する際に欠落している要素を明示的に undefined するようにしてください。そうすれば、コードの明確さや保守性が高まります。

+ +

真偽値リテラル

+ +

真偽値型は 2 つのリテラル値、truefalse があります。

+ +
+

忠告: プリミティブ型の真偽値である truefalse と、{{jsxref("Boolean")}} オブジェクトの truefalse という値とを混同してはいけません。

+ +

Boolean オブジェクトは、プリミティブな真偽値型のラッパーです。詳細は {{jsxref("Boolean")}} を参照してください。

+
+ +

数値リテラル

+ +

{{jsxref("Number")}} および {{jsxref("BigInt")}} 型は、10進数、16進数、8進数、2進数で書くことができます。

+ + + +

数値リテラルの例は以下のようになります。

+ +
0, 117, -345, 123456789123456789n             (10進数)
+015, 0001, -0o77, 0o777777777777n             (8進数)
+0x1123, 0x00111, -0xF1A7, 0x123456789ABCDEFn  (16進数)
+0b11, 0b0011, -0b11, 0b11101001010101010101n  (2進数)
+
+ +

詳しい情報は、字句構文リファレンスの数値リテラルをご覧ください。

+ +

浮動小数点リテラル

+ +

浮動小数点リテラルは、以下の部分で構成されます。

+ + + +

指数部は、"e" または "E" の後に、符号 ( "+" or "-") を先行させることできる整数が続く形になります。浮動小数点数リテラルは少なくとも 1 つの数字と、小数点もしくは "e" (または "E") が必要です。

+ +

より簡潔に書けば、次の形式になります。

+ +
[(+|-)][digits].[digits][(E|e)[(+|-)]digits]
+
+ +

例えば以下の通りです。

+ +
3.1415926
+-.123456789
+-3.1E+12
+.1e-23
+
+ +

オブジェクトリテラル

+ +

オブジェクトリテラルとは、プロパティ名とそれに関連付けられたオブジェクトの値との 0 個以上の組が波括弧 ({}) で囲まれたもので作られたリストです。

+ +
+

オブジェクトリテラルを文の先頭で使わないようにしてください。 { がブロックの始まりと解釈されるため、エラーや予期せぬ動作を引き起こすことになります。

+
+ +

以下にオブジェクトリテラルの例を示します。car オブジェクトの最初の要素には myCar プロパティが定義され、新規文字列 "Saturn" が割り当てられています。2番目の要素、getCar プロパティには関数 (carTypes("Honda")); によって呼び出された結果が即座に割り当てられます。3番目の要素、special プロパティには既存の変数 (sales) が使われています。

+ +
var sales = 'Toyota';
+
+function carTypes(name) {
+  if (name === 'Honda') {
+    return name;
+  } else {
+    return "Sorry, we don't sell " + name + ".";
+  }
+}
+
+var car = { myCar: 'Saturn', getCar: carTypes('Honda'), special: sales };
+
+console.log(car.myCar);   // Saturn
+console.log(car.getCar);  // Honda
+console.log(car.special); // Toyota
+
+ +

さらに、数値リテラルや文字列リテラルをプロパティ名に使用したり、オブジェクトを別のオブジェクトの入れ子にすることができます。以下の例では、これらの機能を使用しています。

+ +
var car = { manyCars: {a: 'Saab', b: 'Jeep'}, 7: 'Mazda' };
+
+console.log(car.manyCars.b); // Jeep
+console.log(car[7]); // Mazda
+
+ +

オブジェクトのプロパティには空の文字列を含むあらゆる文字列が使えます。もしプロパティ名が JavaScript で有効な{{Glossary("Identifier", "識別子")}}か数値でなければ、引用符で囲む必要があります。

+ +

有効でない識別子によるプロパティ名にはドット演算子 (.) を使ってアクセスできませんが、配列のような表記法 ("[]") でアクセス、設定ができます。

+ +
var unusualPropertyNames = {
+  '': '空文字列',
+  '!': 'バン!'
+}
+console.log(unusualPropertyNames.'');   // SyntaxError: Unexpected string が発生
+console.log(unusualPropertyNames['']);  // 空文字列
+console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token ! が発生
+console.log(unusualPropertyNames['!']); // バン!
+ +

拡張オブジェクトリテラル

+ +

ES2015 では、オブジェクトリテラルは構築時のプロトタイプの設定に対応するよう拡張され、foo: foo 形式の短縮表記の値割り当て、メソッドの定義、super の呼び出し、式によるプロパティ名の計算ができるようになりました。

+ +

同時に、オブジェクトリテラルとクラス定義が近くなり、オブジェクトベースの設計でも同じ利便性の一部から利益を得ることができます。

+ +
var obj = {
+    // __proto__
+    __proto__: theProtoObj,
+    // 短い ‘handler: handler’ の形式
+    handler,
+    // メソッド
+    toString() {
+     // super の呼び出し
+     return 'd ' + super.toString();
+    },
+    // 計算による (動的な) プロパティ名
+    [ 'prop_' + (() => 42)() ]: 42
+};
+
+ +

正規表現リテラル

+ +

正規表現リテラル (後で詳しく定義) は、スラッシュで囲まれたパターンです。以下は正規表現リテラルの例です。

+ +
var re = /ab+c/;
+ +

文字列リテラル

+ +

文字列リテラルとは、0文字以上の文字を二重引用符 (") または単一引用符 (') で括ったものです。文字列は同じ種類の引用符で括らなければなりません (つまり、どちらも単一引用符にするか、またはどちらも二重引用符にするかです)。

+ +

以下が文字列リテラルの例です。

+ +
'foo'
+"bar"
+'1234'
+'one line \n another line'
+"John's cat"
+
+ +

文字列リテラルを持つ値は、{{jsxref("String")}} オブジェクトのあらゆるメソッドを呼び出すことができます。JavaScript は自動的に文字列リテラルを一時的な String オブジェクトに変換し、メソッドを呼び出して、その後一時的に作られた String オブジェクトを破棄します。String.length プロパティを文字列リテラルで用いることもできます。

+ +
// ホワイトスペースを含む文字列の文字の数を出力する。
+console.log("John's cat".length)  // この場合は 10 が出力される。
+
+ +

ECMAScript 2015 では、テンプレートリテラルも利用することができます。テンプレートリテラルは、二重引用符や単一引用符の代わりに逆引用符 (`) (grave accent) で囲まれたものです。

+ +

テンプレート文字列は文字列の構築に糖衣構文を利用することができます。これは Perl や Python などの文字列補完機能に似ています。

+ +

また、文字列の構築をカスタマイズして、インジェクション攻撃を防いだり文字列コンテンツのより高水準のデータ構造を構築したりするためにタグを追加することができます。

+ +
// 基本的な文字列リテラルの作成
+`In JavaScript '\n' is a line-feed.`
+
+// 複数行の文字列
+`In JavaScript, template strings can run
+ over multiple lines, but double and single
+ quoted strings cannot.`
+
+// 文字列補完
+var name = 'Bob', time = 'today';
+`Hello ${name}, how are you ${time}?`
+
+// 置換や構築を解釈するために使用される HTTP リクエストの接頭辞を構築
+POST`http://foo.org/bar?a=${a}&b=${b}
+     Content-Type: application/json
+     X-Credentials: ${credentials}
+     { "foo": ${foo},
+       "bar": ${bar}}`(myOnReadyStateChangeHandler);
+ +

特に String オブジェクトを使う必要がない場合は、文字列リテラルを使うようにしてください。詳細は {{jsxref("String")}} をご覧ください。

+ +

文字列での特殊文字の使用

+ +

文字列では、通常の文字に加えて特殊文字も使用できます。次の例をご覧ください。

+ +
'one line \n another line'
+
+ +

ここで、JavaScript の文字列で使用できる特殊文字の表を示します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
表: JavaScript の特殊文字
文字意味
\0ヌル文字
\bバックスペース
\f改ページ
\n改行
\r復帰
\tタブ
\v垂直タブ
\'アポストロフィまたは単一引用符
\"二重引用符
\\バックスラッシュ (\)
\XXX0 から 377 までの 3桁の 8進数 XXX で指定された、Latin-1 エンコーディングの文字。
+ 例えば、\251 は著作権記号を示します。
\xXX +

00 から FF までの 2桁の 16進数 XX で指定された、Latin-1 エンコーディングの文字。
+ 例えば、\xA9 は著作権記号を示します。

+
\uXXXX4桁の 16 進数 XXXX で指定された Unicode 文字。
+ 例えば、\u00A9 は著作権記号を示します。Unicode エスケープシーケンスをご覧ください。
\u{XXXXX}Unicode コードポイントエスケープです。
+ 例えば \u{2F804} は単純な Unicode エスケープである \uD87E\uDC04 と同じです。
+ +

文字のエスケープ

+ +

上記の表に掲載されていない文字は直前にバックスラッシュをつけても無視されますが、こうした使い方は非推奨であり使用を避けるべきです。

+ +

バックスラッシュを直前につけることで、引用符を文字列に含めることができます。これは引用符のエスケープと呼ばれます。例えば以下のようにします。

+ +
var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
+console.log(quote);
+
+ +

この結果は次のようになります。

+ +
He read "The Cremation of Sam McGee" by R.W. Service.
+
+ +

文字列にバックスラッシュそのものを含めるには、バックスラッシュのエスケープが必要です。例えば、文字列に c:\temp というファイルパスを代入するには、以下のようにします。

+ +
var home = 'c:\\temp';
+
+ +

改行の直前にバックスラッシュを置くことで、改行をエスケープすることもできます。バックスラッシュと改行の両方が、文字列の値から取り除かれます。

+ +
var str = 'this string \
+is broken \
+across multiple \
+lines.'
+console.log(str);   // この文字列は複数行にわたって分解されます。
+
+ +

JavaScript には「ヒアドキュメント」構文はありませんが、各行の末尾に改行のエスケープ表記とエスケープした改行を置くことで似たことができます。

+ +
var poem =
+'Roses are red,\n\
+Violets are blue.\n\
+Sugar is sweet,\n\
+and so is foo.'
+
+ +

ECMAScript 2015 ではテンプレートリテラルと呼ばれる新しい種類のリテラルが導入されました。これによって複数行の文字列を含む多数の新機能が利用できるようになりました。

+ +
var poem =
+`Roses are red,
+Violets are blue.
+Sugar is sweet,
+and so is foo.` 
+ +

関連情報

+ +

本章では宣言とデータ型についての基本文法に重点を置いています。JavaScript の言語構成についてより詳しく知りたければ、当ガイドの以下に挙げた章をご覧ください。

+ + + +

次章では、制御フローの構造とエラー処理について見ていきます。

+ +

{{PreviousNext("Web/JavaScript/Guide/Introduction", "Web/JavaScript/Guide/Control_flow_and_error_handling")}}

diff --git a/files/ja/web/javascript/guide/index.html b/files/ja/web/javascript/guide/index.html new file mode 100644 index 0000000000..9e89757ae6 --- /dev/null +++ b/files/ja/web/javascript/guide/index.html @@ -0,0 +1,138 @@ +--- +title: JavaScript ガイド +slug: Web/JavaScript/Guide +tags: + - Guide + - JavaScript + - 'l10n:priority' + - ガイド +translation_of: Web/JavaScript/Guide +--- +
{{jsSidebar("JavaScript Guide")}}
+ +

この JavaScript ガイドでは、JavaScript の使い方を紹介し、この言語の概要を説明します。JavaScript の機能についてもっと知りたい場合は、JavaScript リファレンス を参照してください。

+ +

目次

+ +

このガイドは、いくつかの章に分かれています。

+ + + + + + + + + +

{{Next("Web/JavaScript/Guide/Introduction")}}

diff --git a/files/ja/web/javascript/guide/indexed_collections/index.html b/files/ja/web/javascript/guide/indexed_collections/index.html new file mode 100644 index 0000000000..6675d1a97c --- /dev/null +++ b/files/ja/web/javascript/guide/indexed_collections/index.html @@ -0,0 +1,598 @@ +--- +title: インデックス付きコレクション +slug: Web/JavaScript/Guide/Indexed_collections +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Indexed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}
+ +

この節では、インデックス値により順序付けされたデータのコレクションを紹介します。配列、{{jsxref("Array")}} オブジェクト、{{jsxref("TypedArray")}} オブジェクトなどの配列用の構造体があります。

+ +

Array オブジェクト

+ +

配列は名前やインデックスで参照できる値からなる順序集合です。例えば、emp という配列を作成し、従業員番号と従業員の名前を対応付けることができます。つまり、emp[1] が従業員番号 1 、emp[2] が従業員番号 2 、のようになります。

+ +

JavaScript は明確な配列データ型を持っていません。しかし、アプリケーションで配列として機能する定義済みの Array オブジェクトとそのメソッドを利用できます。Array オブジェクトには配列の結合、反転、ソートなど様々な方法で配列を操作するメソッドがあります。また、配列の長さを特定するプロパティや、正規表現で使用するプロパティなどがあります。

+ +

配列の生成

+ +

以下の文は同じ配列を生成します。

+ +
let arr = new Array(element0, element1, ..., elementN)
+let arr = Array(element0, element1, ..., elementN)
+let arr = [element0, element1, ..., elementN]
+
+ +

element0, element1, ..., elementN は配列要素になる値から構成されるリストです。これらの値が指定されると、この配列の要素はそれらの値に初期化されます。配列の length プロパティは引数の数に設定されます。

+ +

角括弧による構文は「配列リテラル」または「配列初期化子」と呼ばれます。この構文はその他の形式による配列作成よりも短いため、一般的に好まれる方法です。詳細については、配列リテラルをご覧ください。

+ +

長さがゼロではないが項目のない配列を作成するには、以下の方法が使用できます。

+ +
// これはこ...
+let arr = new Array(arrayLength)
+
+// ...このような結果になります
+let arr = Array(arrayLength)
+
+
+// これも同じ効果があります
+let arr = []
+arr.length = arrayLength
+
+ +
+

注: 上記のコードでは、arrayLengthNumber(数値)である必要があります。さもないと、(指定した値の)単一の要素を持つ配列が生成されます。arr.length を呼び出すと arrayLength が返されますが、実際には配列は空要素 (undefined) で構成されます。この配列で {{jsxref("Statements/for...in","for...in")}} ループを実行しても、配列の要素は返されません。

+
+ +

上記のように新規に定義した変数に割り当てるだけでなく、新規または既存のオブジェクトのプロパティに配列を割り当てることができます。

+ +
let obj = {}
+// ...
+obj.prop = [element0, element1, ..., elementN]
+
+// または
+let obj = {prop: [element0, element1, ...., elementN]}
+
+ +

単一の要素で配列を初期化しようとして、その要素が Number である場合、角括弧の構文を使用する必要があります。単一の Number 値が Array() コンストラクタや関数に渡されると、単一の数値要素としてではなく、arrayLength として解釈されます。

+ +
let arr = [42]       // 42 という数の要素を
+                     // 1 個だけ持つ配列が作られます。
+
+let arr = Array(42)  // 要素がなく、arr.length が
+                     // 42 に設定された配列が作られます。
+                     //
+                     // 以下のコードと同様です。
+let arr = []
+arr.length = 42
+
+ +

N の値が小数部分がゼロではない実数である場合、Array(N) を呼び出すと、結果は RangeError になります。以下の例ではこの動作を示します。

+ +
let arr = Array(9.3)   // RangeError: Invalid array length
+
+ +

任意のデータ型の単一の要素を持つ配列を作成したければ、配列リテラルを使用する方が安全です。あるいは、単一の要素を追加する前に空の配列を作成しましょう。

+ +

ES2015 から単一の要素を持つ配列を生成するために {{jsxref("Array.of")}} 静的メソッドを使用することができます。

+ +
let wisenArray = Array.of(9.3)   // wisenArray は 1 つの要素 9.3 だけを持つ配列
+ +

配列要素の参照

+ +

要素はプロパティでもあるので、プロパティアクセサーを使ってアクセスすることができます。以下の配列を定義するとします。

+ +
let myArray = ['Wind', 'Rain', 'Fire']
+
+ +

要素のインデックスは 0 から始まるので、配列の 1 番目の要素を myArray[0]、2 番目の要素を myArray[1] と呼ぶことができます。

+ +
+

注: プロパティアクセサーを使用して、オブジェクトのように配列の他のプロパティにアクセスすることもできます。

+ +
let arr = ['one', 'two', 'three']
+arr[2]          // three
+arr['length']   // 3
+
+
+ +

配列へのデータ追加

+ +

要素に値を割り当てることで配列にデータを追加することができます。例えば、

+ +
let emp = []
+emp[0] = 'Casey Jones'
+emp[1] = 'Phil Lesh'
+emp[2] = 'August West'
+
+ +
+

注: 上記のコードで配列演算子(角括弧)内に非整数値を指定すると、配列要素ではなく配列を表すオブジェクトのプロパティとして作成されます。

+ +
var arr = [];
+arr[3.4] = 'Oranges';
+console.log(arr.length);                // 0
+console.log(arr.hasOwnProperty(3.4));   // true
+
+
+ +

配列を作成するときにも、データを追加することができます。

+ +
let myArray = new Array('Hello', myVar, 3.14159)
+// または
+let myArray = ['Mango', 'Apple', 'Orange']
+
+ +

配列の長さの理解

+ +

実装レベルでは、JavaScript の配列は、配列のインデックスをプロパティ名として使用して、その要素を標準的なオブジェクトのプロパティとして格納します。

+ +

length プロパティは特別です。これは常に最終要素のインデックス +1 を返します(次の例では、'Dusty' のインデックスは 30 なので、cats.length30 + 1 を返します)。

+ +

JavaScript の配列のインデックスは 0 から始まることを覚えておいてください。これは、length プロパティは配列に格納されている最大のインデックスより 1 つ多い値になるということです。

+ +
var cats = [];
+cats[30] = ['Dusty'];
+console.log(cats.length); // 31
+
+ +

length プロパティに値を割り当てることもできます。

+ +

格納されているアイテムの数より小さい値を設定すると、配列は切り捨てられます。すなわち、0 に設定すると完全に配列を空にします。

+ +
let cats = ['Dusty', 'Misty', 'Twiggy'];
+console.log(cats.length); // 3
+
+cats.length = 2;
+console.log(cats); // ログに "Dusty, Misty"  - Twiggy は削除される
+
+cats.length = 0;
+console.log(cats); // ログに [ ] 、配列 cats は空になる
+
+cats.length = 3;
+console.log(cats); // ログに [ <3 個の空スロット> ]
+
+ +

配列の反復処理

+ +

よく行われるのは配列に含まれる値に対し、それぞれの値について、なんらかの処理を行うことです。これを行う一番簡単な方法は次のとおりです。

+ +
let colors = ['red', 'green', 'blue'];
+for (var i = 0; i < colors.length; i++) {
+  console.log(colors[i]);
+}
+
+ +

配列内の要素がいずれも真偽値としては false に評価されないことがわかっている場合 ― 例えば配列が DOM ノードのみで構成されている場合などには、例のように、より効率的な表現を使用できます。

+ +
let divs = document.getElementsByTagName('div');
+for (var i = 0, div; div = divs[i]; i++) {
+  /* div に対して何らか処理をする */
+}
+
+ +

この例では、配列の長さのチェックに掛かるオーバーヘッドを回避しています。そしてより便利に使えるように、ループの反復のたびに div 変数に現在の項目を代入するようにしています。

+ +

配列を反復処理する別の方法として {{jsxref("Array.forEach", "forEach()")}} メソッドがあります。

+ +
let colors = ['red', 'green', 'blue'];
+colors.forEach(function(color) {
+  console.log(color);
+});
+// red
+// green
+// blue
+
+ +

あるいは、ES2015 のアロー関数式を forEach の引数にしてコードを短縮することもできます。

+ +
let colors = ['red', 'green', 'blue'];
+colors.forEach(color => console.log(color));
+// red
+// green
+// blue
+
+ +

forEach に渡される関数では、その関数への引数に配列の要素が渡されて、配列内の各項目ごとに 1 回ずつ実行されます。値が割り当てられていない要素は forEach ループで反復されません。

+ +

配列定義の際に省略された要素は、forEach によって反復処理されるときには現れませんが、配列要素に undefined が割り当てられている場合は現れることに注意してください。

+ +
let array = ['first', 'second', , 'fourth']
+
+array.forEach(function(element) {
+  console.log(element)
+})
+// first
+// second
+// fourth
+
+if (array[2] === undefined) {
+  console.log('array[2] is undefined')  // true
+}
+
+array = ['first', 'second', undefined, 'fourth']
+
+array.forEach(function(element) {
+  console.log(element)
+})
+// first
+// second
+// undefined
+// fourth
+
+ +

JavaScript では、配列の要素は標準的なオブジェクトプロパティとして保存されるので、{{jsxref("Statements/for...in","for...in")}} ループを使って JavaScript 配列を反復処理するのはお勧めできません。というのも、通常の要素とすべての列挙可能なプロパティが現れるからです。

+ +

配列のメソッド

+ +

{{jsxref("Array")}} オブジェクトには以下のようなメソッドがあります。

+ +

{{jsxref("Array.concat", "concat()")}} は 2 つの配列を結合し、新しい配列を返します。

+ +
let myArray = new Array('1', '2', '3')
+myArray = myArray.concat('a', 'b', 'c')
+// myArray は ["1", "2", "3", "a", "b", "c"] になる
+
+ +

{{jsxref("Array.join", "join(delimiter = ',')")}} は配列のすべての要素を文字列に結合します。

+ +
var myArray = new Array('Wind', 'Rain', 'Fire');
+var list = myArray.join(' - '); // list は "Wind - Rain - Fire" になる
+
+ +

{{jsxref("Array.push", "push()")}} は 1 つ以上の要素を配列の最後に追加し、その新しい配列の長さを返します。

+ +
var myArray = new Array('1', '2');
+myArray.push('3'); // myArray は ["1", "2", "3"] になる
+
+ +

{{jsxref("Array.pop", "pop()")}} は配列から最後の要素を取り除き、その要素を返します。

+ +
let myArray = new Array('1', '2', '3')
+let last = myArray.pop()
+// myArray は ["1", "2"] に、last は "3" になる
+
+ +

{{jsxref("Array.shift", "shift()")}} は配列から最初の要素を取り除き、その要素を返します。

+ +
let myArray = new Array('1', '2', '3')
+let first = myArray.shift()
+// myArray は ["2", "3"]に、first は "1" になる
+
+ +

{{jsxref("Array.shift", "unshift()")}} は 1 つ以上の要素を配列の先頭に追加し、その新しい配列の長さを返します。

+ +
let myArray = new Array('1', '2', '3')
+myArray.unshift('4', '5')
+// myArray は ["4", "5", "1", "2", "3"] になる
+
+ +

{{jsxref("Array.slice", "slice(start_index, upto_index)")}} は配列の一部を抽出し、新しい配列を返します。

+ +
let myArray = new Array('a', 'b', 'c', 'd', 'e')
+myArray = myArray.slice(1, 4)  // インデックス 1 から始め、インデックス 3 まですべての要素を
+                               // 展開して、[ "b", "c", "d"] を返す
+
+ +

{{jsxref("Array.splice", "splice(index, count_to_remove, addElement1, addElement2, ...)")}} は要素を配列から取り除き、(必要に応じて)置き換えます。

+ +
let myArray = new Array('1', '2', '3', '4', '5')
+myArray.splice(1, 3, 'a', 'b', 'c', 'd')
+// myArray は ["1", "a", "b", "c", "d", "5"] になる
+// このコードは、インデックス 1 の要素("2" のある場所)から始まり、
+// 3 つの要素を削除して、そこに後続のすべての要素を挿入します。
+
+ +

{{jsxref("Array.reverse", "reverse()")}} は配列の中の要素をその場で反転させます。配列の最初の要素が最後に、最後の要素が最初になります。配列への参照を返します。

+ +
let myArray = new Array('1', '2', '3')
+myArray.reverse()
+// 配列要素が入れ替えられ、myArray = ["3", "2", "1"] になる
+
+ +

{{jsxref("Array.sort", "sort()")}} は配列の要素をその場でソートし、その配列の参照を返します。

+ +
let myArray = new Array('Wind', 'Rain', 'Fire')
+myArray.sort()
+// 配列がソートされ、myArray = ["Fire", "Rain", "Wind"] になる
+
+ +

sort() は要素を比較する方法を指定するための、コールバック関数を引数として取ることがあります。

+ +

sort メソッドを始めとしコールバック関数を引数として取る以下のメソッドは {{原語併記("反復メソッド","iterative method")}} と呼ばれ、何らかの形で配列全体を反復処理します。それぞれが任意で thisObject と呼ばれる第二引数を受け取ります。thisObject が与えられた場合、これがコールバック関数の本体内で this キーワードの値になります。与えられなかった場合は、関数が明示的なオブジェクトコンテキストの外で呼び出された場合と同様に、this はアロー関数がコールバックとして使用された場合にはグローバルオブジェクト({{domxref("window")}})を参照し、通常の関数の場合には undefined になります。

+ +

コールバック関数は、配列の要素 2 つを引数として呼び出されます。

+ +

以下の関数は 2 つの値を比較して、3 つの値のうち 1 つを返します。

+ +

つまり、以下の例は文字列の最後の文字で並べ替えをします。

+ +
let sortFn = function(a, b) {
+  if (a[a.length - 1] < b[b.length - 1]) return -1;
+  if (a[a.length - 1] > b[b.length - 1]) return 1;
+  if (a[a.length - 1] == b[b.length - 1]) return 0;
+}
+myArray.sort(sortFn)
+// 配列がソートされ、myArray = ["Wind","Fire","Rain"] になる
+ + + +

{{jsxref("Array.indexOf", "indexOf(searchElement[, fromIndex])")}} は配列から searchElement を検索します。そして、最初に一致した位置のインデックスを返します。

+ +
let a = ['a', 'b', 'a', 'b', 'a']
+console.log(a.indexOf('b'))     // 1 がログに出力される
+
+// 最初から最後への検索を試してみる
+console.log(a.indexOf('b', 2))  // 3 がログに出力される
+console.log(a.indexOf('z'))     // 'z' は見つからないので -1 がログに出力される
+
+ +

{{jsxref("Array.lastIndexOf", "lastIndexOf(searchElement[, fromIndex])")}} は indexOf のように動作しますが、最後の要素から開始して前方に検索します。

+ +
let a = ['a', 'b', 'c', 'd', 'a', 'b']
+console.log(a.lastIndexOf('b'))     // 5 がログに出力される
+
+// 最後から最初への検索を試してみる
+console.log(a.lastIndexOf('b', 4))  // 1 がログに出力される
+console.log(a.lastIndexOf('z'))     // -1 がログに出力される
+
+ +

{{jsxref("Array.forEach", "forEach(callback[, thisObject])")}} はすべての配列アイテムにコールバック関数 callback を実行し、undefined を返します。

+ +
let a = ['a', 'b', 'c']
+a.forEach(function(element) { console.log(element) })
+// 順番にそれぞれのアイテムをログに出力する
+
+ +

{{jsxref("Array.map", "map(callback[, thisObject])")}} はすべての配列アイテムごとにコールバック関数 callback を実行し、戻り値からなる新しい配列を返します。

+ +
let a1 = ['a', 'b', 'c']
+let a2 = a1.map(function(item) { return item.toUpperCase() })
+console.log(a2) // ['A', 'B', 'C'] がログに出力される
+
+ +

{{jsxref("Array.filter", "filter(callback[, thisObject])")}} はコールバック関数 callback が true を返すアイテムからなる新しい配列を返します。

+ +
let a1 = ['a', 10, 'b', 20, 'c', 30]
+let a2 = a1.filter(function(item) { return typeof item === 'number'; })
+console.log(a2)  // [10, 20, 30] がログに出力される
+
+ +

{{jsxref("Array.every", "every(callback[, thisObject])")}} はコールバック関数 callback が配列内のすべてのアイテムで true を返す場合に true を返します。

+ +
function isNumber(value) {
+  return typeof value === 'number'
+}
+let a1 = [1, 2, 3]
+console.log(a1.every(isNumber))  // true がログに出力される
+let a2 = [1, '2', 3]
+console.log(a2.every(isNumber))  // false がログに出力される
+
+ +

{{jsxref("Array.some", "some(callback[, thisObject])")}} はコールバック関数 callback が配列内の少なくとも一つのアイテムで true を返す場合に true を返します。

+ +
function isNumber(value) {
+  return typeof value === 'number'
+}
+let a1 = [1, 2, 3]
+console.log(a1.some(isNumber))  // true がログに出力される
+let a2 = [1, '2', 3]
+console.log(a2.some(isNumber))  // true がログに出力される
+let a3 = ['1', '2', '3']
+console.log(a3.some(isNumber))  // false がログに出力される
+
+ +

{{jsxref("Array.reduce", "reduce(callback[, initialValue])")}} は、配列の各値に対して callback(accumulator, currentValue[, currentIndex[, array]]) を適用し、項目のリストを一つの値に減らすことを目的としています。reduce 関数は、コールバック関数によって返された最終的な値を返します。

+ +

initialValue が指定された場合は、initialValue を第 1 引数の値として、配列の最初の項目の値を第 2 引数の値としてコールバックが呼び出されます。

+ +

initialValue が指定されていない場合、コールバックのの最初の 2 つの引数の値は、配列の最初と 2 番目の要素になります。後続のすべての呼び出しで、最初の引数の値は前の呼び出しでコールバックが返した値になり、2 番目の引数の値は配列の次の値になります。

+ +

コールバックが処理対象の項目のインデックスにアクセスする必要がある場合は、配列全体にアクセスするときに、オプションの引数として利用できます。

+ +
let a = [10, 20, 30]
+let total = a.reduce(function(accumulator, currentValue) { return accumulator + currentValue }, 0)
+console.log(total) // 60 がログに出力される
+
+ +

{{jsxref("Array.reduceRight", "reduceRight(callback[, initialValue])")}} は reduce() のように機能します。しかし最後の要素から適用を開始します。

+ +

reducereduceRight もある意味では配列の反復メソッドです。要素列を単一の値に還元するために、再帰的に 2 つの値を組み合わせるアルゴリズムにこれらのメソッドを使用してください。

+ +

多次元配列

+ +

配列をネストすることができます、つまり配列要素として配列を含めることができることを意味します。JavaScript の配列の特徴を活かして、多次元配列を生成できます。

+ +

以下のコードでは 2次元配列を作成しています。

+ +
let a = new Array(4)
+for (let i = 0; i < 4; i++) {
+  a[i] = new Array(4)
+  for (let j = 0; j < 4; j++) {
+    a[i][j] = '[' + i + ', ' + j + ']'
+  }
+}
+
+ +

この例では、次のテーブル行を持つ配列を作成しています。

+ +
Row 0: [0, 0] [0, 1] [0, 2] [0, 3]
+Row 1: [1, 0] [1, 1] [1, 2] [1, 3]
+Row 2: [2, 0] [2, 1] [2, 2] [2, 3]
+Row 3: [3, 0] [3, 1] [3, 2] [3, 3]
+
+ +

配列を使用して他のプロパティを格納する

+ +

配列は、オブジェクトのように関連する情報を格納するために使用することもできます。

+ +
const arr = [1, 2, 3];
+arr.property = "value";
+console.log(arr.property);  // "value" がログに出力される
+
+ +

配列と正規表現

+ +

配列が正規表現と文字列との間の一致結果である場合、その配列は一致についての情報を提供するプロパティと要素を返します。{{jsxref("Global_Objects/RegExp/exec","RegExp.exec()")}}、{{jsxref("Global_Objects/String/match","String.match()")}}、{{jsxref("Global_Objects/String/split","String.split()")}} による戻り値がこうした配列となります。正規表現とともに配列を使用する際の情報については、当ガイドの正規表現の章をご覧ください。

+ +

配列用のオブジェクトを利用する

+ +

{{domxref("document.getElementsByTagName()")}} によって返される {{domxref("NodeList")}} や、関数本体内で利用できる {{jsxref("Functions/arguments","arguments")}} オブジェクトのように、表面上は配列のようにふるまう JavaScript オブジェクトがありますが、これらはメソッドすべてを共有してはいません。例えば、arguments オブジェクトには {{jsxref("Global_Objects/Function/length","length")}} 属性がありますが、{{jsxref("Array.forEach", "forEach()")}} メソッドは実装されていません。

+ +

配列状のオブジェクトに対して配列メソッドを直接呼び出すことはできません。

+ +
function printArguments() {
+  arguments.forEach(function(item) {  // TypeError: arguments.forEach is not a function
+    console.log(item);
+  });
+}
+
+ +

これを行うには、{{jsxref("Global_Objects/Function/call","Function.prototype.call()")}} を使って間接的に呼び出します。

+ +
function printArguments() {
+  Array.prototype.forEach.call(arguments, function(item) {
+    console.log(item);
+  });
+}
+
+ +

配列のプロトタイプメソッドは、配列と同様の方法で文字に逐次アクセスできるため、文字列にも使用できます。

+ +
Array.prototype.forEach.call('a string', function(chr) {
+  console.log(chr)
+})
+
+ +

型付き配列

+ +

JavaScript の型付き配列は配列用のオブジェクトで、未加工のバイナリーデータにアクセスする仕組みをもたらします。ご存知のように、{{jsxref("Array")}} オブジェクトは動的に拡大、縮小し、JavaScript におけるいかなる値でも保持することができます。JavaScript エンジンは最適化を行うため、これらの配列は高速に機能します。しかし、オーディオやビデオ操作といった機能が追加され、WebSocket を使い未加工のデータにアクセスするなど、Web アプリケーションはさらにパワフルなものとなってきました、そのため JavaScript コードが型付き配列内の未加工バイナリーデータを手早く簡単に操作できれば有益である場合がよくある、ということが明らかになってきました。

+ +

バッファとビュー : 型付き配列のアーキテクチャ

+ +

最大の柔軟性と効率性を達成するため、JavaScript 型付き配列の実装をバッファビューに分離しました。バッファ({{jsxref("ArrayBuffer")}} オブジェクトによる実装)はデータのかたまりを表すオブジェクトです。語るほどのフォーマットはなく、データの中身にアクセスするためのメカニズムを提供しません。バッファに含まれるメモリーにアクセスするには、ビューを使用する必要があります。ビューはデータを実際の型付き配列に変換するコンテキスト — つまり、データ型、開始位置のオフセット、要素数 — を提供します。

+ +

Typed arrays in an ArrayBuffer

+ +

ArrayBuffer

+ +

{{jsxref("ArrayBuffer")}} は汎用的な固定長のバイナリーデータバッファを表すために使用されるデータ型です。ArrayBuffer の内容は直接操作できません。かわりに、型付き配列ビューか特定のフォーマットでバッファを表す {{jsxref("DataView")}} を生成し、それらをバッファの内容の読み書きに使用します。

+ +

型付き配列ビュー

+ +

型付き配列ビューは自己記述的な名前を持っていて、そのすべてが Int8, Uint32, Float64 などといったよく見られる数値型用のビューを提供しています。Uint8ClampedArray という 1 つ特別な型付き配列ビューがあります。これは、0〜255 の範囲に値を固定します。これは、例えば、Canvas のデータ処理に便利です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
値の範囲サイズ (バイト数)説明Web IDL 型同等の C 型
{{jsxref("Int8Array")}}-128 から 12718 ビット 2 の補数方式の符号付き整数値byteint8_t
{{jsxref("Uint8Array")}}0 から 25518 ビット 符号なし整数値octetuint8_t
{{jsxref("Uint8ClampedArray")}}0 から 25518 ビット 符号なし整数値 (切り詰め)octetuint8_t
{{jsxref("Int16Array")}}-32768 から 32767216 ビット 2 の補数方式の符号付き整数値shortint16_t
{{jsxref("Uint16Array")}}0 から 65535216 ビット 符号なし整数値unsigned shortuint16_t
{{jsxref("Int32Array")}}-2147483648 から 2147483647432 ビット 2 の補数方式の符号付き整数値longint32_t
{{jsxref("Uint32Array")}}0 から 4294967295432 ビット 符号なし整数値unsigned longuint32_t
{{jsxref("Float32Array")}}1.2×10-38 から 3.4×1038432 ビット IEEE 浮動小数点数 (7 桁の有効数字 例:1.1234567)unrestricted floatfloat
{{jsxref("Float64Array")}}5.0×10-324 から 1.8×10308864 ビット IEEE 浮動小数点数 (16 桁の有効数字 例:1.123...15)unrestricted doubledouble
{{jsxref("BigInt64Array")}}-263 から 263-1864 ビット 2 の補数方式の符号付き整数値bigintint64_t (signed long long)
{{jsxref("BigUint64Array")}}0 から 264-1864 ビット 符号なし整数値bigintuint64_t (unsigned long long)
+ +

詳細については、JavaScript 型付き配列と様々な {{jsxref("TypedArray")}} オブジェクトに関するリファレンスをご覧ください。

+ +

{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Keyed_Collections")}}

diff --git a/files/ja/web/javascript/guide/introduction/index.html b/files/ja/web/javascript/guide/introduction/index.html new file mode 100644 index 0000000000..189df7a18b --- /dev/null +++ b/files/ja/web/javascript/guide/introduction/index.html @@ -0,0 +1,160 @@ +--- +title: 入門編 +slug: Web/JavaScript/Guide/Introduction +tags: + - Beginner + - Guide + - Introduction + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Introduction +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}}
+ +

本章では JavaScript について紹介し、その基本的なコンセプトについて説明します。

+ +

事前に知っておくべきこと

+ +

このガイドは、以下の基礎的な予備知識を持っていることを前提としています:

+ + + +

JavaScript の情報源

+ +

MDN には以下の JavaScript 関連ドキュメントがあります:

+ + + +

JavaScript を初めて学ぶ方は、学習エリア、および JavaScript ガイドの記事から始めてください。基礎をしっかり学んだら、JavaScript リファレンスを利用して、個別のオブジェクトや文についての詳細を得てください。

+ +

JavaScript とは?

+ +

JavaScript は、クロスプラットフォームで動作するオブジェクト指向のスクリプト言語で、ウェブページをインタラクティブにするために使用されます (例えば、複雑なアニメーション、押下可能なボタン、ポップアップメニューなどを設けることです) 。Node.js のような より高度なサーバー側のバージョンの JavaScript もあり、ファイルをダウンロードするだけでなく (複数のコンピューター間でのリアルタイムコラボレーションなど) 、ウェブサイトに多くの機能を追加することができます。ホスト環境 (例えばウェブブラウザー) 内では、JavaScript とその環境のオブジェクトが結びつけられ、プログラム制御が可能になっています。

+ +

JavaScript には、ArrayDate、そして Math といったオブジェクトからなる基本的なライブラリ、そして演算子、制御構造、文といったプログラミング言語の要素からなる主要な機能が含まれています。JavaScript のコア機能は、追加のオブジェクトを補うことで、様々な目的に拡張することができます。例えば以下のようなものです:

+ + + +

これはつまり、ブラウザー内で JavaScript がウェブページ (DOM) の見た目を変更できるということです。同様に、サーバー上の Node.js の JavaScript は、ブラウザー内に記述されたコードからのカスタム要求に応答できます。

+ +

JavaScript と Java

+ +

JavaScript と Java はいくつかの点では似ていますが、その他の点では全くの別物です。JavaScript 言語は Java と共通点がありますが、Java のような静的型付けと強い型検査を持っていません。LiveScript から JavaScript へ改名する理由ともなった、Java が持つ多くの式構文、命名規則と基本的な制御フローを JavaScript は踏襲しています。

+ +

宣言によって作られたクラスから構成される Java のコンパイル時システムとは対照的に、JavaScript は、数値や真偽値、文字列を表す少数のデータ型をベースにしたランタイムシステムをサポートしています。JavaScript は、より一般的であるクラスベースのオブジェクトモデルの代わりに、プロトタイプベースのオブジェクトモデルを持っています。プロトタイプベースモデルは動的な継承をもたらします、それはつまり、様々なオブジェクトから継承できるということです。また JavaScript は、特殊な宣言型を必要としない関数をサポートしています。関数はオブジェクトのプロパティに設定することができ、弱い型付けのメソッドとして実行することができます。

+ +

JavaScript は Java に比べて非常に自由な形式を持つ言語です。変数、クラス、メソッドをあまねく宣言する必要はありません。メソッドが public か private か、あるいは protected かどうかを気に掛けることも、インターフェイスを実装する必要もありません。変数、引数、そして型を返す関数は厳密に型付けされていません。

+ +

Java は高速実行と型安全のために設計されたクラスベースのプログラミング言語です。型安全というのは、例えば Java の整数値はオブジェクトの参照値として型変換することはできず {{訳注("Java のデータ型は、数値や文字列などのデータのみを表すプリミティブ型とクラス定義されたオブジェクト型 (参照型とも呼ばれる) の 2 つに分かれており、プリミティブ型のデータをオブジェクトから参照する場合はラッパークラスを使い、そのデータを適切なオブジェクト型に明示的に変換する必要がある")}}、またメモリー環境を破壊しようとする Java バイトコードからはプライベートメモリーにアクセスできないようになっているということです。Java のクラス継承と強い型付けは一般的に密結合されたオブジェクト階層を必要とします。こうした前提条件によって Java プログラミングは JavaScript プログラミングに比べ複雑なものとなります。

+ +

それとは対照的に、JavaScript は HyperTalk や dBASE といった一連の小規模で動的型付けを持つ言語の精神を受け継いでいます。これらのスクリプト言語が持っている、より簡素な構文、専門化されたビルトイン関数、そして最低限の条件のみを必要とするオブジェクト作成のおかげで、より広い人々にプログラミングという道具をもたらしてくれます。

+ + + + + + + + + + + + + + + + + + + + + + + +
JavaScript と Java との比較
JavaScriptJava
オブジェクト指向言語。オブジェクトのデータ型に区別はない。継承はプロトタイプベースの機構を通して行われ、プロパティとメソッドはどんなオブジェクトにも動的に追加できる。クラスベース言語。オブジェクトはクラスとそのクラス階層によって継承されたインスタンスとに分かれている。クラスとインスタンスは動的にプロパティやメソッドを追加することができない。
変数のデータ型は宣言が不要(動的型付け、弱い型付け)。変数のデータ型は宣言が必須(静的型付け、強い型付け)。
ハードディスクには自動的に書き込みできない。ハードディスクには自動的に書き込みできる。
+ +

JavaScript と Java との違いについてのさらに詳しい情報は、オブジェクトモデルの詳細の章をご覧ください。

+ +

JavaScript と ECMAScript 仕様

+ +

JavaScript は国際的なプログラミング言語を提供できるように Ecma International によって標準化されています (ECMA は、以前は European Computer Manufacturers Association の頭文字をとったものでした)。この標準化された JavaScript のバージョンは ECMAScript と呼ばれ、この標準をサポートするアプリケーションはすべて同じ動作になります。企業は、JavaScript の実装開発にこのオープンな標準言語を利用できます。ECMAScript 標準は、ECMA-262 仕様に文書化されています。JavaScript バージョンと ECMAScript 標準化の各版との違いについて知りたい場合は JavaScript の新機能をご覧ください。

+ +

ECMA-262 標準は、ISO(International Organization for Standardization、国際標準化機構)により ISO-16262 としても承認されています。また仕様書は、Ecma International のウェブサイトでも確認できます。ECMAScript 仕様には、World Wide Web Consortium (W3C) によって標準化されているドキュメントオブジェクトモデル (DOM) が記載されていません。DOM はスクリプトから利用できる HTML ドキュメントのオブジェクトを定義しています。JavaScript でプログラミングする際に使われる様々な技術のさらに詳しい情報は、JavaScript 技術概説の記事を参考にしてください。

+ +

JavaScript ドキュメント vs ECMAScript 仕様書

+ +

ECMAScript 仕様は ECMAScript の実装要件の集合体です。これは ECMAScript 実装やブラウザー描画エンジン (Firefox の SpiderMonkey、あるいは Chrome の V8 など) に対し、標準に準拠した言語機能を実装したい場合には便利です。

+ +

ECMAScript の文書はスクリプトプログラマを支援するためのものではありません。スクリプトの記述についての情報を知りたければ JavaScript のドキュメントを使いましょう。

+ +

ECMAScript 仕様書は、JavaScript プログラマにあまり馴染みのない専門用語と文法で書かれています。この言語を解説したものと ECMAScript とは異なるところがあるかもしれませんが、この言語自体は同じものです。JavaScript は、ECMAScript 仕様書で描かれた機能をすべてサポートしています。

+ +

JavaScript のドキュメントは、JavaScript プログラマに適した形で言語の特徴について記述しています。

+ +

JavaScript を始めよう

+ +

JavaScript を始めるのは簡単です。必要なものは、最新のウェブブラウザーだけです。このガイドでは最新の Firefox でのみ利用できる JavaScript の機能をいくつか使用するので、最新の Firefox を使用することをお勧めします。

+ +

Firefox に組み込まれているウェブコンソールツールは、JavaScript を試すのに役立ちます。シングルライン入力モードとマルチライン入力モードの 2 つのモードで使用できます。

+ +

ウェブコンソールでの単一行入力

+ +

ウェブコンソールには、現在読み込まれているウェブページの情報が表示されるほか、現在のページで JavaScript 式を実行するために使用できる JavaScript インタープリターも含まれています。

+ +

ウェブコンソールを開くには(Windows および Linux では Ctrl+Shift+I、Mac では Cmd-Option-K)、Firefox のツールメニューを開き、ウェブ開発 ▶ ウェブコンソールを選択します。

+ +

ブラウザーウィンドウの下部にウェブコンソールが表示されます。コンソールの下部に沿って、JavaScript を入力するための入力行があり、出力は上のパネルに表示されます。

+ +

+ +

コンソールは eval と全く同じように動作し、最後に入力された式が返されます。これはコンソールに何かが入力されるたびに、console.log で囲まれた eval で評価されていると想像できます。

+ +
function greetMe(yourName) {
+  alert('Hello ' + yourName);
+}
+console.log(eval('3 + 5'));
+
+ +

ウェブコンソールでの複数行入力

+ +

ウェブコンソールの単一行入力モードは、JavaScript の式を素早くテストするのには最適ですが、複数行を実行するには向いていません。より複雑な JavaScript の場合は、複数行の入力モードを使用できます。

+ +

Hello world

+ +

JavaScript を書き始めるあたり、ウェブコンソールを複数行モードで開いて、初めての JavaScript コード "Hello world" を書いてみましょう。

+ +
(function(){
+  "use strict";
+  /* コードの開始 */
+  function greetMe(yourName) {
+    alert('Hello ' + yourName);
+  }
+
+  greetMe('World');
+  /* コードの終了 */
+})();
+ +

Cmd+Enter または Ctrl+Enter を押して(または実行ボタンをクリック)、結果を見てみましょう!

+ +

このガイドの以降のページでは、より複雑なアプリケーションを作成できるように、JavaScript の構文と言語の特徴を紹介します。

+ +

ですが、しばらくの間、常にあなたのコードの先頭に (function(){"use strict"; を、コードの最後に })(); を記述することを忘れないでください。あとでこれらの意味を学びますが、今のところは次のように捉えておいてください。

+ +
    +
  1. パフォーマンスを大幅に向上させる。
  2. +
  3. 初心者をつまづかせる、JavaScript の愚かなセマンティクスを避ける。
  4. +
  5. コンソールで実行されたコードスニペットが相互に影響することを防止する。(たとえば、あるコンソールの実行で作成されたものを別のコンソールの実行に使用するなど)
  6. +
+ +

{{PreviousNext("Web/JavaScript/Guide", "Web/JavaScript/Guide/Grammar_and_types")}}

diff --git a/files/ja/web/javascript/guide/iterators_and_generators/index.html b/files/ja/web/javascript/guide/iterators_and_generators/index.html new file mode 100644 index 0000000000..685898d31f --- /dev/null +++ b/files/ja/web/javascript/guide/iterators_and_generators/index.html @@ -0,0 +1,242 @@ +--- +title: イテレーターとジェネレーター +slug: Web/JavaScript/Guide/Iterators_and_Generators +tags: + - Guide + - Intermediate + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Iterators_and_Generators +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Meta_programming")}}
+ +
+

コレクション内の各アイテムに対する処理は非常に一般的な操作です。JavaScript では簡単な {{jsxref("Statements/for","for")}} ループから {{jsxref("Global_Objects/Array/map","map()")}}、{{jsxref("Global_Objects/Array/filter","filter()")}} にいたるまで、コレクションに対する反復処理の複数の方法を提供します。

+ +

イテレーターとジェネレーターは、コア言語の内部に反復処理が直接的に取り入れられており、{{jsxref("Statements/for...of","for...of")}} ループの動作を簡単にカスタマイズできる仕組みをもたらします。

+
+ +

詳細についてはこちらもご覧ください:

+ + + +

イテレーター

+ +

JavaScript では、イテレーターはシーケンスおよび潜在的には終了時の戻り値を定義するオブジェクトです。

+ +

より具体的に言うと、イテレーターは、次の 2 つのプロパティを持つオブジェクトを返す next() メソッドを持つことによってイテレータープロトコルを実装するオブジェクトです。

+ +
+
value
+
反復シーケンスの次の値
+
done
+
シーケンスの最後の値が既に消費されている場合に true となります。done と並んで value が存在する場合、それがイテレーターの戻り値となります。
+
+ +

イテレーターオブジェクトが作成されると、next() を繰り返し呼び出すことによって、明示的に反復することができます。イテレーターを反復することを、イテレーターを消費すると言います。一般的に 1 回しか実行できないためです。終了値が返された後、さらに next() を呼び出しても、単に {done: true} を返し続けます。

+ +

Javascript で最も一般的なイテレーターは配列イテレーターで、配列の各値を順番に返します。

+ +

すべてのイテレーターを配列として表現できるとは想像するのは容易ですが、これは真実ではありません。配列は完全に割り当てなければなりませんが、イテレーターは必要なだけで消費されるため、0 から Infinity までの整数の範囲など、無限のサイズのシーケンスを表現できます。

+ +

ここでは、それを行うことができる例を示します。start (包括) から end (排他) までの一連の整数を定義する単純な範囲のイテレーターの作成を可能にします。最終的な戻り値は、作成したシーケンスのサイズあり、変数 iterationCount で追跡されます。

+ +
function makeRangeIterator(start = 0, end = Infinity, step = 1) {
+    let nextIndex = start;
+    let iterationCount = 0;
+
+    const rangeIterator = {
+       next: function() {
+           let result;
+           if (nextIndex < end) {
+               result = { value: nextIndex, done: false }
+               nextIndex += step;
+               iterationCount++;
+               return result;
+           }
+           return { value: iterationCount, done: true }
+       }
+    };
+    return rangeIterator;
+}
+
+ +

このイテレーターを使えば、次のようになります:

+ +
const it = makeRangeIterator(1, 10, 2);
+
+let result = it.next();
+while (!result.done) {
+ console.log(result.value); // 1 3 5 7 9
+ result = it.next();
+}
+
+console.log("Iterated over sequence of size: ", result.value); // [5 numbers returned, that took interval in between: 0 to 10]
+
+ +
+

メモ: 特定のオブジェクトがイテレーターであるかどうかは考えても知ることはできません。それが必要な場合は、反復可能オブジェクトを使用してください。

+
+ +

ジェネレーター関数

+ +

カスタムイテレーターは便利なツールですが、その作成には内部状態を明示的に維持する必要があるため、慎重なプログラミングが必要です。ジェネレーター関数は強力な代替手段を提供します。実行が連続していない単一の関数を記述することによって反復アルゴリズムを定義できます。ジェネレーター関数は、{{jsxref("Statements/function*","function*")}} 構文を使用して記述されます。

+ +

最初に呼び出されると、ジェネレーター関数はコードを実行せず、ジェネレーターと呼ばれるある種のイテレーターを返します。ジェネレーターの next メソッドを呼び出すことによって値が消費されると、ジェネレーター関数は yield キーワードを検出するまで実行します。

+ +

この関数は、必要な回数だけ呼び出すことができ、毎回新しいジェネレーターを返しますが、各ジェネレーターは 1 回のみ反復することができます。

+ +

上の例に適用してみましょう。このコードの動作は同じですが、実装は書くのも読むのもはるかに容易になります。

+ +
function* makeRangeIterator(start = 0, end = 100, step = 1) {
+    let iterationCount = 0;
+    for (let i = start; i < end; i += step) {
+        iterationCount++;
+        yield i;
+    }
+    return iterationCount;
+}
+ +

反復可能オブジェクト

+ +

オブジェクトは、{{jsxref("Statements/for...of", "for...of")}} 構文でループされる値など反復動作を定義する場合、反復可能オブジェクトです。{{jsxref("Array")}} や {{jsxref("Map")}} のような組み込み型の中にはデフォルトの反復動作を持つものがありますが、他の型 ({{jsxref("Object")}} など) は持っていません。

+ +

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

+ +

反復可能オブジェクトは 1 回だけでも 2 回以上でも反復することができます。どちらが当てはまるかは、プログラマに任されています。

+ +

一度しか反復することができない反復可能オブジェクト (例えば、ジェネレーター) は、通常 @@iterator メソッドから this を返します。何度も繰り返し可能なものは、@@iterator の各呼び出しで新しいイテレーターを返す必要があります。

+ +
function* makeIterator() {
+    yield 1;
+    yield 2;
+}
+
+const it = makeIterator();
+
+for (const itItem of it) {
+    console.log(itItem);
+}
+
+console.log(it[Symbol.iterator]() === it) // true;
+
+// This example show us generator(iterator) is iterable object,
+// which has the @@iterator method return the it (itself),
+// and consequently, the it object can iterate only _once_.
+
+
+// If we change it's @@iterator method to a function/generator
+// which returns a new iterator/generator object, (it)
+// can iterate many times
+
+it[Symbol.iterator] = function* () {
+  yield 2;
+  yield 1;
+};
+
+ +

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

+ +

以下のようにして反復可能オブジェクトを自作することができます:

+ +
var myIterable = {
+    *[Symbol.iterator]() {
+        yield 1;
+        yield 2;
+        yield 3;
+    }
+}
+
+for (let value of myIterable) {
+    console.log(value);
+}
+// 1
+// 2
+// 3
+
+or
+
+[...myIterable]; // [1, 2, 3]
+
+ +

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

+ +

{{jsxref("String")}}、{{jsxref("Array")}}、{{jsxref("TypedArray")}}、{{jsxref("Map")}}、{{jsxref("Set")}} はすべて組み込み反復可能オブジェクトです。これらのオブジェクトはすべて、そのプロトタイプオブジェクトに {{jsxref("Symbol.iterator")}} メソッドを備えているためです。

+ +

反復可能オブジェクトが必要な構文

+ +

{{jsxref("Statements/for...of","for-of")}} ループ、{{jsxref("Operators/yield*","yield*")}} などの文や式は、反復可能オブジェクトを必要とします。

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

高度なジェネレーター

+ +

ジェネレーターは要求に応じて yield 文により生成される値を計算しており、多くの計算が必要な一連のデータを効率的に表現したり、前出のとおり無限のシーケンスを表現したりすることを可能にします。

+ +

ジェネレーターの内部状態を変更するのための値を {{jsxref("Global_Objects/Generator/next","next()")}} メソッドで受け入れることもできます。next() に渡された値は yield が受け取ります。最初 next() の呼び出しに値を渡しても常に無視されることに注意してください。

+ +
+

メモ: next()最初の呼び出しに渡された値は常に無視されます。

+
+ +

以下のフィボナッチ数列ジェネレーターでは数列を再起動するのに next(x) を使っています:

+ +
function* fibonacci() {
+  let current = 0;
+  let next = 1;
+  while (true) {
+    let reset = yield current;
+    [current, next] = [next, next + current];
+    if (reset) {
+        current = 0;
+        next = 1;
+    }
+  }
+}
+
+const sequence = fibonacci();
+console.log(sequence.next().value);     // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+console.log(sequence.next().value);     // 3
+console.log(sequence.next().value);     // 5
+console.log(sequence.next().value);     // 8
+console.log(sequence.next(true).value); // 0
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 1
+console.log(sequence.next().value);     // 2
+ +

ジェネレーターの {{jsxref("Global_Objects/Generator/throw","throw()")}} メソッドを呼び出して発生すべき例外値を渡すことで、ジェネレーターに例外を強制的に発生させることができます。これにより、まるで停止中の yieldthrow value 文に替わったかのように、ジェネレーターが停止した際の状況に応じて例外が発生します。

+ +

例外がジェネレーター内部で捕捉されない場合は、throw() を通してその例外が呼び出し元へと伝播し、その後 next() を呼び出した結果の done プロパティは true となります。

+ +

またジェネレーターは、与えられた値を返してジェネレーター自身の処理を終了させる {{jsxref("Global_Objects/Generator/return","return(value)")}} メソッドを持っています。

+ +

{{PreviousNext("Web/JavaScript/Guide/Using_promises", "Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/ja/web/javascript/guide/keyed_collections/index.html b/files/ja/web/javascript/guide/keyed_collections/index.html new file mode 100644 index 0000000000..fbc979ab2b --- /dev/null +++ b/files/ja/web/javascript/guide/keyed_collections/index.html @@ -0,0 +1,161 @@ +--- +title: キー付きコレクション +slug: Web/JavaScript/Guide/Keyed_collections +tags: + - Collections + - Guide + - JavaScript + - Map + - 'l10n:priority' + - set +translation_of: Web/JavaScript/Guide/Keyed_collections +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}
+ +

本章では、キーによって順序付けされたデータのコレクションを紹介します。Map および Set オブジェクトは挿入順に反復処理を行える要素を保持します。

+ +

Map

+ +

Map オブジェクト

+ +

ECMAScript 2015 で値と値とをマッピングする新しいデータ構造が導入されました。{{jsxref("Map")}} オブジェクトはシンプルなキー / バリューマップで、挿入順に要素を反復処理することができます。

+ +

次のコードでは Map を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、{{jsxref("Map")}} リファレンスページをご覧ください。{{jsxref("Statements/for...of","for...of")}} ループを使って、各反復処理において [key, value] からなる配列を返しています。

+ +
let sayings = new Map();
+sayings.set('dog', 'woof');
+sayings.set('cat', 'meow');
+sayings.set('elephant', 'toot');
+sayings.size; // 3
+sayings.get('dog'); // woof
+sayings.get('fox'); // undefined
+sayings.has('bird'); // false
+sayings.delete('dog');
+sayings.has('dog'); // false
+
+for (let [key, value] of sayings) {
+  console.log(key + ' goes ' + value);
+}
+// "cat goes meow"
+// "elephant goes toot"
+
+sayings.clear();
+sayings.size; // 0
+
+ +

ObjectMap との比較

+ +

伝統的に、{{jsxref("Object", "objects", "", "1")}} は文字列を値にマップするのに使われてきました。オブジェクトを使うことで、キーを値に設定し、その値を取得し、キーを削除し、キーに対応する何かが格納されているかどうかを検出することができます、しかしながら、Map の方が少し便利です。

+ + + +

MapObject のどちらを使用すべきかを決めるには下記の 3 つのヒントが役立つでしょう :

+ + + +

WeakMap オブジェクト

+ +

{{jsxref("WeakMap")}} オブジェクトは、キーはオブジェクトのみ値は任意の値にできるキー / バリューのペアからなるコレクションです。キーによるオブジェクト参照は弱く保持され、そのオブジェクトへの参照が他に存在しないときはガベージコレクション (GC) の対象になります。WeakMap API は Map API と同じです。

+ +

Map オブジェクトとの違いの1つは、WeakMap のキーは列挙可能ではないことです(すなわち、キーのリストを取得するメソッドがありません)。もしも列挙可能であれば、リストは非決定性をもたらす、ガベージコレクションの状態に依存することになってしまいます。

+ +

詳細やサンプルコードについては、{{jsxref("WeakMap")}} リファレンスページの「なぜ WeakMap なのか?」もご覧ください。

+ +

WeakMap オブジェクトのよくある使用方法のひとつとして、オブジェクトに対するプライベートデータの格納、あるいは実装の細部の隠蔽があります。次の例は Nick Fitzgerald 氏のブログ投稿、"Hiding Implementation Details with ECMAScript 6 WeakMaps"(ECMAScript 6 WeakMaps を使って実装の詳細を隠蔽する)です。プライベートなデータとメソッドはオブジェクトの内部に属していて、プライベートな WeakMap オブジェクトに格納されています。インスタンスから露出する全てとプロトタイプは公開されています、他の全てのものは外部よりアクセスできません。privates はモジュールから export されていません。

+ +
const privates = new WeakMap();
+
+function Public() {
+  const me = {
+    // ここにプライベートデータが置かれる
+  };
+  privates.set(this, me);
+}
+
+Public.prototype.method = function () {
+  const me = privates.get(this);
+  // `me` にプライベートデータを詰め込む…
+};
+
+module.exports = Public;
+ +

Set

+ +

Set オブジェクト

+ +

{{jsxref("Set")}} オブジェクトは値によって構成されるコレクションです。挿入順に要素を反復処理することができます。Set の 1 つの値は 1 回だけ出現します; Set のコレクションでは値は一意です。

+ +

次のコードでは Set を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、{{jsxref("Set")}} リファレンスページをご覧ください。

+ +
let mySet = new Set();
+mySet.add(1);
+mySet.add('some text');
+mySet.add('foo');
+
+mySet.has(1); // true
+mySet.delete('foo');
+mySet.size; // 2
+
+for (let item of mySet) console.log(item);
+// 1
+// "some text"
+
+ +

ArraySet 間の変換

+ +

{{jsxref("Array.from")}} または スプレッド構文 を使用して Set から {{jsxref("Array")}} を生成できます。また、Set コンストラクタを使って Array から Set へと逆変換することができます。

+ +
+

注: Set オブジェクトは一意の値を格納することにくれぐれも注意してください、重複した要素は Array から変換するときに削除されます。

+
+ +
Array.from(mySet);
+[...mySet2];
+
+mySet2 = new Set([1, 2, 3, 4]);
+
+ +

ArraySet との比較

+ +

伝統的に、要素の集合は多くの状況において JavaScript の配列に格納されてきました。しかし、新しい Set オブジェクトにはいくつかの利点があります :

+ + + +

WeakSet オブジェクト

+ +

{{jsxref("WeakSet")}} オブジェクトは、オブジェクトのコレクションです。WeakSet 内の 1 つのオブジェクトは 1 回だけ出現します; WeakSet コレクション内では値は一意で、オブジェクトは列挙可能ではありません。

+ +

{{jsxref("Set")}} オブジェクトとの主な違いは下記の通りです :

+ + + +

WeakSet オブジェクトの使用例は限定的です。メモリーリークが発生しないため、例えば、DOM 要素をキーとして使用し、監視するためにそれらにマーキングすることが安全に行なえます。

+ +

MapSet におけるキーと値の等値性

+ +

Map オブジェクトのキーの等値性と Set オブジェクトの値の等値性は両方とも、「same-value-zero アルゴリズム」に基づいています:

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}

diff --git a/files/ja/web/javascript/guide/liveconnect_overview/index.html b/files/ja/web/javascript/guide/liveconnect_overview/index.html new file mode 100644 index 0000000000..4deeca4ad2 --- /dev/null +++ b/files/ja/web/javascript/guide/liveconnect_overview/index.html @@ -0,0 +1,799 @@ +--- +title: LiveConnect の概要 +slug: Web/JavaScript/Guide/LiveConnect_Overview +tags: + - Java + - JavaScript + - LiveConnect +translation_of: Archive/Web/LiveConnect/LiveConnect_Overview +--- +

この章では、Java のコードと JavaScript のコードが相互通信を可能にする技術である LiveConnect の使用方法を解説します。この章の読者は、Java プログラミングの経験があるものとします。

+ +

ラッパの使用

+ +

JavaScript において、ラッパとは元の言語のオブジェクトをくるんだ、ターゲットとする言語のデータ型のオブジェクトです。JavaScript でプログラミングをするときは、ラッパオブジェクトを用いることで Java のメソッドやフィールドにアクセスすることができます。つまり、ラッパのメソッドを呼び出したりプロパティにアクセスすることで、Java のオブジェクトにおいて呼び出すことになります。Java 側では JavaScript のオブジェクトがクラス netscape.javascript.JSObject のインスタンスでラップされ、Java に渡されます。

+ +

JavaScript のオブジェクトが Java に送られる際、ランタイムエンジンは JSObject 型の Java ラッパを生成します。一方 JSObject が Java から JavaScript に送られるときは、ランタイムエンジンはそのラップを解き、元の JavaScript オブジェクトの種類に戻します。JSObject クラスには、JavaScript のメソッドを呼び出したり JavaScript のプロパティを調べるためのインタフェースが備わっています。

+ +

JavaScript から Java への通信

+ +

Java のパッケージやクラスを参照したり、Java のオブジェクトや配列を扱ったりするときは、特別な LiveConnect オブジェクトを使用します。JavaScript から Java へのアクセスはすべて、これらのオブジェクトを用いて行います。それらのオブジェクトについて、以下の表で簡単にまとめます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
表 9.1 LiveConnect オブジェクト
オブジェクト説明
JavaArrayラップされた Java の配列です。JavaScript コード内からアクセスされます。
JavaClassJava のクラスへの JavaScript からの参照です。
JavaObjectラップされた Java のオブジェクトです。JavaScript コード内からアクセスされます。
JavaPackageJava のパッケージへの JavaScript からの参照です。
+ +

注意: Java は強く型付けされた言語であり、JavaScript は弱く型付けされた言語であるため、LiveConnect を使用する際はもう一方の言語のために JavaScript ランタイムエンジンが引数の値を適当なデータ型に変換します。詳細はデータ型の変換をご覧ください。

+ +

かなり直感的に Java とやりとりできることから、ある意味で LiveConnect オブジェクトの存在は透過的です。例えば、次のように Java の String オブジェクトを作成し、new 演算子を Java のコンストラクタとともに用いて、そのオブジェクトを JavaScript の変数 myString に代入することができます:

+ +
var myString = new java.lang.String("Hello world");
+
+ +

この例では、変数 myStringJavaObject になります。これは、Java の String オブジェクトのインスタンスを保持しているためです。JavaObject であるので、myStringjava.lang.String およびそのスーパークラスである java.lang.Object のパブリックなインスタンスメソッドにアクセスできます。これらの Java のメソッドは JavaScript から、JavaObject のメソッドとして使用できます:

+ +
myString.length(); // 11 を返す
+
+ +

JavaClass オブジェクトの静的メンバは直接呼び出すことができます。

+ +
alert(java.lang.Integer.MAX_VALUE); // 2147483647 というアラート
+
+ +

Packages オブジェクト

+ +

Java のクラスが javasun あるいは netscape パッケージのいずれの一部でもない場合は、Packages オブジェクトを用いてそれにアクセスします。例えば Redwood 社が、実装したさまざまな Java のクラスを格納するための、redwood という名前の Java パッケージを使用することを想定します。redwoodHelloWorld クラスのインスタンスを作成するには、次のようにそのクラスのコンストラクタにアクセスします:

+ +
var red = new Packages.redwood.HelloWorld();
+
+ +

デフォルトパッケージのクラス (すなわち、明示的にはパッケージに名前をつけていないクラス) にアクセスすることもできます。例えば、HelloWorld クラスが直接 CLASSPATH に入っており、またパッケージには入っていない場合は、次のようにしてそれにアクセスできます:

+ +
var red = new Packages.HelloWorld();
+
+ +

LiveConnect の javasun および netscape オブジェクトはよく使用される Java のパッケージであるために、短縮記法が備わっています。例えば、次のように使用できます:

+ +
var myString = new java.lang.String("Hello world");
+
+ +

これは次のものを省略したものです:

+ +
var myString = new Packages.java.lang.String("Hello world");
+
+ +

Java の配列の使用

+ +

Java のメソッドが配列を作成し、JavaScript からその配列を参照するときは、JavaArray を使用します。例えば、次のコードは int 型の要素を 10 個持つ JavaArray x を作成します:

+ +
var x = java.lang.reflect.Array.newInstance(java.lang.Integer, 10);
+
+ +

JavaScript の Array オブジェクトのように、JavaArray にはその配列の要素数を返す length プロパティがあります。Array.length とは異なり、JavaArray.length は読み取り専用のプロパティです。これは、Java の配列は作成時に要素総数が固定されるためです。

+ +

パッケージおよびクラスの参照

+ +

JavaScript から Java のパッケージやクラスへの簡単な参照では、JavaPackageJavaClass オブジェクトが作成されます。先の Redwood 社についての例では、例えば Packages.redwood という参照が JavaPackage オブジェクトです。同様に、java.lang.String のような参照は JavaClass オブジェクトです。

+ +

ほとんどの場合は JavaPackageJavaClass オブジェクトについて気にする必要はありません。ただ Java のパッケージを使うだけのことであり、LiveConnect がこれらのオブジェクトを透過的に生成するからです。LiveConnect がクラスの読み込みに失敗する場合があり、そのときは以下のようにして手動で読み込みを行う必要があります:

+ +
var Widgetry = java.lang.Thread.currentThread().getContextClassLoader().loadClass("org.mywidgets.Widgetry");
+
+ +

JavaScript 1.3 以前では JavaClass オブジェクトをパラメータとして Java のメソッドとして渡す際に、自動的には java.lang.Class のインスタンスに変換されません。そのため、java.lang.Class のインスタンスのラッパを作成しなければなりません。次の例では、forName メソッドがラッパオブジェクトである theClass を生成します。そしてそれを newInstance メソッドに渡し、配列を生成します。

+ +
// JavaScript 1.3
+var theClass = java.lang.Class.forName("java.lang.String");
+var theArray = java.lang.reflect.Array.newInstance(theClass, 5);
+
+ +

JavaScript 1.4 以降では次の例のように、JavaClass オブジェクトをメソッドに直接渡すことができます:

+ +
// JavaScript 1.4
+var theArray = java.lang.reflect.Array.newInstance(java.lang.String, 5);
+
+ +

char 型の引数

+ +

JavaScript 1.4 以降では char 型の引数を必要とする Java のメソッドに、1 文字の文字列を渡すことができます。例えば、次のようにして文字列 "H" を Character コンストラクタに渡すことができます:

+ +
var c = new java.lang.Character("H");
+
+ +

JavaScript 1.3 以前では、このようなメソッドにはその文字の Unicode 値に対応する整数値を渡さなければなりません。例えば、次のコードも "H" という文字列を変数 c に代入するものです:

+ +
var c = new java.lang.Character(72);
+
+ +

JavaScript での Java 例外の処理

+ +

Java のコードは実行時に失敗すると、例外を投げます。JavaScript のコードが Java のデータメンバまたはメソッドにアクセスし、失敗すると、Java の例外が JavaScript に渡されます。これは、例外を処理できるようにするためです。JavaScript 1.4 からは try...catch 文でこの例外を受け取ることができます。(Mozilla 固有の LiveConnect コードが Mozilla 内でメンテナンスされていなかったため、この機能は (他の一部機能もあわせて) Gecko 1.9 で壊れています (バグ 391642 をご覧ください)。しかし Java 6 アップデート 11 および 12 での、Mozilla の汎用 (かつクロスブラウザの) NPAPI プラグインコードに依存する構築のサポートにより修復されました。)

+ +

例えば、Java の forName メソッドを使用して Java のクラス名を theClass という変数に代入するとします。forName メソッドに渡す値が Java のクラス名に評価できなければ、そのメソッドは例外を投げます。次のようにして、例外を処理できるように forName 代入文を try ブロック内に置きます:

+ +
function getClass(javaClassName) {
+   try {
+      var theClass = java.lang.Class.forName(javaClassName);
+   } catch (e) {
+      return ("The Java exception is " + e);
+   }
+   return theClass;
+}
+
+ +

この例では、javaClassName が "java.lang.String" のような正当なクラス名に評価されると代入が成功します。javaClassName が "String" のような不正なクラス名に評価されると、getClass 関数が例外を受け取り、次のようなものを返します:

+ +
The Java exception is java.lang.ClassNotFoundException: String
+
+ +

例外の型に基づいて特別な処理をするには instanceof 演算子を使用します:

+ +
try {
+  // ...
+} catch (e) {
+  if (e instanceof java.io.FileNotFound) {
+     // FileNotFound についての処理
+  } else {
+    throw e;
+  }
+}
+
+ +

JavaScript の例外についての詳細情報は例外処理文を参照してください。

+ +

Java から JavaScript への通信

+ +

Java で JavaScript のオブジェクトを使用したい場合は、その Java ファイルに netscape.javascript パッケージをインポートしなければなりません。このパッケージは次のクラスを定義しています:

+ + + +

これらのクラスの詳細は JavaScript リファレンスをご覧ください。

+ +

LiveConnect クラスの場所の特定

+ +

古いバージョンの Netscape ブラウザでは、これらのクラスがブラウザに同梱されていました。JavaScript 1.2 からは、これらのクラスは .jar ファイルに格納されています。それより古いバージョンの JavaScript では、これらのクラスは .zip ファイルに格納されています。例えば Windows NT 向けの Netscape Navigator 4 では、クラスは Navigator のディレクトリ直下の Program\Java\Classes ディレクトリ内の java40.jar ファイルに格納されています。

+ +

より最近では、クラスは Sun の Java ランタイムに同梱されています。はじめはランタイムディストリビューションの "jre/lib" ディレクトリ内の "jaws.jar" ファイルに入っていましたが (JRE 1.3)、その後同じ場所の "plugin.jar" に移っています (JRE 1.4 以降)。

+ +

JDK での LiveConnect クラスの使用

+ +

LiveConnect クラスにアクセスするには、次のどちらかの方法で JDK コンパイラの CLASSPATH に .jar または .zip ファイルを配置します:

+ + + +

Windows NT では、コントロールパネルのシステムアイコンをダブルクリックし、CLASSPATH という名前のユーザ環境変数を作成し、それに次のような値を設定することで環境変数を作成できます:

+ +
C:\Program Files\Java\jre1.4.1\lib\plugin.jar
+
+ +

CLASSPATH についての詳細は Sun の JDK に関する資料をご覧ください。

+ +

注意: Java は強く型付けされた言語であり、JavaScript は弱く型付けされた言語であるため、LiveConnect を使用する際はもう一方の言語のために JavaScript ランタイムエンジンが引数の値を適当なデータ型に変換します。詳細は  をご覧ください。

+ +

LiveConnect クラスの使用

+ +

すべての JavaScript オブジェクトは、Java コード内では netscape.javascript.JSObject のインスタンスとして現れます。Java コード内でメソッドを呼び出すときに、その引数として JavaScriptのオブジェクトを渡すことができます。そうするためには、そのメソッドの対応する仮パラメータを JSObject 型で定義しなければなりません。

+ +

さらに、Java コード内で JavaScript のオブジェクトを使用するたびに、netscape.javascript.JSException 型の例外を処理する try...catch 文の内側で、その JavaScript オブジェクトを呼び出すようにしてください。こうすることで JSException 型の例外として Java で現れる、JavaScript コードの実行におけるエラーを Java コードで処理できるようになります。

+ +

JSObject を用いた JavaScript へのアクセス

+ +

例えば、JavaDog という Java のクラスを使用するとします。次のコードで示すように、JavaDog コンストラクタは JavaScript のオブジェクトである jsDog を引数としてとります。このオブジェクトは JSObject 型として定義されています:

+ +
import netscape.javascript.*;
+
+public class JavaDog{
+    public String dogBreed;
+    public String dogColor;
+    public String dogSex;
+
+    // クラスコンストラクタの定義
+    public JavaDog(JSObject jsDog){
+        // ここで try...catch を使用して JSExceptions を処理できるようにする
+        this.dogBreed = (String)jsDog.getMember("breed");
+        this.dogColor = (String)jsDog.getMember("color");
+        this.dogSex = (String)jsDog.getMember("sex");
+    }
+}
+
+ +

JSObjectgetMember メソッドは、JavaScript のオブジェクトのプロパティにアクセスするために使用するものです。この例では JavaScript のプロパティである jsDog.breed の値を Java のデータメンバである JavaDog.dogBreed に代入するために、getMember を使用しています。

+ +

注意: より現実的な例では try...catch 文の内側で getMember を呼び出し、JSException 型のエラーを処理できるようにします。詳細は、Java での JavaScript の例外処理を参照してください。

+ +

getMember の動作をさらに知るために、JavaScript の Dog オブジェクトを作成し、その定義を見てみます:

+ +
function Dog(breed,color,sex){
+   this.breed = breed;
+   this.color = color;
+   this.sex = sex;
+}
+
+ +

Dog の JavaScript のインスタンスである gabby は、次のようにして作ることができます:

+ +
var gabby = new Dog("lab", "chocolate", "female");
+
+ +

gabby.color を評価すると、それが "chocolate" という値を持っていることがわかります。ここで次のように gabby オブジェクトをコンストラクタに渡し、JavaScript コードで JavaDog のインスタンスを作成することにします:

+ +
var javaDog = new Packages.JavaDog(gabby);
+
+ +

javaDog.dogColor を評価すると、それも "chocolate" という値を持っていることがわかります。これは Java のコンストラクタ内の getMember メソッドが、gabby.color の値を dogColor に代入するからです。

+ +

Java での JavaScript の例外処理

+ +

実行時に Java からの JavaScript コードの呼び出しに失敗すると、例外が投げられます。Java から JavaScript コードを呼び出すときに、try...catch 文でこの例外を受け取ることができます。JavaScript の例外は、netscape.javascript.JSException のインスタンスとして Java コードから扱えます。

+ +

JSException は JavaScript が投げるあらゆる種類の例外に対応する、Java のラッパです。JSObject のインスタンスが JavaScript のオブジェクトのラッパであるのと同じようなものです。Java で JavaScript コードを評価するときは JSException を使用してください。

+ +

Java で JavaScript コードを評価する際、次の状況でランタイムエラーが発生します:

+ + + +

例えば、Java のオブジェクトである jsCode が自身に渡される文字列 eTest を評価するとします。次のようなエラー処理を実行することで、評価が原因で発生するどちらの種類のランタイムエラーにも対応できます:

+ +
import netscape.javascript.JSObject;
+import netscape.javascript.JSException;
+
+public class eTest {
+    public static Object doit(JSObject obj, String jsCode) {
+        try {
+            obj.eval(jsCode);
+        } catch (JSException e) {
+            if (e.getWrappedException() == null)
+                return e;
+            return e.getWrappedException();
+        }
+        return null;
+    }
+}
+
+ +

この例では、渡された文字列 jsCodetry ブロック内のコードが評価しようとします。文字列 "myFunction()" を jsCode の値として渡すとします。myFunction が JavaScript の関数として定義されていない場合、JavaScript インタプリタは jsCode を評価できません。インタプリタはエラーメッセージを生成し、Java のハンドラがそのメッセージを受け取り、doit メソッドは netscape.javascript.JSException のインスタンスを返します。

+ +

しかし、次のように myFunction が JavaScript で定義されているとします:

+ +
function myFunction() {
+   try {
+      if (theCondition == true) {
+         return "Everything's ok";
+      } else {
+         throw "JavaScript error occurred";
+      }
+   } catch (e) {
+      if (canHandle == true) {
+         handleIt();
+      } else {
+         throw e;
+      }
+   }
+}
+
+ +

theCondition が false であれば、関数は例外を投げます。その例外は JavaScript コードで受け取られ、さらに canHandle が true の場合に JavaScript はそれを処理します。canHandle false がならばその例外が再び投げられ、Java のハンドラがそれを受け取り、 doit メソッドが次の Java の文字列を返します:

+ +
JavaScript error occurred
+
+ +

JavaScript の例外についての詳細情報は例外処理文を参照してください。

+ +

後方互換性

+ +

JavaScript 1.3 以前のバージョンでは、JSException クラスには省略可能な文字列引数をとる 3 つの public タイプのコンストラクタがありました。この文字列引数は、詳細なメッセージやその例外に対する他の情報を指定するものです。getWrappedException メソッドは使用できませんでした。

+ +

次のような try...catch 文を使用することで、JavaScript 1.3 以前のバージョンで LiveConnect の例外を処理できます:

+ +
try {
+   global.eval("foo.bar = 999;");
+} catch (Exception e) {
+   if (e instanceof JSException) {
+      jsCodeFailed();
+   } else {
+      otherCodeFailed();
+   }
+}
+
+ +

この例では foo が定義されていないと eval 文が失敗します。try ブロックの eval 文が JSException を投げると、catch ブロックが jsCodeFailed メソッドを実行します。try ブロックがそれ以外のエラーを投げると、otherCodeFailed メソッドが実行されます。

+ +

データ型変換

+ +

Java は強く型付けされた言語であり、JavaScript は弱く型付けされた言語であるため、LiveConnect を使用する際はもう一方の言語のために、JavaScript ランタイムエンジンが引数の値を適切なデータ型に変換します。この変換について以下のセクションで説明します:

+ + + +

JavaScript から Java への変換

+ +

JavaScript から Java のメソッドを呼び出してパラメータを渡す際、渡すパラメータのデータ型は以下のセクションで説明するルールによって変換されます:

+ + + +

netscape.javascript.JSObject メソッドの戻り値は常に java.lang.Object のインスタンスに変換されます。このような戻り値の変換ルールもここで説明します。

+ +

例えば JSObject.eval が JavaScript の数値を返すのであれば、この数値を java.lang.Object のインスタンスに変換するルールは数値に記載されています。

+ +

数値

+ +

Java のメソッドに JavaScript の数値型をパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
double +
    +
  • そのままの値が、丸められたり絶対値や符号が損なわれることなく Java に渡されます。
  • +
  • NaNNaN に変換されます。
  • +
+
java.lang.Double
+ java.lang.Object
java.lang.Double の新しいインスタンスが作成され、そのままの値が、丸められたり絶対値や符号が損なわれることなく Java に渡されます。
float +
    +
  • 値は float 精度に丸められます。
  • +
  • 大きすぎまたは小さすぎて表現できない値は、正の無限大または負の無限大に丸められます。
  • +
  • NaNNaN に変換されます。
  • +
+
byte
+ char
+ int
+ long
+ short
+
    +
  • 値は負の無限大方向に丸められます。
  • +
  • 大きすぎまたは小さすぎて表現できない値は、ランタイムエラーになります。
  • +
  • NaN は変換されずにランタイムエラーになります。
  • +
+
java.lang.String値は文字列に変換されます。例えば: +
    +
  • 237 は "237" になります。
  • +
+
boolean +
    +
  • 0 および NaN は false に変換されます。
  • +
  • その他の値は true に変換されます。
  • +
+
+ +

java.lang.String のインスタンスをパラメータに想定した Java のメソッドに JavaScript の数値をパラメータとして渡すと、その数値は文字列に変換されます。equals() メソッドを使用すると、この変換結果と他の文字列を比較できます。

+ +

真偽値

+ +

Java のメソッドに JavaScript の真偽値型をパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
booleanすべての値は、Java で対応するものに直接変換されます。
java.lang.Boolean
+ java.lang.Object
java.lang.Boolean の新しいインスタンスが作成されます。同一のプリミティブ値に対して 1 つのインスタンスではなく、各パラメータについて新しいインスタンスが作成されます。
java.lang.String値は文字列に変換されます。例えば: +
    +
  • true は "true" になります。
  • +
  • false は "false" になります。
  • +
+
byte
+ char
+ double
+ float
+ int
+ long
+ short
+
    +
  • true は 1 になります。
  • +
  • false は 0 になります。
  • +
+
+ +

java.lang.String のインスタンスをパラメータに想定した Java のメソッドに JavaScript の真偽値をパラメータとして渡すと、その真偽値は文字列に変換されます。== 演算子を使用すると、この変換結果と他の文字列を比較できます。

+ +

文字列値

+ +

Java のメソッドに JavaScript の文字列型をパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
java.lang.String
+ java.lang.Object
JavaScript 1.4: +
    +
  • JavaScript の文字列は、Unicode 値で java.lang.String のインスタンスに変換されます。
  • +
+ +

JavaScript 1.3 以前:

+ +
    +
  • JavaScript の文字列は、ASCII 値で java.lang.String のインスタンスに変換されます。
  • +
+
byte
+ double
+ float
+ int
+ long
+ short
すべての値は、ECMA-262 に記載に従って数値に変換されます。JavaScript の文字列値は ECMA-262 に記載されたルールに従って数値に変換されます。
charJavaScript 1.4: +
    +
  • 1 文字の文字列は、Unicode 文字に変換されます。
  • +
  • 他のすべての値は数値に変換されます。
  • +
+ +

JavaScript 1.3 以前:

+ +
    +
  • すべての値が数値に変換されます。
  • +
+
boolean +
    +
  • 空文字列は false になります。
  • +
  • 他のすべての値は true になります。
  • +
+
+ +

undefined 値

+ +

Java のメソッドに JavaScript の undefined 値をパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
java.lang.String
+ java.lang.Object
値は java.lang.String のインスタンスに変換され、インスタンスの値は文字列 "undefined" になります。
boolean値は false になります。
double
+ float
値は NaN になります。
byte
+ char
+ int
+ long
+ short
値は 0 になります。
+ +

undefined 値の変換は JavaScript 1.3 以降でのみ可能です。それより古いバージョンでは、undefined 値がサポートされていません。

+ +

java.lang.String のインスタンスをパラメータに想定した Java のメソッドに JavaScript の undefined 値をパラメータとして渡すと、その undefined 値は文字列に変換されます。== 演算子を使用すると、この変換結果と他の文字列を比較できます。

+ +

null 値

+ +

Java のメソッドに JavaScript の null 値をパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
あらゆるクラス
+ あらゆるインタフェースの種類
値は null になります。
byte
+ char
+ double
+ float
+ int
+ long
+ short
値は 0 になります。
boolean値は false になります。
+ +

JavaArray および JavaObject オブジェクト

+ +

ほとんどの場合、Java のメソッドに JavaScript の JavaArray または JavaObject オブジェクトをパラメータとして渡すと、Java は単にそのオブジェクトのラップを解きます。そうでない場合は、Java は次の表で示すルールに従ってそのオブジェクトを別のデータ型に変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
ラップが解かれたオブジェクトと代入互換性のある、あらゆるインタフェースまたはクラスオブジェクトのラップが解かれます。
java.lang.Stringオブジェクトのラップが解かれ、ラップが解かれた Java オブジェクトの toString メソッドが呼び出され、その結果が java.lang.String の新しいインスタンスとして返されます。
byte
+ char
+ double
+ float
+ int
+ long
+ short
オブジェクトのラップが解かれ、次の状況のどちらかが起こります: +
    +
  • ラップが解かれた Java のオブジェクトに doubleValue メソッドがあれば、JavaArray または JavaObject はこのメソッドが返す値に変換されます。
  • +
  • ラップが解かれた Java オブジェクトに doubleValue メソッドがなければ、エラーが発生します。
  • +
+
booleanJavaScript 1.3 以降ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります: +
    +
  • オブジェクトが null ならば、false に変換されます。
  • +
  • オブジェクトがそれ以外の値ならば、true に変換されます。
  • +
+ +

JavaScript 1.2 以前ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります:

+ +
    +
  • ラップが解かれたオブジェクトに booleanValue メソッドがあれば、ソースオブジェクトは戻り値のために変換されます。
  • +
  • オブジェクトに booleanValue がなければ、変換に失敗します。
  • +
+
+ +

ラップが解かれたオブジェクトが Java のパラメータ型のインスタンスであれば、インタフェースまたはクラスが、ラップが解かれたオブジェクトと代入互換性があるということです。つまり、次の文は必ず true を返します:

+ +
unwrappedObject instanceof parameterType;
+
+ +

JavaClass オブジェクト

+ +

Java のメソッドに JavaScript の JavaClass オブジェクトをパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
java.lang.Classオブジェクトのラップが解かれます。
netscape.javascript.JSObject
+ java.lang.Object
JavaClass オブジェクトが netscape.javascript.JSObject の新しいインスタンス内にラップされます。
java.lang.Stringオブジェクトのラップが解かれ、ラップが解かれた Java オブジェクトの toString メソッドが呼び出され、その結果が java.lang.String の新しいインスタンスとして返されます。
booleanJavaScript 1.3 以降ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります: +
    +
  • オブジェクトが null ならば、false に変換されます。
  • +
  • オブジェクトがそれ以外の値ならば、true に変換されます。
  • +
+ +

JavaScript 1.2 以前ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります:

+ +
    +
  • ラップが解かれたオブジェクトに booleanValue メソッドがあれば、ソースオブジェクトは戻り値のために変換されます。
  • +
  • オブジェクトに booleanValue がなければ、変換に失敗します。
  • +
+
+ +

その他の JavaScript のオブジェクト

+ +

Java のメソッドに JavaScript のその他のオブジェクトをパラメータとして渡すと、Java は次の表で示すルールに従ってその値を変換します:

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Java のパラメータ型変換ルール
netscape.javascript.JSObject
+ java.lang.Object
オブジェクトは netscape.javascript.JSObject の新しいインスタンス内にラップされます。
java.lang.Stringオブジェクトのラップが解かれ、ラップが解かれたオブジェクトの toString メソッドが呼び出され、その結果が java.lang.String の新しいインスタンスとして返されます。
byte
+ char
+ double
+ float
+ int
+ long
+ short
オブジェクトは、ECMA-262 に記載された ToPrimitive 演算子のロジックを使用して値に変換されます。この演算子で使用される PreferredType ヒントは Number です。
booleanJavaScript 1.3 以降ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります: +
    +
  • オブジェクトが null ならば、false に変換されます。
  • +
  • オブジェクトがそれ以外の値ならば、true に変換されます。
  • +
+ +

JavaScript 1.2 以前ではオブジェクトのラップが解かれ、次の状況のどちらかが起こります:

+ +
    +
  • ラップが解かれたオブジェクトに booleanValue メソッドがあれば、ソースオブジェクトは戻り値のために変換されます。
  • +
  • オブジェクトに booleanValue がなければ、変換に失敗します。
  • +
+
+ +

Java から JavaScript への変換

+ +

Java から JavaScript に渡された値は、次のように変換されます:

+ + + +

java.lang.Double および java.lang.Integer のインスタンスは、JavaScript の数値ではなく JavaScript のオブジェクトに変換されることに注意してください。同様に java.lang.String のインスタンスも、JavaScript の文字列ではなく JavaScript のオブジェクトに変換されます。

+ +

Java の String オブジェクトも、JavaScript のラッパに相当します。JavaScript の文字列を必要とする JavaScript のメソッドを、このラッパを渡して呼び出すとエラーになります。そうではなく、次のようにラッパに空文字列を付加することで、ラッパを JavaScript の文字列に変換してください:

+ +
var JavaString = JavaObj.methodThatReturnsAString();
+var JavaScriptString = JavaString + "";
diff --git a/files/ja/web/javascript/guide/loop_statements/break_statement/index.html b/files/ja/web/javascript/guide/loop_statements/break_statement/index.html new file mode 100644 index 0000000000..35cc94abdf --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/break_statement/index.html @@ -0,0 +1,24 @@ +--- +title: break 文 +slug: Web/JavaScript/Guide/Loop_Statements/break_Statement +--- +

break 文

+

break 文は loop 文や switch 文、label 文から抜け出すために使用します。

+ +

break 文は次のように使用します。

+
    +
  1. break;
  2. +
  3. break label;
  4. +
+

1番目の形式の構文は最も内側のループもしくは switch から抜けます。2番目の形式の構文は指定した label 文から抜けます。

+


+ 次の例は、その値が theValue である要素のインデックスが見つかるまで、配列の要素について繰り返します。

+
for (i = 0; i < a.length; i++) {
+   if (a[i] == theValue)
+      break;
+}
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements/label_Statement", "JavaScript/Guide/Loop_Statements/continue_Statement") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/continue_statement/index.html b/files/ja/web/javascript/guide/loop_statements/continue_statement/index.html new file mode 100644 index 0000000000..f7a5697eeb --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/continue_statement/index.html @@ -0,0 +1,46 @@ +--- +title: continue 文 +slug: Web/JavaScript/Guide/Loop_Statements/continue_Statement +--- +

continue 文

+

continue 文は while 文、do-while 文、for 文、label 文をリスタートさせるために用います。

+ +

continue 文は次のように使用します。

+
    +
  1. continue
  2. +
  3. continue label
  4. +
+

例 1
+ 次の例では、i の値が 3 のときに実行される continue 文を用いた while ループを示します。こうすることで n は順に 1、3、7、12 という値をとります。

+
i = 0;
+n = 0;
+while (i < 5) {
+   i++;
+   if (i == 3)
+      continue;
+   n += i;
+}
+
+

例 2
+ checkiandj というラベルの付いた文の中に checkj というラベルの付いた文があります。continue に出くわすと、プログラムは checkj の現在の反復を終了し、次の反復を始めます。continue に出くわすたびに、条件が false になるまで checkj を繰り返します。false が返されると checkiandj 文の残りを完了し、条件が false を返すまで checkiandj を繰り返します。false が返されると checkiandj に続く文が実行されます。

+

continuecheckiandj というラベルを持っているとプログラムは checkiandj 文の最初から続けます。

+
checkiandj :
+   while (i < 4) {
+      document.write(i + "<br/>");
+      i += 1;
+      checkj :
+         while (j > 4) {
+            document.write(j + "<br/>");
+            j -= 1;
+            if ((j % 2) == 0)
+               continue checkj;
+            document.write(j + " is odd.<br/>");
+         }
+      document.write("i = " + i + "<br/>");
+      document.write("j = " + j + "<br/>");
+   }
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements/break_Statement", "JavaScript/Guide/Object_Manipulation_Statements") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/do...while_statement/index.html b/files/ja/web/javascript/guide/loop_statements/do...while_statement/index.html new file mode 100644 index 0000000000..6e1df1e586 --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/do...while_statement/index.html @@ -0,0 +1,19 @@ +--- +title: do...while 文 +slug: Web/JavaScript/Guide/Loop_Statements/do...while_Statement +--- +

do...while 文

+

do...while 文は指定した条件が false に評価されるまで繰り返します。do...while 文は次のように使用します。

+
do
+   statement
+while (condition);
+
+

statement は条件がチェックされる前に一度実行されます。複数の文を実行するにはブロック文 ({ ... }) を使用して文をグループ化してください。condition が true の場合、その文が再び実行されます。毎回実行された後に条件がチェックされます。条件が false ときは実行が停止され、コントロールが do...while の後に続く文に渡されます。

+


+ 次の例では do ループは最低 1 回は反復され、i が 5 より小さくなくなるまで反復されます。

+
do {
+   i += 1;
+   document.write(i);
+} while (i < 5);
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements/for_Statement", "JavaScript/Guide/Loop_Statements/while_Statement") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/for_statement/index.html b/files/ja/web/javascript/guide/loop_statements/for_statement/index.html new file mode 100644 index 0000000000..b2dccec25b --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/for_statement/index.html @@ -0,0 +1,50 @@ +--- +title: for 文 +slug: Web/JavaScript/Guide/Loop_Statements/for_Statement +--- +

for 文

+

for ループは指定した条件が false に評価されるまで繰り返します。JavaScript の for ループは Java や C の for ループに似ています。for 文は次のように使用します。

+
for ([initialExpression]; [condition]; [incrementExpression])
+   statement
+
+

for ループを実行すると以下のことが起こります。

+
    +
  1. 初期化式 initialExpression があれば実行されます。この式は通常、1 つかそれ以上のループカウンタを初期化しますが、構文的にはある程度複雑な式も指定できます。また、この式は変数を宣言することもできます。
  2. +
  3. condition 式が評価されます。condition の値が true であればループ文が実行されます。condition が false の場合は for ループは終了します。condition 式が完全に省略されている場合、条件は true であると仮定されます。
  4. +
  5. statement が実行されます。複数の式を実行するにはブロック文 ({ ... }) を使用して文をグループ化してください。
  6. +
  7. 更新式 incrementExpression があれば実行されます。そしてコントロールがステップ 2 に戻ります。
  8. +
+


+ 次の関数には、スクローリングリスト(複数選択できる Select オブジェクト)で選択されたオプションの数を数える for 文が含まれています。for 文では変数 i が宣言され、それが 0 に初期化されています。iSelect オブジェクトのオプションの個数より小さいかをチェックし、続く if 文を実行し、ループが 1 回りしたら i を 1 だけ増加させます。

+
<script type="text/javascript">//<![CDATA[
+
+function howMany(selectObject) {
+   var numberSelected = 0;
+   for (var i = 0; i < selectObject.options.length; i++) {
+      if (selectObject.options[i].selected)
+         numberSelected++;
+   }
+   return numberSelected;
+}
+
+//]]></script>
+<form name="selectForm">
+   <p>
+      <strong>Choose some music types, then click the button below:</strong>
+      <br/>
+      <select name="musicTypes" multiple="multiple">
+         <option selected="selected">R&B</option>
+         <option>Jazz</option>
+         <option>Blues</option>
+         <option>New Age</option>
+         <option>Classical</option>
+         <option>Opera</option>
+      </select>
+   </p>
+   <p>
+      <input type="button" value="How many are selected?"
+         onclick="alert ('Number of options selected: ' + howMany(document.selectForm.musicTypes))"/>
+   </p>
+</form>
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements", "JavaScript/Guide/Loop_Statements/do...while_Statement") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/index.html b/files/ja/web/javascript/guide/loop_statements/index.html new file mode 100644 index 0000000000..54ef32d2c9 --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/index.html @@ -0,0 +1,17 @@ +--- +title: ループ文 +slug: Web/JavaScript/Guide/Loop_Statements +--- +

ループ文

+

ループは指定した条件が満たされている限り繰り返し実行されるコマンドのセットです。JavaScript は、label はもちろん、for、do while、while といったループ文をサポートしています(label 自体はループ文ではありませんが、これらの文とともに頻繁に使用されます)。さらに、break および continue 文をループ文の中で使うことができます。

+

さらに for...in 文も文を繰り返し実行しますが、これはオブジェクトの操作に使用します。オブジェクト操作文 をご覧ください。

+

ループ文は以下のとおりです。

+ +

{{ PreviousNext("JavaScript/Guide/Conditional_Statements", "JavaScript/Guide/Loop_Statements/for_Statement") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/label_statement/index.html b/files/ja/web/javascript/guide/loop_statements/label_statement/index.html new file mode 100644 index 0000000000..d0b878455b --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/label_statement/index.html @@ -0,0 +1,19 @@ +--- +title: label 文 +slug: Web/JavaScript/Guide/Loop_Statements/label_Statement +--- +

label 文

+

label を使うと、そのプログラムのどこからでも参照できる、識別子を持った文を作ることができます。例えば、ラベルを使用してあるループに名前を付けると、break 文や continue 文を使用してプログラムがループを脱出するべきかそのまま実行を継続するべきかを示すことができます。

+

label 文は次のように使用します。

+
label :
+   statement
+
+

label の値は予約語でなければどんな JavaScript の識別子でも使用できます。ラベルを用いて名前を付ける statement はどんな文でも結構です。

+


+ この例では markLoop というラベルを用いて while ループに名前を付けています。

+
markLoop:
+while (theMark == true)
+   doSomething();
+}
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements/while_Statement", "JavaScript/Guide/Loop_Statements/break_Statement") }}

diff --git a/files/ja/web/javascript/guide/loop_statements/while_statement/index.html b/files/ja/web/javascript/guide/loop_statements/while_statement/index.html new file mode 100644 index 0000000000..77fd191f75 --- /dev/null +++ b/files/ja/web/javascript/guide/loop_statements/while_statement/index.html @@ -0,0 +1,35 @@ +--- +title: while 文 +slug: Web/JavaScript/Guide/Loop_Statements/while_Statement +--- +

while 文

+

while 文は、指定した条件が true に評価される限り文を実行します。while 文は次のように使用します。

+
while (condition)
+   statement
+
+

条件が false になるとループ内の statement の実行が停止し、ループの後に続く文にコントロールが渡されます。

+

ループの statement を実行する前に条件がテストされます。条件が true を返すと statement が実行され、再び条件がテストされます。条件が false を返すと、実行が停止され、while の後に続く文にコントロールが渡されます。

+

複数の文を実行するにはブロック文 ({ ... }) を用いて文をグループ化してください。

+

例 1
+ 次の while ループでは n が 3 より小さい限り反復されます。

+
n = 0;
+x = 0;
+while (n < 3) {
+   n++;
+   x += n;
+}
+
+

それぞれの反復で、ループは n をインクリメントし、その値を x に加えています。その結果、xn は次の値をとります。

+ +

第 3 段階が完了すると条件 n < 3 が true ではなくなっているため、ループは終了します。

+

例 2
+ 無限ループは避けてください。ループの条件が最終的には false になることを確認してください。そうしないとループが終了しなくなります。次の while ループ内の文は永久に実行されます。条件が決して false にならないためです。

+
while (true) {
+   alert("Hello, world");
+}
+
+

{{ PreviousNext("JavaScript/Guide/Loop_Statements/do...while_Statement", "JavaScript/Guide/Loop_Statements/label_Statement") }}

diff --git a/files/ja/web/javascript/guide/loops_and_iteration/index.html b/files/ja/web/javascript/guide/loops_and_iteration/index.html new file mode 100644 index 0000000000..baf78c7d80 --- /dev/null +++ b/files/ja/web/javascript/guide/loops_and_iteration/index.html @@ -0,0 +1,365 @@ +--- +title: ループと反復処理 +slug: Web/JavaScript/Guide/Loops_and_iteration +tags: + - Guide + - JavaScript + - Loop + - Syntax + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Loops_and_iteration +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}
+ +

ループは繰り返し何かを実行するための簡便な方法を提供します。本章では JavaScript で利用可能な反復処理を行う数々の文を紹介します。

+ +

誰かに話しかけようと、ある方向に X 歩進み、別の方向に Y 進むといった場面を、コンピューター化されたゲームととらえた上で、ループについて考えてみましょう。例えば、「西に 5 歩進む」という概念はループとして、下記のように表現できます :

+ +
for (let step = 0; step < 5; step++) {
+  // 値が 0 から 4 まで計 5 回実行される
+  console.log('一歩西に歩く');
+}
+
+ +

ループには様々な種類がありますが、本質的にはそれらはすべて同じことをしています : 何らかの行為をある回数繰り返すということです(ただしその回数がゼロということもありえます)。

+ +

様々なループ機構が存在することによって、色々な方法でループの開始点と終了点を決定することができます。あるループの方が別のタイプのループより簡単に目的を果たせる、という状況はたくさんあります。

+ +

JavaScript で提供されるループ文は以下のとおりです :

+ + + +

for

+ +

{{jsxref("Statements/for","for")}} 文によるループは指定された条件が false と評価されるまで繰り返されます。JavaScript の for ループは Java や C 言語の for ループと同じです。

+ +

for 文は以下のような形です :

+ +
for ([初期化式]; [条件式]; [加算式])
+  文
+
+ +

for ループが実行されるとき、次の処理が行われます :

+ +
    +
  1. もしあれば、初期化式が実行されます。この式は通常、1 個またはそれ以上のループカウンターを初期化しますが、この構文ではいかなるレベルの複雑な式を入れることが可能です。初期化式で変数を宣言することもできます。
  2. +
  3. 条件式 条件式が評価されます。条件式の値が true の場合、ループ文が実行されます。条件式の値が false の場合、for ループは終了します。条件式がすべて省略されている場合、条件式は真であると仮定されます。
  4. +
  5. が実行されます。複数の文を実行するには、それらの文をグループ化するためにブロック文 ({ ... }) を使用します。
  6. +
  7. もしあれば、更新式 加算式が実行されます。
  8. +
  9. ステップ 2 に制御が戻ります。
  10. +
+ +

+ +

下の例では、スクロールリスト(複数選択できる {{HTMLElement("select")}} 要素)で選択したオプションの数をカウントする for 文が関数内にあります。for 文が変数 i を宣言しゼロに初期化します。i<select> 要素のオプション数未満であることがチェックされると、後続の if 文が実行され、オプションが選択されていれば、ループの各通過後に 1 個ずつ i が加算されます。

+ +
<form name="selectForm">
+  <p>
+    <label for="musicTypes">Choose some music types, then click the button below:</label>
+    <select id="musicTypes" name="musicTypes" multiple="multiple">
+      <option selected="selected">R&B</option>
+      <option>Jazz</option>
+      <option>Blues</option>
+      <option>New Age</option>
+      <option>Classical</option>
+      <option>Opera</option>
+    </select>
+  </p>
+  <p><input id="btn" type="button" value="How many are selected?" /></p>
+</form>
+
+<script>
+function howMany(selectObject) {
+  let numberSelected = 0;
+  for (let i = 0; i < selectObject.options.length; i++) {
+    if (selectObject.options[i].selected) {
+      numberSelected++;
+    }
+  }
+  return numberSelected;
+}
+
+let btn = document.getElementById('btn');
+btn.addEventListener('click', function() {
+  alert('Number of options selected: ' + howMany(document.selectForm.musicTypes));
+});
+</script>
+
+
+ +

do...while

+ +

{{jsxref("Statements/do...while","do...while")}} 文は指定された条件が false になるまで繰り返します。

+ +

do...while 文は以下のような形です :

+ +
do
+  文
+while (条件式);
+
+ +

は条件式がチェックされる前に毎回一度実行されます。(複数の文を実行するには、ブロック文 ({ ... }) を使って一つの文にします)。

+ +

条件式true の場合、が再び実行されます。の実行終了時に毎回条件がチェックされます。条件が false の場合、実行は停止し、制御は do...while の次の文に渡ります。

+ +

+ +

次の例では、do ループは少なくとも一度繰り返されます。そして i が 5 未満でなくなる直前まで繰り返しされます。

+ +
let i = 0;
+do {
+  i += 1;
+  console.log(i);
+} while (i < 5);
+ +

while

+ +

{{jsxref("Statements/while","while")}} 文は指定された条件が true に評価される限り文を実行します。while 文は以下のようになります :

+ +
while (条件式)
+  文
+
+ +

条件式false となる場合、ループ内のは実行を停止し、ループに続く文に制御が渡されます。

+ +

ループ内のが実行されるに条件がテストされます。条件が true を返す場合、は実行され、条件が再びテストされます。条件が false を返す場合、実行は停止し、while の次の文に制御が渡されます。

+ +

複数の文を実行するには、それらの文をグループ化するブロック文 ({ ... }) を使用します。

+ +

例 1

+ +

次の例では、while ループは、n3 未満の場合繰り返されます。:

+ +
let n = 0;
+let x = 0;
+while (n < 3) {
+  n++;
+  x += n;
+}
+
+ +

各反復で、n がインクリメントされ、その値が x に加算されます。そのため、xn は以下の値をとります:

+ + + +

3 回目の通過完了後、条件式 n < 3 はもはや true ではなくなるため、ループが終了します。

+ +

例 2

+ +

無限ループは避けてください。ループ内の条件が最終的に false になることを確かめるようにしましょう。さもないと、ループは永遠に終了しません。次の while ループ文は、条件が決して false にならないので永遠に実行されます :

+ +
// 無限ループは悪!
+while (true) {
+  console.log('Hello, world!');
+}
+ +

ラベルつき

+ +

{{jsxref("Statements/label","label")}} を使って、プログラム内の他の場所から参照できる識別子を組み込んだ文が作成できます。例えば、ループの識別にラベルを使い、そのプログラムでループを中断するか、実行を継続するかどうかを指定する場合に、ラベルを break 文や continue 文で使用することができます。

+ +

ラベル文の構文は以下のようになります :

+ +
ラベル :
+   文
+
+ +

ラベル の値には、予約語でなければあらゆる JavaScript 識別子を使用できます。ラベルによって識別されるはどんな文でもかまいません。

+ +

+ +

この例では、ラベル markLoopwhile ループを指し示しています。

+ +
markLoop:
+while (theMark === true) {
+   doSomething();
+}
+ +

break

+ +

ループ、switch、ラベル文を使った関連付けを終了させるには {{jsxref("Statements/break","break")}} 文を使います。

+ + + +

break 文の構文は下記のようになります:

+ +
break;
+break [ラベル];
+
+ +
    +
  1. 最初の形では最も内側のループや switch を終了します
  2. +
  3. 2 つ目の形では指定した外側のラベルつき文を終了します。
  4. +
+ +

1

+ +

次の例では、値が theValue である要素のインデックスを探すまで配列の要素を反復します。:

+ +
for (let i = 0; i < a.length; i++) {
+  if (a[i] === theValue) {
+    break;
+  }
+}
+ +

例 2: ラベルまでブレーク

+ +
let x = 0;
+let z = 0;
+labelCancelLoops: while (true) {
+  console.log('外側のループ: ' + x);
+  x += 1;
+  z = 1;
+  while (true) {
+    console.log('内側のループ: ' + z);
+    z += 1;
+    if (z === 10 && x === 10) {
+      break labelCancelLoops;
+    } else if (z === 10) {
+      break;
+    }
+  }
+}
+
+ +

continue

+ +

{{jsxref("Statements/continue","continue")}} 文は whiledo-whileforlabel 文を再開する際に使用されます。

+ + + +

continue文の構文は下記のようになります :

+ +
continue [ラベル];
+
+ +

例 1

+ +

次の例では、i の値が 3 のときに実行される continue 文が使用された while ループを示しています。この場合、n の値は 13712 となります。

+ +
let i = 0;
+let n = 0;
+while (i < 5) {
+  i++;
+  if (i === 3) {
+    continue;
+  }
+  n += i;
+  console.log(n);
+}
+//1,3,7,12
+
+
+let i = 0;
+let n = 0;
+while (i < 5) {
+  i++;
+  if (i === 3) {
+     // continue;
+  }
+  n += i;
+  console.log(n);
+}
+// 1,3,6,10,15
+
+ +

例 2

+ +

次の例では、checkiandj とラベル付けされた文には checkj とラベル付けされた文が含まれています。continue 文に出会うと、プログラムは checkj の現在の反復を終了し次の反復を開始します。continue に出会うたびに、checkj はその条件が false を返すまで繰り返されます。false が返されると、checkiandj の残りの部分が完了し、その条件が false を返すまで checkiandj が繰り返されます。false が返されると、プログラムは checkiandj に続く文を継続します。

+ +

もし continuecheckiandj のラベルを持っていると、プログラムは checkiandj のラベル文の先頭から継続されます。

+ +
let i = 0;
+let j = 10;
+checkiandj:
+  while (i < 4) {
+    console.log(i);
+    i += 1;
+    checkj:
+      while (j > 4) {
+        console.log(j);
+        j -= 1;
+        if ((j % 2) === 0) {
+          continue checkj;
+        }
+        console.log(j + ' is odd.');
+      }
+      console.log('i = ' + i);
+      console.log('j = ' + j);
+  }
+ +

for...in

+ +

{{jsxref("Statements/for...in","for...in")}} 文はオブジェクトにあるすべての列挙可能なプロパティに対し指定された変数を通して反復処理を行います。それぞれの異なるプロパティに、JavaScript は指定された文を実行します。for...in 文は下記のようになります :

+ +
for (変数 in オブジェクト)
+  文
+
+ +

+ +

次の関数は引数としてオブジェクトと、そのオブジェクトの名前を表す文字列を取ります。それからすべてのオブジェクトのプロパティに対して反復し、プロパティ名とその値を表示する文字列を返します。

+ +
function dump_props(obj, obj_name) {
+  let result = '';
+  for (let i in obj) {
+    result += obj_name + '.' + i + ' = ' + obj[i] + '<br>';
+  }
+  result += '<hr>';
+  return result;
+}
+
+ +

make プロパティと model プロパティを持つ car オブジェクトに対し、result は下記のようになります :

+ +
car.make = Ford
+car.model = Mustang
+
+ +

配列

+ +

{{jsxref("Array")}} の要素に対して反復処理を行う方法として for...in 文を使用したくなるかもしれませんが、これは数値のインデックスに加えてユーザー定義プロパティの名前も返します。

+ +

そのため、配列に対しての反復処理には、数値のインデックスを使い従来の {{jsxref("Statements/for","for")}} ループを使用するほうが良いです。なぜなら、(カスタムプロパティやカスタムメソッドを追加するといった) Array オブジェクトの変更を行った場合、for...in 文は配列要素に加えてユーザー定義プロパティに対しても反復処理するからです。

+ +

for...of

+ +

{{jsxref("Statements/for...of","for...of")}} 文は、反復可能オブジェクト({{jsxref("Array")}}、{{jsxref("Map")}}、{{jsxref("Set")}}、{{jsxref("functions/arguments","arguments")}} オブジェクトなどを含む)を反復処理するループを生成し、それぞれのプロパティの値に対して実行したい文をともなって作られた反復処理フックを呼び出します。

+ +
for (変数 of オブジェクト)
+  
+
+ +

次の例では、for...of ループと {{jsxref("Statements/for...in","for...in")}} ループとの違いを示しています。for...in はプロパティ名に対し反復処理される一方、for...of はプロパティの値に対し反復処理します :

+ +
const arr = [3, 5, 7];
+arr.foo = 'hello';
+
+for (let i in arr) {
+   console.log(i); // "0", "1", "2", "foo" が出力される
+}
+
+for (let i of arr) {
+   console.log(i); // 3, 5, 7 が出力される
+}
+
+ +

{{PreviousNext("Web/JavaScript/Guide/Control_flow_and_error_handling", "Web/JavaScript/Guide/Functions")}}

diff --git a/files/ja/web/javascript/guide/meta_programming/index.html b/files/ja/web/javascript/guide/meta_programming/index.html new file mode 100644 index 0000000000..c0b3b18129 --- /dev/null +++ b/files/ja/web/javascript/guide/meta_programming/index.html @@ -0,0 +1,290 @@ +--- +title: メタプログラミング +slug: Web/JavaScript/Guide/Meta_programming +tags: + - ECMAScript 2015 + - Guide + - JavaScript + - Proxy + - Reflect + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Meta_programming +--- +
{{jsSidebar("JavaScript Guide")}} {{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}
+ +

ECMAScript 2015 から、JavaScript には {{jsxref("Proxy")}} オブジェクトと {{jsxref("Reflect")}} オブジェクトがサポートされました。これらは基本的な言語操作(例えば、プロパティ検索、代入、列挙、関数呼び出しなど)に割り込み、動作をカスタマイズできます。この 2 つのオブジェクトのおかげで、JavaScript でメタレベルのプログラミングが行えます。

+ +

Proxy

+ +

ECMAScript 6 で導入された {{jsxref("Proxy")}} オブジェクトによって、特定の操作に割り込んで動作をカスタマイズできます。

+ +

例えば、オブジェクトのプロパティを取得してみましょう :

+ +
let handler = {
+  get: function(target, name) {
+    return name in target? target[name] : 42
+  }
+}
+
+let p = new Proxy({}, handler)
+p.a = 1
+console.log(p.a, p.b) // 1, 42
+
+ +

この Proxy オブジェクトは target(ここでは空オブジェクト)と get トラップが実装された handler オブジェクトを定義しています。ここで、プロキシとなったオブジェクトは未定義のプロパティを取得しようとした時 undefined を返さず、代わりに数値 42 を返します。

+ +

さらなる使用例がリファレンスの「{{jsxref("Proxy")}}」ページにあります。

+ +

用語集

+ +

プロキシの機能について話題にする際は、次の用語が使用されます。

+ +
+
{{jsxref("Global_Objects/Proxy/handler","ハンドラ","","true")}} (handler)
+
トラップを入れるためのプレースホルダ用オブジェクト。
+
{{原語併記("トラップ","trap")}}
+
プロパティへのアクセスを提供するメソッド。オペレーティングシステムにおけるトラップの概念と同じようなものです。
+
{{原語併記("ターゲット","target")}}
+
プロキシが仮想化するオブジェクト。これはプロキシのストレージバックエンドとしてしばしば使われます。拡張・設定可能でないプロパティを持つオブジェクトに関する不変条件(変更されないセマンティック、つまりオブジェクトの意味情報)は、このターゲットに対して検証されます。
+
{{原語併記("不変条件","invariant")}}
+
カスタマイズした動作を実装する際、変更されないセマンティックを不変条件と呼びます。ハンドラの不変条件に違反した場合、{{jsxref("TypeError")}} が発生します。
+
+ +

ハンドラとトラップ

+ +

次の表は、Proxy オブジェクトに対して利用可能なトラップをまとめたものです。詳細と例についてはリファレンスのハンドラについてのページをご覧ください。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ハンドラ / トラップ割り込みされる処理不変条件
{{jsxref("Global_Objects/Proxy/handler/getPrototypeOf", "handler.getPrototypeOf()")}}{{jsxref("Object.getPrototypeOf()")}}
+ {{jsxref("Reflect.getPrototypeOf()")}}
+ {{jsxref("Object/proto", "__proto__")}}
+ {{jsxref("Object.prototype.isPrototypeOf()")}}
+ {{jsxref("Operators/instanceof", "instanceof")}}
+
    +
  • getPrototypeOf メソッドはオブジェクトか null を返す必要があります。
  • +
  • target が拡張不可の場合、Object.getPrototypeOf(proxy) メソッドは Object.getPrototypeOf(target) と同じ値を返す必要があります。
  • +
+
{{jsxref("Global_Objects/Proxy/handler/setPrototypeOf", "handler.setPrototypeOf()")}}{{jsxref("Object.setPrototypeOf()")}}
+ {{jsxref("Reflect.setPrototypeOf()")}}
target が拡張不可の場合、prototype パラメータは Object.getPrototypeOf(target) と同じ値である必要があります。
{{jsxref("Global_Objects/Proxy/handler/isExtensible", "handler.isExtensible()")}}{{jsxref("Object.isExtensible()")}}
+ {{jsxref("Reflect.isExtensible()")}}
Object.isExtensible(proxy)Object.isExtensible(target) と同じ値を返す必要があります。
{{jsxref("Global_Objects/Proxy/handler/preventExtensions", "handler.preventExtensions()")}}{{jsxref("Object.preventExtensions()")}}
+ {{jsxref("Reflect.preventExtensions()")}}
+

Object.isExtensible(proxy)false の場合のみ、Object.preventExtensions(proxy)true を返します。

+
{{jsxref("Global_Objects/Proxy/handler/getOwnPropertyDescriptor", "handler.getOwnPropertyDescriptor()")}}{{jsxref("Object.getOwnPropertyDescriptor()")}}
+ {{jsxref("Reflect.getOwnPropertyDescriptor()")}}
+
    +
  • getOwnPropertyDescriptor はオブジェクトか undefined のいずれかを返す必要があります。
  • +
  • ターゲットオブジェクトに設定不可の所有プロパティとして存在する場合、そのプロパティについて存在しないと報告することはできません。
  • +
  • 拡張不可のターゲットオブジェクトに所有プロパティとして存在する場合、そのプロパティについて存在しないと報告することはできません。
  • +
  • 拡張不可のターゲットオブジェクトに所有プロパティとして存在しない場合、そのプロパティについて存在すると報告することはできません。
  • +
  • ターゲットオブジェクトに所有プロパティとして存在しない場合、あるいはターゲットオブジェクトに設定可能な所有プロパティとして存在する場合、そのプロパティについて設定不可と報告することはできません。
  • +
  • Object.getOwnPropertyDescriptor(target) の結果は Object.defineProperty を使用してターゲットオブジェクトに適用され、この時に例外は発生しません。
  • +
+
{{jsxref("Global_Objects/Proxy/handler/defineProperty", "handler.defineProperty()")}}{{jsxref("Object.defineProperty()")}}
+ {{jsxref("Reflect.defineProperty()")}}
+
    +
  • ターゲットオブジェクトが拡張可能ではない場合、プロパティは追加できません。
  • +
  • ターゲットオブジェクトに設定不可の所有プロパティとして存在しない場合、そのプロパティを追加したり、また設定不可に更新することはできません。
  • +
  • ターゲットオブジェクトに対応する設定可能なプロパティとして存在する場合、そのプロパティを設定不可としてもかまいません。
  • +
  • プロパティが対応するターゲットオブジェクトプロパティを持つ場合、Object.defineProperty(target, prop, descriptor) は例外を発生しません。
  • +
  • strict モードでは、defineProperty ハンドラからの戻り値が false の場合、{{jsxref("TypeError")}} 例外が発生します。
  • +
+
{{jsxref("Global_Objects/Proxy/handler/has", "handler.has()")}}プロパティの照会 :
+ foo in proxy
+ 継承されたプロパティの照会 :
+ foo in Object.create(proxy)
+ {{jsxref("Reflect.has()")}}
+
    +
  • ターゲットオブジェクトに設定不可の所有プロパティとして存在する場合、そのプロパティについて存在しないと報告することはできません。
  • +
  • ターゲットオブジェクトの所有プロパティとして存在し、そのターゲットオブジェクトが拡張可能ではない場合、そのプロパティについて存在しないと報告することはできません。
  • +
+
{{jsxref("Global_Objects/Proxy/handler/get", "handler.get()")}}プロパティへのアクセス :
+ proxy[foo]and proxy.bar
+ 継承されたプロパティアクセス :
+ Object.create(proxy)[foo]
+ {{jsxref("Reflect.get()")}}
+
    +
  • ターゲットオブジェクトプロパティが書込不可、設定不可のデータプロパティである場合、プロパティに対して報告する値は対応するプロパティと同じ値である必要があります。
  • +
  • 対応するターゲットオブジェクトプロパティが、Get 属性に undefined を持つ設定不可のアクセサプロパティである場合、プロパティに対して報告される値を undefined とする必要があります。
  • +
+
{{jsxref("Global_Objects/Proxy/handler/set", "handler.set()")}}プロパティへの代入 :
+ proxy[foo] = bar, proxy.foo = bar
+ 継承されたプロパティの割り当て :
+ Object.create(proxy)[foo] = bar
+ {{jsxref("Reflect.set()")}}
+
    +
  • 対応するターゲットオブジェクトのプロパティが書込不可、設定不可のデータプロパティである場合、そのプロパティとは違うプロパティ値に変更することはできません。
  • +
  • 対応するターゲットオブジェクトプロパティが、Set 属性に undefined を持つ設定不可のアクセサプロパティである場合、プロパティの値を設定することはできません。
  • +
  • strict モードでは、set ハンドラからの戻り値が false の場合、{{jsxref("TypeError")}} 例外が発生します。 +
      +
    +
  • +
+
{{jsxref("Global_Objects/Proxy/handler/deleteProperty", "handler.deleteProperty()")}}プロパティの削除 :
+ delete proxy[foo], delete proxy.foo
+ {{jsxref("Reflect.deleteProperty()")}}
ターゲットオブジェクトに設定不可の所有プロパティとして存在する場合、削除することはできません。
{{jsxref("Global_Objects/Proxy/handler/enumerate", "handler.enumerate()")}}プロパティの列挙 / for...in :
+ for (var name in proxy) {...}
+ {{jsxref("Reflect.enumerate()")}}
enumerate メソッドはオブジェクトを返す必要があります。
{{jsxref("Global_Objects/Proxy/handler/ownKeys", "handler.ownKeys()")}}{{jsxref("Object.getOwnPropertyNames()")}}
+ {{jsxref("Object.getOwnPropertySymbols()")}}
+ {{jsxref("Object.keys()")}}
+ {{jsxref("Reflect.ownKeys()")}}
+
    +
  • ownKeys の結果はリストとなります。
  • +
  • 出力リストの要素の型は {{jsxref("String")}} か {{jsxref("Symbol")}} のどちらかとなります。
  • +
  • 出力リストはターゲットオブジェクト中にあるすべての設定不可な所有プロパティのキーを含める必要があります。
  • +
  • ターゲットオブジェクトが拡張不可の場合、出力リストはターゲットオブジェクト中の所有プロパティのキーをすべて含める必要があり、他の値は含まれません。 +
      +
    +
  • +
+
{{jsxref("Global_Objects/Proxy/handler/apply", "handler.apply()")}}proxy(..args)
+ {{jsxref("Function.prototype.apply()")}} and {{jsxref("Function.prototype.call()")}}
+ {{jsxref("Reflect.apply()")}}
handler.apply メソッドに対する不変条件はありません。
{{jsxref("Global_Objects/Proxy/handler/construct", "handler.construct()")}}new proxy(...args)
+ {{jsxref("Reflect.construct()")}}
出力結果は Object とする必要があります。
+ +

取り消し可能 Proxy

+ +

{{jsxref("Proxy.revocable()")}} メソッドは取り消し可能な Proxy オブジェクトの生成に使用されます。これにより、プロキシを revoke 関数で取り消し、プロキシの機能を停止することができます。

+ +

その後はプロキシを通じたいかなる操作も {{jsxref("TypeError")}} になります。

+ +
let revocable = Proxy.revocable({}, {
+  get: function(target, name) {
+    return '[[' + name + ']]'
+  }
+})
+let proxy = revocable.proxy
+console.log(proxy.foo)  // "[[foo]]"
+
+revocable.revoke()
+
+console.log(proxy.foo)  // TypeError が発生
+proxy.foo = 1           // TypeError が再び発生
+delete proxy.foo        // TypeError がここでも発生
+typeof proxy            // "object" が返され, typeof はどんなトラップも引き起こさない
+
+ +

リフレクション

+ +

{{jsxref("Reflect")}} は JavaScript で割り込み操作を行うメソッドを提供するビルトインオブジェクトです。そのメソッドは {{jsxref("Global_Objects/Proxy/handler","Proxy ハンドラ","","true")}}のメソッドと同じです。

+ +

Reflect は関数オブジェクトではありません。

+ +

Reflect はハンドラからターゲットへのデフォルト操作を転送するのに役立ちます。

+ +

例えば、{{jsxref("Reflect.has()")}} を使えば、in 演算子を関数として使うことができます :

+ +
Reflect.has(Object, 'assign') // true
+
+ +

より優れた apply 関数

+ +

ES5 では、所定の this 値と配列や配列様のオブジェクトとして提供される arguments を使って関数を呼び出す {{jsxref("Function.prototype.apply()")}} メソッドがよく使われてきました。

+ +
Function.prototype.apply.call(Math.floor, undefined, [1.75])
+
+ +

{{jsxref("Reflect.apply")}} を使えば、より簡潔で分かりやすいものにできます :

+ +
Reflect.apply(Math.floor, undefined, [1.75])
+// 1
+
+Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111])
+// "hello"
+
+Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index
+// 4
+
+Reflect.apply(''.charAt, 'ponies', [3])
+// "i"
+
+ +

プロパティ定義の成否チェック

+ +

成功した時はオブジェクトを返し、失敗した時は {{jsxref("TypeError")}} を発生させる {{jsxref("Object.defineProperty")}} では、プロパティを定義する際に発生するエラーを捉えるのに {{jsxref("Statements/try...catch","try...catch")}} ブロックを使おうとしていたでしょう。{{jsxref("Reflect.defineProperty")}} では成功したかどうかによって真偽値を返すので、ここでは {{jsxref("Statements/if...else","if...else")}} ブロックを使えます :

+ +
if (Reflect.defineProperty(target, property, attributes)) {
+  // 成功した時の処理
+} else {
+  // 失敗した時の処理
+}
+ +

{{Previous("Web/JavaScript/Guide/Iterators_and_Generators")}}

diff --git a/files/ja/web/javascript/guide/modules/index.html b/files/ja/web/javascript/guide/modules/index.html new file mode 100644 index 0000000000..1f976ae67a --- /dev/null +++ b/files/ja/web/javascript/guide/modules/index.html @@ -0,0 +1,457 @@ +--- +title: JavaScript モジュール +slug: Web/JavaScript/Guide/Modules +tags: + - Guide + - JavaScript + - Modules + - export + - impot +translation_of: Web/JavaScript/Guide/Modules +--- +
{{jsSidebar("JavaScript Guide")}}{{Previous("Web/JavaScript/Guide/Meta_programming")}}
+ +

本章では、JavaScript のモジュールを使い始めるために必要なことすべてを紹介します。

+ +

モジュールの背景

+ +

JavaScript のプログラムはとても小さいものから始まりました。初期の用途は、必要に応じてウェブページにちょっとした対話的な機能を追加する独立したスクリプト処理がほとんどであったため、大きなスクリプトは通常必要ありませんでした。そして何年かが過ぎ、今や大量の JavaScript を持つ完全なアプリケーションをブラウザーで実行することはもちろん、JavaScript を他のコンテキスト (例えば Node.js) で使うこともあります。

+ +

それゆえ近年は、JavaScript プログラムをモジュールに分割して必要な時にインポートできるような仕組みの提供が検討されるようになってきました。Node.js は長年この機能を提供しており、モジュールの利用を可能にする JavaScript ライブラリーやフレームワークも数多くあります (例えば、他の CommonJS や、AMD ベースのモジュールシステムである RequireJS など、そしてより最近では WebpackBabel)。

+ +

良い知らせは、モダンブラウザーがモジュール機能のネイティブサポートを開始していることで、この記事がその全てです。これは良いことです。ブラウザーはモジュールの読み込みを最適化できるので、外部ライブラリーを使用してクライアント側の余分な処理やラウンドトリップを行うよりも効率的にすることができます。

+ +

ブラウザーのサポート状況

+ +

ネイティブの JavaScript モジュール機能は、importexport 文を利用します。これらに対するブラウザーの互換性は次のとおりです。

+ +

import

+ +

{{Compat("javascript.statements.import")}}

+ +

export

+ +

{{Compat("javascript.statements.export")}}

+ +

使用例の紹介

+ +

モジュールの使い方を紹介するために、GitHub 上に簡単な使用例を作りました。これらは、ウェブページに {{htmlelement("canvas")}} 要素を追加し、その canvas 上にいくつかの異なる図形 (と、それに関するレポート) を描画する簡単なモジュールの例です。

+ +

このような機能はあまり役に立ちませんが、モジュールの説明が明確になるように意図的に単純にしています。

+ +
+

注意: 使用例をダウンロードしてローカル実行する場合、ローカルのウェブサーバー上で実行する必要があります。

+
+ +

構造の基本的な例

+ +

最初の使用例 (basic-modules を参照) には、次のようなファイル構造があります。

+ +
index.html
+main.js
+modules/
+    canvas.js
+    square.js
+ +
+

注意: このガイドの使用例のファイル構造は、全て基本的に同一ですので、上記のファイル構造をよく見ることになるでしょう。

+
+ +

ディレクトリー modules には、次の 2 つのモジュールがあります。

+ + + +

余談 — .mjs.js

+ +

この記事ではモジュールファイルに .js の拡張子を使用していますが、他の記事では .mjs という拡張子が使用されているのを目にすることがあるかもしれません。例えば、V8 のドキュメントではこれを推奨しています。理由は以下の通りです。

+ + + +

しかし、少なくとも今のところは .js を使い続けることにしました。ブラウザでモジュールを正しく動作させるためには、サーバーが text/javascript などの JavaScript MIME タイプを含む Content-Type ヘッダでモジュールを提供していることを確認する必要があります。そうしないと、"The server responded with a non-JavaScript MIME type" のような厳格な MIME タイプチェックエラーが表示され、ブラウザは JavaScript を実行しません。ほとんどのサーバーでは、.js ファイルにはすでに正しい MIME タイプが設定されていますが、.mjs ファイルにはまだ設定されていません。すでに .mjs ファイルを正しく提供しているサーバーには、GitHub Pages や Node.js の http-server などがあります。

+ +

これは、すでにそのような環境を使用している場合や、今はまだ使用していないが、何をしているか知っていてアクセスできる場合には問題ありません(つまり、.mjs ファイルに正しい Content-Type を設定するようにサーバーを設定することができます)。しかし、あなたがファイルを提供しているサーバーを制御できない場合には、混乱を引き起こす可能性があります。

+ +

この記事では学習と移植性を考慮して、.js を使用することにしました。

+ +

通常の JavaScript ファイルに .js を使用するのと比較して、モジュールに .mjs を使用することの明確さを本当に重視しているが、上記の問題に直面したくない場合は、開発中に .mjs を使用し、ビルドステップで .js に変換することをおすすめします。

+ +

また、次の点にも注意してください。

+ + + +

モジュール機能のエクスポート

+ +

モジュールが持つ機能にアクセスするために最初に必要なことは、そのような機能をエクスポートすることです。これは export 文を使って行います。

+ +

最も簡単な使い方は、モジュール外部に公開したい項目の前に export をつけることです。

+ +
export const name = 'square';
+
+export function draw(ctx, length, x, y, color) {
+  ctx.fillStyle = color;
+  ctx.fillRect(x, y, length, length);
+
+  return {
+    length: length,
+    x: x,
+    y: y,
+    color: color
+  };
+}
+ +

エクスポートできるものは、関数、varletconst、および後で見ることになりますが、クラスです。これらは最上位の階層にある必要があります。例えば、関数内で export を使うことはできません。

+ +

エクスポートしたい全ての項目をエクスポートするより便利な方法は、モジュールファイルの末尾に単一の export 文を追加し、その後にエクスポートしたい機能のカンマ区切りリストを中かっこで囲んで続けることです。例えば次のようにします。

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

スクリプトへの機能のインポート

+ +

モジュールから何らかの機能をエクスポートした後は、それらを使えるようにするためにスクリプトにインポートする必要があります。その最も単純な方法は次のとおりです。

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+ +

import 文の後ろに、中かっこで囲まれたインポートしたい機能のカンマ区切りリストを続け、その後ろに from キーワードと、モジュールファイルへのパスを続けます。このパスは、サイトのルートからの相対パスであり、basic-modules の場合は /js-examples/modules/basic-modules です。

+ +

しかし、この例ではパスの書き方が少し異なっています。「現在の位置」を意味するドット (.) 記法を使っており、その後ろに見つけようとするファイルへのパスを続けています。これは、完全な相対パスを毎回記述するよりも短くてすむためとてもよい方法であり、URL の可搬性もあるため、サイト階層構造の異なる場所に移動させた場合でも動作するでしょう。

+ +

そのため、このようなパスは、

+ +
/js-examples/modules/basic-modules/modules/square.js
+ +

このように書けます。

+ +
./modules/square.js
+ +

このような書き方の動作している例は main.js にあります。

+ +
+

注意: モジュールシステムの中には、ファイルの拡張子やドットを省略できるものがあります (例えば '/modules/square')。このような書き方は、ネイティブの JavaScript モジュールでは動作しません。

+
+ +

スクリプトへ機能をインポートすると、同じファイル内で定義されているのと同じように使うことができます。次のコードは、main.js でインポートに続く部分です。

+ +
let myCanvas = create('myCanvas', document.body, 480, 320);
+let reportList = createReportList(myCanvas.id);
+
+let square1 = draw(myCanvas.ctx, 50, 50, 100, 'blue');
+reportArea(square1.length, reportList);
+reportPerimeter(square1.length, reportList);
+
+ +
+

注: インポートされた機能はファイル内で利用できますが、エクスポートされた機能の読み取り専用ビューです。インポートされた変数を変更することはできませんが、const と同様にプロパティを変更することはできます。さらに、これらの機能はライブバインディングとしてインポートされます。つまり、const と違ってバインディングを変更できなくても値を変更できるということです。

+
+ +

HTML にモジュールを適用する

+ +

次に main.js モジュールを HTML ページに適用する必要があります。これは少し重要な点に違いがありますが、通常のスクリプトをページに適用する方法ととてもよく似ています。

+ +

最初に type="module" を {{htmlelement("script")}} 要素に含めることで、そのスクリプトがモジュールであることを宣言します。

+ +
<script type="module" src="main.js"></script>
+ +

また、<script> 要素の本文内に JavaScript コードを配置することで、モジュールのスクリプトをHTMLファイルに直接埋め込むこともできます。

+ +
<script type="module">
+  /* ここに JavaScript モジュールコード */
+</script>
+ +

モジュールをインポートする先のスクリプトは、基本的に最上位のモジュールとして動作します。これを無視すると、例えば Firefox の場合は "SyntaxError: import declarations may only appear at top level of a module" (構文エラー: インポート宣言は最上位のモジュールしか使えません) というエラーが発生します。

+ +

importexport 文は、モジュールの中でのみ使うことができます。通常のスクリプトの中では使えません。

+ +

モジュールの通常のスクリプトの間のその他の違い

+ + + +

デフォルトエクスポートと名前付きエクスポート

+ +

これまでエクスポートした機能は、名前付きエクスポート (named export) というものです。それぞれの項目 (関数、const など) は、エクスポート時にその名前を参照されて、インポート時にもその名前で参照されます。

+ +

エクスポートの種類には、他にデフォルトエクスポートと呼ばれるものもあります。これは、モジュールがデフォルトの機能を簡単に持つことができるように設計されたもので、また JavaScript のモジュールが既存の CommonJS や AMD のモジュールシステムと相互運用できるようになります (Json Orendorff による ES6 In Depth: Modules で上手く説明されています。"Default exports" で検索してみてください)。

+ +

どのように動作するか説明するので、使用例をみてみましょう。basic-modules の square.js に、ランダムな色、大きさ、位置の正方形を描く randomSquare() という関数があります。この関数をデフォルトとしてエクスポートしたいので、ファイルの末尾に次の内容を書きます。

+ +
export default randomSquare;
+ +

中かっこがないことに注意してください。

+ +

または、export default を関数に追加して、次のように匿名関数のように定義することもできます。

+ +
export default function(ctx) {
+  ...
+}
+ +

main.js では、次のようにしてデフォルトの関数をインポートします。

+ +
import randomSquare from './modules/square.js';
+ +

インポートの時にも中かっこがないことに注意してください。これは、デフォルトエクスポートはモジュールごとにひとつしか作れず、randomSquare がそれであることがわかっているからです。上記は、基本的に次の簡略表現です。

+ +
import {default as randomSquare} from './modules/square.js';
+ +
+

注意: エクスポートされる項目の名前を変更するために使われる as の文法については、以下の {{anch("Renaming imports and exports")}} セクションで説明します。

+
+ +

名前の衝突を避ける

+ +

これまでのところ、キャンバスに図形を描く私たちのモジュールは正常に動作しているようです。しかし、円や三角形など別の図形を描くモジュールを追加しようとしたらどうなるでしょう? そのような図形にも draw()reportArea() のような関数があるかもしれません。もし同じ名前を持つ異なる関数を同じトップレベルのモジュールファイルにインポートしようとすると、最終的に名前の衝突によるエラーが起きるでしょう。

+ +

幸いなことに、これに対処する方法はいくつかあります。それらについて、次のセクションで見ていきましょう。

+ +

インポートやエクスポートの名前を変更する

+ +

import 文や export 文の中かっこの中では、キーワード as と新しい名前を使うことで、トップレベルのモジュールでその機能を使うときの名前を変更することができます。

+ +

次の二つの例は、異なる方法ですが、同じことをしています。

+ +
// module.js の内部
+export {
+  function1 as newFunctionName,
+  function2 as anotherNewFunctionName
+};
+
+// main.js の内部
+import { newFunctionName, anotherNewFunctionName } from './modules/module.js';
+ +
// module.js の内部
+export { function1, function2 };
+
+// main.js の内部
+import { function1 as newFunctionName,
+         function2 as anotherNewFunctionName } from './modules/module.js';
+ +

実際の例を見てみましょう。renaming ディレクトリでは、前の使用例と同じモジュールを使っていますが、円や三角形を描画するためのモジュールである circle.jstriangle.js も追加しています。

+ +

それぞれのモジュール内部では、同じ名前を持つ機能がエクスポートされており、それゆえそれぞれの末尾の export 文は次のように同一であることがわかります。

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

これらを main.js にインポートするために、次のようにするとします。

+ +
import { name, draw, reportArea, reportPerimeter } from './modules/square.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/circle.js';
+import { name, draw, reportArea, reportPerimeter } from './modules/triangle.js';
+ +

すると、ブラウザーは "SyntaxError: redeclaration of import name" (構文エラー: インポート名の再宣言) (Firefox の場合) のようなエラーを発生させるでしょう。

+ +

そのため、それぞれが固有の名前を持つようにするために、次のようにインポートの名前を変える必要があります。

+ +
import { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter } from './modules/square.js';
+
+import { name as circleName,
+         draw as drawCircle,
+         reportArea as reportCircleArea,
+         reportPerimeter as reportCirclePerimeter } from './modules/circle.js';
+
+import { name as triangleName,
+        draw as drawTriangle,
+        reportArea as reportTriangleArea,
+        reportPerimeter as reportTrianglePerimeter } from './modules/triangle.js';
+ +

他の方法として、例えば次のようにすることで、モジュールファイル側でこの問題を解決することもできます。

+ +
// in square.js
+export { name as squareName,
+         draw as drawSquare,
+         reportArea as reportSquareArea,
+         reportPerimeter as reportSquarePerimeter };
+ +
// in main.js
+import { squareName, drawSquare, reportSquareArea, reportSquarePerimeter } from './modules/square.js';
+ +

これも同じように機能します。どちらのスタイルを取るかはあなた次第ですが、モジュール側のコードはそのままにしてインポート側を変更する方が、間違いなく賢明です。これは、制御できないサードパーティーのモジュールからインポートするときには、特に意味があります。

+ +

モジュールオブジェクトの作成

+ +

上記のインポート方法は正常に動作しますが、少し使いづらく冗長です。よりよい方法は、モジュール内のそれぞれの機能を、モジュールオブジェクトの中にインポートすることです。その構文は次のとおりです。

+ +
import * as Module from './modules/module.js';
+ +

これは、module.js の中にある全てのエクスポートを取得して、それらを Module というオブジェクトのメンバーとして利用できるようにすることで、独自の名前空間を持たせるような効果があります。次のようにして使います。

+ +
Module.function1()
+Module.function2()
+など
+ +

実際の使用例を見てみましょう。module-objects ディレクトリでは、また同じ例を使っていますが、この新しい構文を利用するために書き直されています。モジュール内のエクスポートは、いずれも次の単純な構文を使っています。

+ +
export { name, draw, reportArea, reportPerimeter };
+ +

一方でインポートは次のようなものです。

+ +
import * as Canvas from './modules/canvas.js';
+
+import * as Square from './modules/square.js';
+import * as Circle from './modules/circle.js';
+import * as Triangle from './modules/triangle.js';
+ +

どの場合も、その指定されたオブジェクト名の配下からモジュールのインポートにアクセスできます。例えば次のようにして使います。

+ +
let square1 = Square.draw(myCanvas.ctx, 50, 50, 100, 'blue');
+Square.reportArea(square1.length, reportList);
+Square.reportPerimeter(square1.length, reportList);
+ +

このように (必要な箇所にオブジェクトの名前を含むようにさえすれば) コードは以前と同じように書くことができ、そしてインポートはより簡潔になります。

+ +

モジュールとクラス

+ +

最初の方で触れましたが、クラスをエクスポートしたりインポートすることもできます。これがコード上で名前の衝突を避けるもう一つの方法で、もし自分のモジュールを既にオブジェクト指向のスタイルで書いているのであれば、特に便利です。

+ +

classes ディレクトリの中には、私たちの図形を描くモジュールを ES クラスを使って書き直した例があります。例えば square.js ファイルでは、次のように全ての機能を一つのクラスの中に持たせています。

+ +
class Square {
+  constructor(ctx, listId, length, x, y, color) {
+    ...
+  }
+
+  draw() {
+    ...
+  }
+
+  ...
+}
+ +

そして、次のようにエクスポートします。

+ +
export { Square };
+ +

main.js では、これを次のようにインポートします。

+ +
import { Square } from './modules/square.js';
+ +

そして、正方形を描くために次のようにクラスを使います。

+ +
let square1 = new Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+square1.draw();
+square1.reportArea();
+square1.reportPerimeter();
+ +

モジュールの集約

+ +

複数のモジュールをひとつに集約させたいと思うことがあるかもしれません。依存性の階層は複数になることがあり、いくつかあるサブモジュールをひとつの親モジュールにまとめて管理を単純化したいと思うかもしれません。これは、親モジュールで次の形式によるエクスポート構文を使うことで可能です。

+ +
export * from 'x.js'
+export { name } from 'x.js'
+ +

使用例は module-aggregation ディレクトリを参照してください。この例 (クラスを使った以前の例を元にしています) には、shapes.js というモジュールが追加されています。これは circle.jssquare.jstriangle.js の全ての機能をひとつに集約したものです。また、サブモジュールを modules ディレクトリの中にある shapes というサブディレクトリに移動させています。つまり、この例のモジュール構造は次のようなものです。

+ +
modules/
+  canvas.js
+  shapes.js
+  shapes/
+    circle.js
+    square.js
+    triangle.js
+ +

それぞれのサブモジュールでは、例えば次のような同じ形式のエクスポートが行われています。

+ +
export { Square };
+ +

その次は集約を行う部分です。shapes.js の内部には次のような行があります。

+ +
export { Square } from './shapes/square.js';
+export { Triangle } from './shapes/triangle.js';
+export { Circle } from './shapes/circle.js';
+ +

これらは、個々のサブモジュールのエクスポートを取得して、それらを shapes.js モジュールから利用できるようにする効果があります。

+ +
+

注意: shapes.mjs の中で参照されているエクスポートは、基本的にそのファイルを経由して転送されるだけで、ファイルの中には存在しません。そのため、同じファイルの中でそれらを使ったコードを書くことはできません。

+
+ +

最後に main.js ファイルでは、全てのモジュールのクラスにアクセスするために、次のインポートを書き換えています。

+ +
import { Square } from './modules/square.js';
+import { Circle } from './modules/circle.js';
+import { Triangle } from './modules/triangle.js';
+ +

書き換え後は、次のような 1行になります。

+ +
import { Square, Circle, Triangle } from './modules/shapes.js';
+ +

動的なモジュールの読み込み

+ +

ブラウザーで利用できる JavaScript モジュールの最新機能は、動的なモジュールの読み込みです。これにより、全てを最初に読み込んでしまうのではなく、必要が生じたときにのみ動的にモジュールを読み込むことができます。これには明らかなパフォーマンス上の利点があります。どのように動作するのか、読んで見てましょう。

+ +

この新しい機能により、import() を関数として実行し、そのときのパラメーターとしてモジュールへのパスを指定することができます。これは次のように Promise を返し、エクスポートにアクセスできるモジュールオブジェクト ({{anch("Creating a module object")}} を参照) を使って fulfilled 状態になります。

+ +
import('./modules/myModule.js')
+  .then((module) => {
+    // モジュールを使って何かをする。
+  });
+ +

例を見てみましょう。dynamic-module-imports ディレクトリには、以前のクラスの例に基づいた別の使用例があります。しかし、今回は使用例が読み込まれたときにはキャンバスに何も描画しません。その代わり "Circle" (円)、"Square" (正方形)、"Triangle" (三角形) という 3つのボタンを表示し、それらが押されたとき、対応した図形を描くために必要なモジュールを動的に読み込んで使用します。

+ +

この使用例では index.htmlmain.js のみを変更しており、モジュールのエクスポートは以前と同じままです。

+ +

main.js では、それぞれのボタンへの参照を取得するために、次のように document.querySelector() を使っています。

+ +
let squareBtn = document.querySelector('.square');
+ +

そしてそれぞれのボタンに、押されたときに関連するモジュールを動的に読み込んで図形を描くためのイベントリスナーを設定します。

+ +
squareBtn.addEventListener('click', () => {
+  import('./modules/square.js').then((Module) => {
+    let square1 = new Module.Square(myCanvas.ctx, myCanvas.listId, 50, 50, 100, 'blue');
+    square1.draw();
+    square1.reportArea();
+    square1.reportPerimeter();
+  })
+});
+ +

Promise が fullfilled 状態になったときにモジュールオブジェクトを返し、クラスはそのオブジェクトの部分機能であるため、Module.Square( ... ) のように Module. を追加したコンストラクターにアクセスする必要があります。

+ +

トラブルシューティング

+ +

これらは、モジュールの動作に問題があるときに助けになるかもしれないヒントです。もし他にあれば自由にリストに追加してください。

+ + + +

関連情報

+ + + +

{{Previous("Web/JavaScript/Guide/Meta_programming")}}

diff --git a/files/ja/web/javascript/guide/numbers_and_dates/index.html b/files/ja/web/javascript/guide/numbers_and_dates/index.html new file mode 100644 index 0000000000..dbe09c4412 --- /dev/null +++ b/files/ja/web/javascript/guide/numbers_and_dates/index.html @@ -0,0 +1,395 @@ +--- +title: 数値と日付 +slug: Web/JavaScript/Guide/Numbers_and_dates +tags: + - Calculation + - Dates + - FP + - Floating Point + - Floating-Point + - Guide + - Integer + - JavaScript + - Math + - Numbers + - Numeric + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Numbers_and_dates +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}
+ +

本章では、JavaScript で数値と日付の計算を実行するのに使われる概念、オブジェクト、関数について紹介します。これには 10進数、2進数、16 進数数値を含むそれぞれの基数で表された数値を使用することや、数値の幅広い種類の数学的演算を実行するグローバル {{jsxref("Math")}} オブジェクトの使い方も含みます。

+ +

数値

+ +

JavaScript では、数値はすべて 64 ビット倍精度浮動小数点数のフォーマットである IEEE 754 (すなわち、±2−1022 と ±2+1023 の間、もしくはおよそ ±10−308 と ±10+308 の間の数値、53 ビットの精度による) にしたがって実装されています。±253 − 1 までの整数は正確に表現できます。

+ +

浮動小数点数の表現に加えて、数値型は 3 つの記号的な値を持っています。 +{{jsxref("Infinity")}}、-{{jsxref("Infinity")}}、{{jsxref("NaN")}}(非数、not-a-number)です。

+ +

JavaScript に最近巨大な数値を表す {{jsxref("BigInt")}} が実装されました。 BigInt には注意事項があり、例えば、BigInt と {{jsxref("Number")}} の値は同じ演算で混ぜたり比較することができず、BigInt の値を {{jsxref("Math")}} オブジェクトで使用することもできません。

+ +

JavaScript における他のプリミティブ型との関わりについては、JavaScript のデータ型とデータ構造 もご覧ください。

+ +

4 種類の数値リテラル、10 進数、2 進数、8 進数、16 進数を使用することができます。

+ +

10 進数

+ +
1234567890
+42
+
+// ゼロを先頭に使用するときは気をつけて:
+
+0888 // 10 進数として 888 と解析される
+0777 // Strict モードでない場合 8 進数として解析される (10 進数の 511 になる)
+
+ +

10 進数リテラルはゼロ (0) から始めて、それ以降に 10 進の桁を続けることが可能ですが、0 に続くすべての数値が 8 より小さい場合、その数値は 8 進数として解析されることに注意してください。

+ +

2 進数

+ +

2 進数の構文では、先行ゼロの後に小文字または大文字の "B" を使います (0b または 0B)。0b の後の数値が 0 または 1 ではない場合、 {{jsxref("SyntaxError")}}: "Missing binary digits after 0b"(0b の後に 2 進数の桁がありません) が発生します。

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

8 進数

+ +

8 進数の構文では、先頭にゼロを使用します。0 の後の数値が 0 から 7 の範囲外の場合、数値は 10 進数として解釈されます。

+ +
var n = 0755; // 493
+var m = 0644; // 420
+
+ +

ECMAScript 5 における厳格モードでは上記の 8 進数記法を禁じています。8 進数記法は ECMAScript 5 仕様の一部ではありませんが、すべてのブラウザーで先行ゼロによる 8 進数記法をサポートしており、 0644 === 420"\045" === "%" となります。ECMAScript 2015 ではまた、先行する 0o を使う 8 進数構文をサポートしています。

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

16 進数

+ +

16 進数の構文では、先行ゼロの後に小文字または大文字の "X" を使います (0x または 0X)。0x の後の数値が範囲 (0123456789ABCDEF) 外の場合、 {{jsxref("SyntaxError")}}: "Identifier starts immediately after numeric literal" (数値リテラルの直後に識別子があります) が発生します。

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

指数表現

+ +
1E3   // 1000
+2e6   // 2000000
+0.1e2 // 10
+ +

Number オブジェクト

+ +

組み込み {{jsxref("Number")}} オブジェクトは最大値、NaN、無限大といった数値定数のプロパティを持っています。これらのプロパティの値は変更できません。下記のように使用します:

+ +
var biggestNum = Number.MAX_VALUE;
+var smallestNum = Number.MIN_VALUE;
+var infiniteNum = Number.POSITIVE_INFINITY;
+var negInfiniteNum = Number.NEGATIVE_INFINITY;
+var notANum = Number.NaN;
+
+ +

自作した Number オブジェクトのプロパティではなく、上記の定義済み Number オブジェクトのプロパティを常に参照してください。

+ +

次の表は Number オブジェクトのプロパティの要約です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number オブジェクトプロパティ
プロパティ説明
{{jsxref("Number.MAX_VALUE")}}表現可能な最大値。(±1.7976931348623157e+308)
{{jsxref("Number.MIN_VALUE")}}表現可能な最小値。(±5e-324)
{{jsxref("Number.NaN")}}非数を表す特別な値。
{{jsxref("Number.NEGATIVE_INFINITY")}}負の無限大を表す特別な値。オーバーフローした際に返されます。
{{jsxref("Number.POSITIVE_INFINITY")}}正の無限大を表す特別な値。オーバーフローした際に返されます。
{{jsxref("Number.EPSILON")}}{{jsxref("Number")}} オブジェクトで表現可能な、ある数とそれよりも大きい最小数との差分値 (計算機イプシロン)。(2.220446049250313e-16)
{{jsxref("Number.MIN_SAFE_INTEGER")}}JavaScript で正確に扱える最小の整数値。(−253 + 1, or −9007199254740991)
{{jsxref("Number.MAX_SAFE_INTEGER")}}JavaScript で正確に扱える最大の整数値。(+253 − 1, or +9007199254740991)
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Number オブジェクトメソッド
メソッド説明
{{jsxref("Number.parseFloat()")}}文字列引数を解析し、浮動小数点数を返します。
+ グローバル関数 {{jsxref("parseFloat", "parseFloat()")}} と同等。
{{jsxref("Number.parseInt()")}}文字列引数を解析し、指定された根(基数)の整数を返します。
+ グローバル関数 {{jsxref("parseInt", "parseInt()")}} と同等。
{{jsxref("Number.isFinite()")}}渡された値が有限数であるか否かを判定します。
{{jsxref("Number.isInteger()")}}渡された値が整数であるか否かを判定します。
{{jsxref("Number.isNaN()")}}渡された値が {{jsxref("Global_Objects/NaN", "NaN")}}(非数)であるか否かを判定します。原型となったグローバル関数 {{jsxref("Global_Objects/isNaN", "isNaN()")}} よりもロバストな(対応能力が強い)バージョン。
{{jsxref("Number.isSafeInteger()")}}渡された値が正確に扱える整数であるか否かを判定します。
+ +

Number オブジェクトのプロトタイプは様々なフォーマットの Number オブジェクトから情報を取得するメソッドを提供します。次表は Number.prototype のメソッドの要約です。

+ + + + + + + + + + + + + + + + + + + + + + + +
Number.prototype メソッド
メソッド説明
{{jsxref("Number.toExponential", "toExponential()")}}数値の指数表記を表す文字列を返します。
{{jsxref("Number.toFixed", "toFixed()")}}数値の固定小数点表記を表す文字列を返します。
{{jsxref("Number.toPrecision", "toPrecision()")}}特定の精度の固定小数点表記による数値を表す文字列を返します。
+ +

Math オブジェクト

+ +

組み込み {{jsxref("Math")}} オブジェクトは数学定数および数学関数のためのプロパティとメソッドを有しています。例えば、Math オブジェクトの PI プロパティは π (3.141...) の値を持ちます。以下のようにアプリケーション内で使用できます。

+ +
Math.PI
+
+ +

同様に、標準的な数学関数が Math のメソッドにあります。数学関数には、三角関数、対数、指数、およびその他の関数が含まれます。例えば、三角関数 sin を使用したい場合、下記のように記述します。

+ +
Math.sin(1.56)
+
+ +

Math のすべての三角関数メソッドはラジアンで引数を取ることに注意してください。

+ +

次表は Math オブジェクトメソッドの要約です。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Math オブジェクトメソッド
メソッド説明
{{jsxref("Math.abs", "abs()")}}絶対値。
{{jsxref("Math.sin", "sin()")}}, {{jsxref("Math.cos", "cos()")}}, {{jsxref("Math.tan", "tan()")}}標準三角関数。引数はラジアン。
{{jsxref("Math.asin", "asin()")}}, {{jsxref("Math.acos", "acos()")}}, {{jsxref("Math.atan", "atan()")}}, {{jsxref("Math.atan2", "atan2()")}}逆三角関数。戻り値はラジアン。
{{jsxref("Math.sinh", "sinh()")}}, {{jsxref("Math.cosh", "cosh()")}}, {{jsxref("Math.tanh", "tanh()")}}双曲線三角関数。引数は双曲線角度。
{{jsxref("Math.asinh", "asinh()")}}, {{jsxref("Math.acosh", "acosh()")}}, {{jsxref("Math.atanh", "atanh()")}}逆双曲線三角関数。戻り値は双曲線角度。
+

{{jsxref("Math.pow", "pow()")}}, {{jsxref("Math.exp", "exp()")}}, {{jsxref("Math.expm1", "expm1()")}}, {{jsxref("Math.log10", "log10()")}}, {{jsxref("Math.log1p", "log1p()")}}, {{jsxref("Math.log2", "log2()")}}

+
指数と対数関数。
{{jsxref("Math.floor", "floor()")}}, {{jsxref("Math.ceil", "ceil()")}}引数以下の最大の整数値、引数以上の最小の整数値を返します。
{{jsxref("Math.min", "min()")}}, {{jsxref("Math.max", "max()")}}カンマで区切られた数値リストの引数から最小値、最大値をそれぞれ返します。
{{jsxref("Math.random", "random()")}}0 から 1 の間のランダムな数値を返します。
{{jsxref("Math.round", "round()")}}, {{jsxref("Math.fround", "fround()")}}, {{jsxref("Math.trunc", "trunc()")}},丸めと切り捨て関数。
{{jsxref("Math.sqrt", "sqrt()")}}, {{jsxref("Math.cbrt", "cbrt()")}}, {{jsxref("Math.hypot", "hypot()")}}平方根、立方根、引数の二乗の和の平方根を返す。
{{jsxref("Math.sign", "sign()")}}数の符号、すなわち数が正、負またはゼロかどうかを返します。
{{jsxref("Math.clz32", "clz32()")}},
+ {{jsxref("Math.imul", "imul()")}}
32 ビットのバイナリー表現にした場合の先行ゼロの個数を返す関数。
+ 2 つの引数を C 言語のように 32 ビット乗算した結果を返す関数。
+ +

他の多くのオブジェクトとは異なり、決して独自の Math オブジェクトを生成しないでください。常にビルトイン Math オブジェクトを使用してください。

+ +

Date オブジェクト

+ +

JavaScript には日付のためのデータ型がありません。しかし、アプリケーション内で日付を取り扱うための {{jsxref("Date")}} オブジェクトとそのメソッドが利用できます。 Date オブジェクトは日付の設定、取得、操作を行う多数のメソッドを有しています。このオブジェクトはいかなるプロパティも持ちません。

+ +

JavaScript は Java と同じように日付を取り扱います。2 つの言語は同様の日付用メソッドを多く持ち、両方の言語とも、Unix タイムスタンプが 1970 年 1 月 1 日 00:00:00 からの秒の数値であるのと同様に、1970 年 1 月 1 日 00:00:00 からのミリ秒の数値で日付を格納しています。

+ +

Date オブジェクトの設定可能範囲は 1970 年 1 月 1 日 UTC 時間 に対し -100,000,000 日から 100,000,000 日までです。

+ +

Date オブジェクトは次のように生成します。

+ +
var dateObjectName = new Date([parameters]);
+
+ +

ここで dateObjectName は生成される Date オブジェクトの名前です。新しいオブジェクトか、あるいは既存のオブジェクトのプロパティにすることができます。

+ +

new キーワードなしで Date を呼び出すと、単に現在の日付と時間を文字列表現にしたものを返します。

+ +

上記構文の parameters は以下のいずれかになります。

+ + + +

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

+ +

日時を扱う Date オブジェクトのメソッドは下記のカテゴリに分類されます:

+ + + +

"get" と "set" メソッドを使用して、秒、分、時、日、曜日、月、年をそれぞれ取得、設定できます。曜日を返す getDay メソッドはありますが、対応する setDay メソッドはありません。というのも、曜日は自動的に設定されるからです。これらのメソッドはそれぞれの値を表すのに下記の整数値を使用します:

+ + + +

例えば、次の日付を定義してみます。

+ +
var Xmas95 = new Date('December 25, 1995');
+
+ +

すると、Xmas95.getMonth() は 11 を返し、Xmas95.getFullYear() は 1995 を返します。

+ +

getTimesetTime メソッドは日付を比較するのに便利です。getTime メソッドは Date オブジェクトに対して January 1, 1970, 00:00:00 からのミリ秒の数値を返します。

+ +

例えば、次のコードでは今年に残された日数を表示します。:

+ +
var today = new Date();
+var endYear = new Date(1995, 11, 31, 23, 59, 59, 999); // 月日を設定
+endYear.setFullYear(today.getFullYear()); // 今年の年を設定
+var msPerDay = 24 * 60 * 60 * 1000; // 一日をミリ秒に換算
+var daysLeft = (endYear.getTime() - today.getTime()) / msPerDay;
+var daysLeft = Math.round(daysLeft); // 今年の残り日数を返す
+
+ +

この例では、今日の日時を含む today と名付けられた Date オブジェクトを生成します。それから、endYear と名付けられた Date オブジェクトを生成し、年を今年に設定します。そして、1日あたりのミリ秒値を使って、todayendYear 間の日数を計算する際に getTime を使用し、そして日数に丸めます。

+ +

parse メソッドは日付文字列から既存の Date オブジェクトに値を割り当てるのに便利です。例えば、次のコードは parsesetTime を使用し、日付の値を IPOdate オブジェクトに割り当てます:

+ +
var IPOdate = new Date();
+IPOdate.setTime(Date.parse('Aug 9, 1995'));
+
+ +

+ +

次の例では、JSClock() 関数がデジタル時計の形式で時刻を返します。

+ +
function JSClock() {
+  var time = new Date();
+  var hour = time.getHours();
+  var minute = time.getMinutes();
+  var second = time.getSeconds();
+  var temp = '' + ((hour > 12) ? hour - 12 : hour);
+  if (hour == 0)
+    temp = '12';
+  temp += ((minute < 10) ? ':0' : ':') + minute;
+  temp += ((second < 10) ? ':0' : ':') + second;
+  temp += (hour >= 12) ? ' P.M.' : ' A.M.';
+  return temp;
+}
+
+ +

JSClock 関数は、はじめに time という名前の新しい Date オブジェクトを生成します。引数が与えられていないため、time は現在の日付と時刻で生成されます。次に、getHours および getMinutesgetSeconds メソッドを呼び出して、現在の時、分、秒を hourminutesecond に代入します。

+ +

続く 4 つの式は、時刻を基にした文字列値を組み立てます。最初の式は temp 変数を生成し、それに条件式を用いて値を代入します。hour が 12 よりも大きい場合は (hour - 12)、そうでない場合は単に hour を代入します。hour が 0 の場合は 12 になります。

+ +

次の式は、minute 値を temp に追加します。minute の値が 10 よりも小さい場合、条件式により先行ゼロの文字が追加されます。そうでない場合は区切りのコロン文字を追加します。そして秒の値を同じ方法で temp に追加します。

+ +

最後の条件式は、hour が 12 以上の場合、"P.M." を temp に追加します。そうでない場合は "A.M." を temp に追加します。

+ +

{{PreviousNext("Web/JavaScript/Guide/Expressions_and_Operators", "Web/JavaScript/Guide/Text_formatting")}}

diff --git a/files/ja/web/javascript/guide/object_manipulation_statements/index.html b/files/ja/web/javascript/guide/object_manipulation_statements/index.html new file mode 100644 index 0000000000..ddf781e031 --- /dev/null +++ b/files/ja/web/javascript/guide/object_manipulation_statements/index.html @@ -0,0 +1,51 @@ +--- +title: Object Manipulation Statements +slug: Web/JavaScript/Guide/Object_Manipulation_Statements +--- +

オブジェクト操作文

+

JavaScript はオブジェクトの操作に for...infor each...in および with 文を使用します。

+

for...in 文

+

for...in 文は指定した変数をオブジェクトの全プロパティに対して反復します。それぞれのプロパティに対して JavaScript は指定した文を実行します。for...in 文は次のように使用します。

+
for (variable in object) {
+   statements
+}
+
+


+ 次の関数は、あるオブジェクトとそのオブジェクトの名前を引数にとります。そしてそのオブジェクトの全プロパティに対して反復し、プロパティ名とその値のリストにした文字列を返します。

+
function dump_props(obj, obj_name) {
+   var result = "";
+   for (var i in obj) {
+      result += obj_name + "." + i + " = " + obj[i] + "<br>";
+   }
+   result += "<hr>";
+   return result;
+}
+
+

make および model というプロパティを持つ car というオブジェクトでは次のような結果が得られます。

+
car.make = Ford
+car.model = Mustang
+
+

配列
+ Array の要素に対して反復する方法としてこれを用いることは魅力的かもしれませんが、for...in 文はその配列の要素に加えてユーザ定義プロパティに対して繰り返すため、独自のプロパティやメソッドを追加するなどして Array オブジェクトに変更を加えると for...in 文は数値のインデックスに加えてユーザ定義プロパティの名前を返します。したがって、配列に対して反復したいときには数値のインデックスを用いた従来の for ループを使用したほうがいいでしょう。

+

for each...in 文

+

for each...inJavaScript 1.6 で導入されるループ文です。これは for...in に似ていますが、オブジェクトのプロパティの名前ではなく、プロパティの値に対して反復します。

+

with 文

+

with 文はデフォルトのオブジェクトについて文のセットを実行します。JavaScript はその文のセットにおいて非修飾名を検索し、その名前がデフォルトのオブジェクトのプロパティであるかを決定します。非修飾名がプロパティにマッチすると、そのプロパティがその文で使われます。そうでない場合はローカル変数かグローバル変数が使われます。

+

with 文は次のように使用します。

+
with (object) {
+   statements
+}
+
+


+ 次の with 文では Math オブジェクトがデフォルトのオブジェクトに指定されています。with 文内の文は PI プロパティや cos および sin メソッドを参照していますが、オブジェクトは指定していません。JavaScript はこれらの参照は Math オブジェクトへのものであると想定します。

+
var a, x, y;
+var r = 10;
+with (Math) {
+   a = PI * r * r;
+   x = r * cos(PI);
+   y = r * sin(PI/2);
+}
+
+

注意:with 文を使うことでプログラムをより簡潔にすることができますが、with の不適切な使用はプログラムを大幅にスローダウンさせることに繋がります。Core JavaScript 1.5 Reference:Statements:with を参照してください。

+ +

{{ PreviousNext("JavaScript/Guide/Loop_Statements/continue_Statement", "JavaScript/Guide/Comments") }}

diff --git a/files/ja/web/javascript/guide/objects_and_properties/index.html b/files/ja/web/javascript/guide/objects_and_properties/index.html new file mode 100644 index 0000000000..f2679c1d00 --- /dev/null +++ b/files/ja/web/javascript/guide/objects_and_properties/index.html @@ -0,0 +1,32 @@ +--- +title: オブジェクトとプロパティ +slug: Web/JavaScript/Guide/Objects_and_Properties +--- +

オブジェクトとプロパティ

+

JavaScript のオブジェクトには、それに結びつけられたプロパティがあります。簡単な記法でオブジェクトのプロパティにアクセスできます。

+
objectName.propertyName
+
+

オブジェクト名もプロパティ名も大文字と小文字を区別します。プロパティの定義は、そのプロパティに値を代入することで行います。例えば、myCar という名前のオブジェクトがあるとします(今回はオブジェクトが既に存在していると仮定)。次のようにして、そのオブジェクトに makemodelyear という名前のプロパティをそれぞれ作成することができます。

+
myCar.make = "Ford";
+myCar.model = "Mustang";
+myCar.year = 1969;
+
+

配列はある単一の変数名に結びつけられた値の順序集合です。JavaScript におけるプロパティと配列は密接に関連しています。事実、それらは同一のデータ構造への異なるインタフェースなのです。そのため、例えば次のようにして myCar オブジェクトのプロパティにアクセスすることができます。

+
myCar["make"] = "Ford";
+myCar["model"] = "Mustang";
+myCar["year"] = 1969;
+
+

この手の配列は連想配列として知られています。それぞれのインデックスの要素が文字列にも結びつけられているからです。これがどう動作するかというと、次の関数は引数としてオブジェクトとそのオブジェクトの名前を渡すとオブジェクトのプロパティを表示します。

+
function show_props(obj, obj_name) {
+   var result = "";
+   for (var i in obj)
+      result += obj_name + "." + i + " = " + obj[i] + "\n";
+   return result;
+}
+
+

関数 show_props(myCar, "myCar") を呼び出すと以下の結果が返されます。

+
myCar.make = Ford
+myCar.model = Mustang
+myCar.year = 1969
+
+

{{ PreviousNext("JavaScript/Guide/Predefined_Functions/escape_and_unescape_Functions", "JavaScript/Guide/Creating_New_Objects") }}

diff --git a/files/ja/web/javascript/guide/obsolete_pages/index.html b/files/ja/web/javascript/guide/obsolete_pages/index.html new file mode 100644 index 0000000000..7594f13fd9 --- /dev/null +++ b/files/ja/web/javascript/guide/obsolete_pages/index.html @@ -0,0 +1,9 @@ +--- +title: Obsolete Pages +slug: Web/JavaScript/Guide/Obsolete_Pages +translation_of: Web/JavaScript/Guide +--- +

This is a list of pages that have been merged into chapters (in alphabetical order):

+ + +
{{tree}}
diff --git a/files/ja/web/javascript/guide/obsolete_pages/predefined_core_objects/function_object/index.html b/files/ja/web/javascript/guide/obsolete_pages/predefined_core_objects/function_object/index.html new file mode 100644 index 0000000000..79c30b670a --- /dev/null +++ b/files/ja/web/javascript/guide/obsolete_pages/predefined_core_objects/function_object/index.html @@ -0,0 +1,44 @@ +--- +title: Function Object +slug: Web/JavaScript/Guide/Obsolete_Pages/Predefined_Core_Objects/Function_Object +--- +

 

+

Function オブジェクト

+

定義済みの Function オブジェクトは、関数としてコンパイルさせたい JavaScript コードの文字列を指定します。

+

Function オブジェクトを作成するには次のようにします。

+
functionObjectName = new Function ([arg1, arg2, ... argn], functionBody)
+
+

functionObjectName は変数名または既存のオブジェクトのプロパティ名です。オブジェクトに小文字のイベントハンドラ名を続けて、window.onerror のようにして指定することもできます。

+

arg1, arg2, ... argn は関数が仮引数名として使用する引数です。それぞれが JavaScript の識別子として妥当な文字列である必要があります。例えば、"x" や "theForm" などです。

+

functionBody は関数の本体としてコンパイルさせたい JavaScript コードを表す文字列です。

+

Function オブジェクトはそれが使用されるたびに評価されます。これは関数を宣言し、それをコード内で呼び出す方法よりも非効率的です。宣言された関数はコンパイルされるからです。

+

ここで説明した関数の定義方法に加えて、function 文と関数式を用いることもできます。詳しくは コア JavaScript 1.5 リファレンス を参照してください。

+

次のコードは関数を変数 setBGColor に代入します。この関数は開いている文書の背景色をセットします。

+
var setBGColor = new Function("document.bgColor='antiquewhite'")
+
+

Function オブジェクトを呼び出すには、それがあたかも関数であるかのように変数名を指定すればいいのです。次のコードは setBGColor 変数で指定された関数を実行します。

+
var colorChoice="antiquewhite"
+if (colorChoice=="antiquewhite") {setBGColor()}
+
+

次のどちらかの方法を使用することでイベントハンドラに関数を代入することができます。

+
1. document.form1.colorButton.onclick=setBGColor
+2. <INPUT NAME="colorButton" TYPE="button"
+      VALUE="Change background color"
+      onClick="setBGColor()">
+
+

上記の変数 setBGColor を作成することは次の関数を宣言することと同じようなことです。

+
function setBGColor() {
+   document.bgColor='antiquewhite'
+}
+
+

関数を変数に代入することは関数を宣言することと似ていますが、異なる点もあります。

+ +

関数を関数の中に入れ子にすることができます。内側の関数は外側の関数に対してプライベートになります。

+ +

{{ PreviousNext("Core_JavaScript_1.5_Guide:Predefined_Core_Objects:Date_Object", "Core_JavaScript_1.5_Guide:Predefined_Core_Objects:Math_Object") }}

diff --git a/files/ja/web/javascript/guide/operators/arithmetic_operators/index.html b/files/ja/web/javascript/guide/operators/arithmetic_operators/index.html new file mode 100644 index 0000000000..4aa9662292 --- /dev/null +++ b/files/ja/web/javascript/guide/operators/arithmetic_operators/index.html @@ -0,0 +1,47 @@ +--- +title: 算術演算子 +slug: Web/JavaScript/Guide/Operators/Arithmetic_Operators +--- +

算術演算子

+

算術演算子は、そのオペランドに数値(リテラルか変数)をとり、1 つの数値を返します。標準的な算術演算子は、加算 (+)、減算 (-)、乗算 (*)、除算 (/) です。これらの演算子は他のほとんどのプログラミング言語と同じように機能しますが、そのときの数値は、浮動小数点数として扱われます(0 で除算した結果は、NaN になることにも注意してください)。

+
1 / 2 // JavaScript では 0.5 を返す
+1 / 2 // Java では 0 を返す(どちらの数も浮動小数点数として明記されていない)
+
+1.0 / 2.0  // JavaScript でも Java でも 0.5 を返す
+
+

さらに、JavaScript では以下の表で示された算術演算子も使用できます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子説明
%
+ (モジュロ)
2 項演算子。2 つのオペランドで除算したときの整数の余りを返す。12 % 5 は 2 を返す。
++
+ (インクリメント)
単項演算子。オペランドに 1 を加える。前置演算子 (++x) を使った場合、オペランドに 1 を加えた後にその値を返す。後置演算子 (x++) を使った場合、オペランドに 1 を加える前にその値を返す。x が 3 のとき、++xx に 4 をセットし、4 を返す。一方、x++x に 4 をセットし、3 を返す。
--
+ (デクリメント)
単項演算子。オペランドから 1 を引く。戻り値はインクリメント演算子のものと同様。x が 3 のとき、--xx に 2 をセットし、2 を返す。一方、x--x に 2 をセットし、3 を返す。
-
+ (符号反転)
単項演算子。オペランドの符号を反転してその値を返す。x が 3 のとき、-x は -3 を返す。
+

表 3.4:算術演算子

+

{{ PreviousNext("JavaScript/Guide/Operators/Comparison_Operators", "JavaScript/Guide/Operators/Bitwise_Operators") }}

diff --git a/files/ja/web/javascript/guide/operators/assignment_operators/index.html b/files/ja/web/javascript/guide/operators/assignment_operators/index.html new file mode 100644 index 0000000000..88a0b0beb7 --- /dev/null +++ b/files/ja/web/javascript/guide/operators/assignment_operators/index.html @@ -0,0 +1,61 @@ +--- +title: 代入演算子 +slug: Web/JavaScript/Guide/Operators/Assignment_Operators +--- +

代入演算子

+

代入演算子は、右のオペランドの値に基づいた値を左のオペランドに代入します。基本的な代入演算子はイコール (=) ですが、これは右のオペランドの値を左のオペランドに代入します。すなわち、x = y では y の値を x に代入します。

+

他の代入演算子は標準的な演算をするための短縮表記があります。次の表でそれを示します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
短縮表記した演算子意味
x += yx = x + y
x -= yx = x - y
x *= yx = x * y
x /= yx = x / y
x %= yx = x % y
x <<= yx = x << y
x >>= yx = x >> y
x >>>= yx = x >>> y
x &= yx = x & y
x ^= yx = x ^ y
x |= yx = x | y
+

表 3.2:代入演算子

+

{{ PreviousNext("JavaScript/Guide/Operators", "JavaScript/Guide/Operators/Comparison_Operators") }}

diff --git a/files/ja/web/javascript/guide/operators/comparison_operators/index.html b/files/ja/web/javascript/guide/operators/comparison_operators/index.html new file mode 100644 index 0000000000..182802bb5a --- /dev/null +++ b/files/ja/web/javascript/guide/operators/comparison_operators/index.html @@ -0,0 +1,67 @@ +--- +title: 比較演算子 +slug: Web/JavaScript/Guide/Operators/Comparison_Operators +--- +

比較演算子

+

This seems to me kind of poorly explained, mostly the diference betwen "==" and "==="... 比較演算子は、オペランドを比較し、比較結果に基づいた論理値を返します。オペランドには数値、文字列、論理値、オブジェクトが使用できます。文字列は、Unicode 値を用いて標準的な辞書順に基づいて比較されます。ほとんどの場合、2 つのオペランドが異なる型ならば JavaScript はそのオペランドを比較に適した型に変換しようとします(このルールの唯一の例外は === および !== であり、これらは厳密に等値か否かを判断し、等値性をチェックする前にオペランドを適合する型に変換するということはありません)。これは一般に数値の比較が実行されることになります。次の表では比較演算子について説明します。次のコードで考えます。

+
var var1 = 3, var2 = 4;
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
演算子説明true を返す例
等しい (==)オペランドが等しい場合に true を返す。3 == var1
+

"3" == var1

+ 3 == '3'
等しくない (!=)オペランドが等しくない場合に true を返す。var1 != 4
+ var2 != "3"
厳密に等しい (===)オペランドが等しく、かつ同じ型である場合に true を返す。3 === var1
厳密には等しくない (!==)オペランドが等しくなく、かつ/または同じ型でない場合に true を返す。var1 !== "3"
+ 3 !== '3'
より大きい (>)左のオペランドが右のオペランドよりも大きい場合に true を返す。var2 > var1
+ "12" > 2
以上 (>=)左のオペランドが右のオペランド以上である場合に true を返す。var2 >= var1
+ var1 >= 3
より小さい (<)左のオペランドが右のオペランドよりも小さい場合に true を返す。var1 < var2
+ "12" < "2"
以下 (<=)左のオペランドが右のオペランド以下である場合に true を返す。var1 <= var2
+ var2 <= 5
+

表 3.3:比較演算子

+

{{ PreviousNext("JavaScript/Guide/Operators/Assignment_Operators", "JavaScript/Guide/Operators/Arithmetic_Operators")}}

diff --git a/files/ja/web/javascript/guide/operators/logical_operators/index.html b/files/ja/web/javascript/guide/operators/logical_operators/index.html new file mode 100644 index 0000000000..fa6fa08068 --- /dev/null +++ b/files/ja/web/javascript/guide/operators/logical_operators/index.html @@ -0,0 +1,63 @@ +--- +title: 論理演算子 +slug: Web/JavaScript/Guide/Operators/Logical_Operators +--- +

論理演算子

+

論理演算子では基本的に真偽(論理)値を用います。そのような値があると真偽値を返します。しかし、&& および || 演算子は実際には指定されたオペランドの一方の値を返します。そのため、非真偽値とともに論理演算子が使われると非真偽値を返します。論理演算子について次の表で説明します。

+ + + + + + + + + + + + + + + + + + + + + + + +
演算子使用法説明
&&expr1 && expr2(論理 AND)expr1 を false と見ることができる場合は expr1 を返す。そうでない場合は expr2 を返す。したがって、真偽値が使われた場合、両オペランドが true の場合は && は true を返し、そうでない場合は false を返す。
||expr1 || expr2(論理 OR)expr1 を true と見ることができる場合は expr1 を返す。そうでない場合は expr2 を返す。したがって、真偽値が使われた場合、どちらかのオペランドが true の場合は || は true を返し、両方とも false の場合は false を返す。
!!expr(論理 NOT)オペランドを true と見ることができる場合は false を返す。そうでない場合は true を返す。
+

表 3.7:論理演算子

+

false と見ることができる式とは、null、0、空文字列 ("")、または undefined に評価される式のことです。

+

以下のコードで &&(論理 AND)演算子の例を示します。

+
a1=true && true       // t && t は true を返す
+a2=true && false      // t && f は false を返す
+a3=false && true      // f && t は false を返す
+a4=false && (3 == 4)  // f && f は false を返す
+a5="Cat" && "Dog"     // t && t は Dog を返す
+a6=false && "Cat"     // f && t は false を返す
+a7="Cat" && false     // t && f は false を返す
+
+

以下のコードで ||(論理 OR)演算子の例を示します。

+
o1=true || true       // t || t は true を返す
+o2=false || true      // f || t は true を返す
+o3=true || false      // t || f は true を返す
+o4=false || (3 == 4)  // f || f は false を返す
+o5="Cat" || "Dog"     // t || t は Cat を返す
+o6=false || "Cat"     // f || t は Cat を返す
+o7="Cat" || false     // t || f は Cat を返す
+
+

以下のコードで !(論理 NOT)演算子の例を示します。

+
n1=!true              // !t は false を返す
+n2=!false             // !f は true を返す
+n3=!"Cat"             // !t は false を返す
+
+

ショートサーキット評価

+

論理式は左から右に評価されるため、以下のルールを用いることで「ショートサーキット」評価ができるようになっています。

+ +

論理のルールはこれらの評価が常に正確であることを保証しています。上記の式の anything の部分は評価されないため、何らかの副作用が生じないように注意してください。

+

{{ PreviousNext("JavaScript/Guide/Operators/Bitwise_Operators", "JavaScript/Guide/Operators/String_Operators") }}

diff --git a/files/ja/web/javascript/guide/operators/special_operators/index.html b/files/ja/web/javascript/guide/operators/special_operators/index.html new file mode 100644 index 0000000000..226faf2b3c --- /dev/null +++ b/files/ja/web/javascript/guide/operators/special_operators/index.html @@ -0,0 +1,197 @@ +--- +title: 特殊演算子 +slug: Web/JavaScript/Guide/Operators/Special_Operators +--- +

特殊演算子

+

JavaScript は以下の特殊演算子があります。

+ +

条件演算子

+

条件演算子は JavaScript では唯一の 3 つのオペランドをとる演算子です。演算子は条件に基づいて 2 つの値のうち、1 つを選択します。構文は次のとおりです。

+
condition ? val1 : val2
+
+

condition が true の場合、演算子は val1 の値を選択します。そうでない場合は val2 の値を選択します。標準的な演算子が使用できる場所でならどこででも条件演算子を使用することができます。

+

例えば、

+
status = (age >= 18) ? "adult" : "minor"
+
+

この文では、age が 18 以上の場合 "adult" という値を変数 status に代入します。そうでない場合は "minor" という値を status に代入します。

+

コンマ演算子

+

コンマ演算子 (,) は単に両方のオペランドを評価し、第 2 のオペランドの値を返します。この演算子は主に for ループ内で使用されます。このことでループのたびに複数の変数を更新できるようになります。

+

例えば、a が一辺が 10 要素の 2 次元配列のとき、以下のコードではコンマ演算子を用いることで 2 変数を同時にインクリメントしています。このコードでは配列の対角成分の値を出力します。

+
for (var i=0, j=9; i <= 9; i++, j--)
+   document.writeln("a["+i+"]["+j+"]= " + a[i][j])
+
+

delete

+

delete 演算子はオブジェクトやオブジェクトのプロパティ、配列の指定されたインデックスの要素を削除します。構文は以下のとおりです。

+
delete objectName
+delete objectName.property
+delete objectName[index]
+delete property // with 文内でのみ有効
+
+

ここで、objectName はオブジェクトの名前を、property は既存のプロパティを、index は配列の要素の位置を表す整数をそれぞれ表しています。

+

4 番目の形式は with 文内でのみ有効で、これはあるオブジェクトからプロパティを削除します。

+

delete 演算子を使うことで暗黙的に宣言された変数を削除することができますが、var 文を用いて宣言された変数は削除できません。

+

delete 演算子が成功すると、そのプロパティや要素には undefined がセットされます。また、演算が可能な場合は delete 演算子は true を返します。演算が不可能な場合は false を返します。

+
x=42
+var y= 43
+myobj=new Number()
+myobj.h=4      // プロパティ h を作成
+delete x       // true を返す(暗黙的に宣言されているならば削除可能)
+delete y       // false を返す(var 付きで宣言されているなら削除不可能)
+delete Math.PI // false を返す(定義済みプロパティは削除不可能)
+delete myobj.h // true を返す(ユーザ定義プロパティは削除可能)
+delete myobj   // true を返す(暗黙的に宣言されているならば削除可能)
+
+

配列要素の削除
+ 配列要素を削除したとき、配列の長さには影響を及ぼしません。例えば a{{ mediawiki.external(3) }} を削除したとき、a{{ mediawiki.external(4) }} は依然 a{{ mediawiki.external(4) }} のままで、a{{ mediawiki.external(3) }} は undefined になります。

+

delete 演算子で配列要素を除去すると、もうその要素はその配列からなくなります。次の例では tree{{ mediawiki.external(3) }} は delete によって除去されます。

+
trees=new Array("redwood","bay","cedar","oak","maple")
+delete trees[3]
+if (3 in trees) {
+   // ここは実行されない
+}
+
+

配列要素は存在させたいが、値は未定義にしたいという場合は、delete 演算子の代わりに undefined キーワードを使用してください。次の例では trees{{ mediawiki.external(3) }} には undefined という値が代入されますが、その配列要素は存在したままになります。

+
trees=new Array("redwood","bay","cedar","oak","maple")
+trees[3]=undefined
+if (3 in trees) {
+   // ここは実行される
+}
+
+

in

+

in 演算子は、指定されたプロパティが指定されたオブジェクトにある場合に true を返します。構文は以下のとおりです。

+
propNameOrNumber in objectName
+
+

ここで、propNameOrNumber はプロパティ名か配列のインデックスを表す文字列式または数値式を、objectName はオブジェクトの名前をそれぞれ表しています。

+

次の例では in 演算子の使用法を示します。

+
// 配列
+trees=new Array("redwood","bay","cedar","oak","maple")
+0 in trees        // true を返す
+3 in trees        // true を返す
+6 in trees        // false を返す
+"bay" in trees    // false を返す(インデックスの指す値ではなく、
+                  // インデックスの数字を指定しなければならない)
+"length" in trees // true を返す(length は Array のプロパティ)
+
+// 定義済みオブジェクト
+"PI" in Math          // true を返す
+myString=new String("coral")
+"length" in myString  // true を返す
+
+// ユーザ定義オブジェクト
+mycar = {make:"Honda",model:"Accord",year:1998}
+"make" in mycar  // true を返す
+"model" in mycar // true を返す
+
+

instanceof

+

instanceof 演算子は、指定されたオブジェクトが指定されたオブジェクトの種類である場合に true を返します。構文は次のとおりです。

+
objectName instanceof objectType
+
+

ここで、objectNameobjectType と比較するオブジェクトの名前を、objectTypeDateArray のようなオブジェクトの種類をそれぞれ表しています。

+

実行時にオブジェクトの種類を確認する必要があるときは instanceof を使用してください。例えば、例外を受け取るとき、投げられた例外の種類によって別々の例外を扱うコードに分岐させることができます。

+

例えば、次のコードでは instanceof を使用することで theDayDate オブジェクトであるかどうかを決定しています。theDayDate オブジェクトなので if 文の中の文は実行されます。

+
theDay=new Date(1995, 12, 17)
+if (theDay instanceof Date) {
+   // 実行される文
+}
+
+

new

+

new 演算子は、ユーザ定義オブジェクトや、ArrayBooleanDateFunctionImageNumberObjectOptionRegExpString といった定義済みオブジェクトのインスタンスを作成するのに使用します。サーバでは DbPoolLockFileSendMail といったオブジェクトも使用できます。new の使用法は以下のとおりです。

+
objectName = new objectType ( param1 [,param2] ...[,paramN] )
+
+

オブジェクト初期化子を使用してもオブジェクトを作成することができます。オブジェクト初期化子の使用 にて説明しています。

+

詳しくはコア JavaScript リファレンスの new 演算子 のページを参照してください。

+

this

+

this キーワードを使うことでカレントオブジェクトを参照することができます。一般に this はあるメソッド内でそのメソッドを呼び出したオブジェクトを参照します。使用法は以下のとおりです。

+
this[.propertyName]
+
+

例 1
+ あるオブジェクトの value プロパティの妥当性を確認する validate という関数を想定します。関数にはそのオブジェクトと、上限および下限の値を渡します。

+
function validate(obj, lowval, hival) {
+   if ((obj.value < lowval) || (obj.value > hival))
+      alert("Invalid Value!")
+}
+
+

各フォーム要素の onChange イベントハンドラにおいて validate を呼び出します。this を使うことでフォーム要素を渡すことができます。次の例をご覧ください。

+
<B>Enter a number between 18 and 99:</B>
+<INPUT TYPE = "text" NAME = "age" SIZE = 3
+   onChange="validate(this, 18, 99)">
+
+

例 2
+ form プロパティと組み合わせると this でカレントオブジェクトの親のフォームを参照できます。次の例では、myForm というフォームに Text オブジェクトとボタンが格納されています。ユーザがボタンをクリックすると、Text オブジェクトの値にフォーム名がセットされます。ボタンの onClick イベントハンドラは this.form を利用して親のフォームである myForm を参照します。

+
<FORM NAME="myForm">
+Form name:<INPUT TYPE="text" NAME="text1" VALUE="Beluga">
+<P>
+<INPUT NAME="button1" TYPE="button" VALUE="Show Form Name"
+   onClick="this.form.text1.value=this.form.name">
+</FORM>
+
+

typeof

+

typeof 演算子は次の方法のうち、どちらかの方法で使用します。

+
1. typeof operand
+2. typeof (operand)
+
+

typeof 演算子は、未評価のオペランドの型を指す文字列を返します。operand は返される型を調べる対象となる文字列、変数、キーワード、オブジェクトです。括弧はあってもなくてもかまいません。

+

以下の変数を定義することを想定します。

+
var myFun = new Function("5+2")
+var shape="round"
+var size=1
+var today=new Date()
+
+

typeof 演算子はこれらの変数に対して以下の結果を返します。

+
typeof myFun is function
+typeof shape is string
+typeof size is number
+typeof today is object
+typeof dontExist is undefined
+
+

truenull というキーワードに対して、typeof 演算子は以下の結果を返します。

+
typeof true is boolean
+typeof null is object
+
+

数値や文字列に対して、typeof 演算子は以下の結果を返します。

+
typeof 62 is number
+typeof 'Hello world' is string
+
+

プロパティ値に対して、typeof 演算子はプロパティ値の型を返します。

+
typeof document.lastModified is string
+typeof window.length is number
+typeof Math.LN2 is number
+
+

メソッドや関数に対して、typeof 演算子は以下の結果を返します。

+
typeof blur is function
+typeof eval is function
+typeof parseInt is function
+typeof shape.split is function
+
+

定義済みオブジェクトに対して、typeof 演算子は以下の結果を返します。

+
typeof Date is function
+typeof Function is function
+typeof Math is function
+typeof Option is function
+typeof String is function
+
+

void

+

void 演算子は次の方法のうち、どちらかの方法で使用します。

+
1. void (expression)
+2. void expression
+
+

void 演算子は値を返さずに評価する式を指定します。expression は評価する JavaScript の式です。式の周りの括弧はあってもなくてもかまいませんが、使用したほうが見た目はいいです。

+

void 演算子を使用することで式をハイパーテキストリンクとして指定することができます。式は評価されますが、開いている文書の代わりに読み込まれるということはありません。

+

以下のコードはユーザがクリックしても何も起こらないハイパーテキストリンクを作成します。ユーザがリンクをクリックすると void(0) は undefined に評価され、JavaScript としては影響を及ぼしません。

+
<A HREF="javascript:void(0)">Click here to do nothing</A>
+
+

以下のコードはユーザがクリックするとフォームが送信されるハイパーテキストリンクを作成します。

+
<A HREF="javascript:void(document.form.submit())">
+Click here to submit</A>
+
+

{{ PreviousNext("JavaScript/Guide/Operators/String_Operators", "JavaScript/Guide/Creating_a_Regular_Expression") }}

diff --git a/files/ja/web/javascript/guide/operators/string_operators/index.html b/files/ja/web/javascript/guide/operators/string_operators/index.html new file mode 100644 index 0000000000..41bf8bbc44 --- /dev/null +++ b/files/ja/web/javascript/guide/operators/string_operators/index.html @@ -0,0 +1,8 @@ +--- +title: 文字列演算子 +slug: Web/JavaScript/Guide/Operators/String_Operators +--- +

文字列演算子

+

比較演算子は文字列に使用できますが、これに加えて 2 つの文字列を結合する結合演算子 (+) も使用できます。これは 2 つのオペランドの文字列を結合した文字列を返します。例えば、"my " + "string""my string" という文字列を返します。

+

短縮表記した代入演算子 += も文字列の結合に使用できます。例えば、変数 mystring に "alpha" という値が格納されているとき、式 mystring += "bet" の評価結果は "alphabet" となり、この値を mystring に代入します。

+

{{ PreviousNext("JavaScript/Guide/Operators/Logical_Operators", "JavaScript/Guide/Operators/Special_Operators") }}

diff --git a/files/ja/web/javascript/guide/predefined_functions/escape_and_unescape_functions/index.html b/files/ja/web/javascript/guide/predefined_functions/escape_and_unescape_functions/index.html new file mode 100644 index 0000000000..aecb8a81f1 --- /dev/null +++ b/files/ja/web/javascript/guide/predefined_functions/escape_and_unescape_functions/index.html @@ -0,0 +1,14 @@ +--- +title: escape 関数と unescape 関数 +slug: Web/JavaScript/Guide/Predefined_Functions/escape_and_unescape_Functions +--- +
+

escape および unescape 関数

+

escape および unescape 関数は文字列をエンコードしたりデコードしたりします。escape 関数は ISO Latin 文字セットで表された引数の 16 進エンコーディングを返します。unescape は指定した 16 進エンコーディングの値に対する ASCII 文字列を返します。

+

これらの関数の構文は以下のとおりです。

+
escape(string)
+unescape(string)
+
+

これらの関数は主にサーバサイド JavaScript で URL 中の名前と値のペアのエンコードやデコードに使用されます。

+ escape および unescape 関数は 非 ASCII 文字に対しては正しく機能せず、廃止予定になっています。JavaScript 1.5 以降では encodeURIdecodeURIencodeURIComponent および decodeURIComponent を使用してください。
+

{{ PreviousNext("JavaScript/Guide/Predefined_Functions/Number_and_String_Functions", "JavaScript/Guide/Objects_and_Properties") }}

diff --git a/files/ja/web/javascript/guide/predefined_functions/eval_function/index.html b/files/ja/web/javascript/guide/predefined_functions/eval_function/index.html new file mode 100644 index 0000000000..3945955e86 --- /dev/null +++ b/files/ja/web/javascript/guide/predefined_functions/eval_function/index.html @@ -0,0 +1,12 @@ +--- +title: eval 関数 +slug: Web/JavaScript/Guide/Predefined_Functions/eval_Function +--- +
+

eval 関数

+

eval 関数は JavaScript のコードの文字列を特定のオブジェクトを参照することなく評価します。eval の構文は次のとおりです。

+
eval(expr)
+
+

ここで expr は評価される文字列です。

+ 文字列が式を表している場合は eval はその式を評価します。また、1 つ以上の JavaScript の文を表している場合は eval はその式を実行します。eval のコードのスコープは呼び出し元コードのスコープと同じです。演算式を評価するために eval を呼び出さないでください。JavaScript は自動的に演算式を評価します。
+

{{ PreviousNext("JavaScript/Guide/Predefined_Functions", "JavaScript/Guide/Predefined_Functions/isFinite_Function") }}

diff --git a/files/ja/web/javascript/guide/predefined_functions/index.html b/files/ja/web/javascript/guide/predefined_functions/index.html new file mode 100644 index 0000000000..758c6f22a0 --- /dev/null +++ b/files/ja/web/javascript/guide/predefined_functions/index.html @@ -0,0 +1,17 @@ +--- +title: 定義済み関数 +slug: Web/JavaScript/Guide/Predefined_Functions +--- +
+

定義済み関数

+

JavaScript にはトップレベルの定義済み関数がいくつかあります。

+ +
+

{{ PreviousNext("JavaScript/Guide/Using_the_arguments_object", "JavaScript/Guide/Predefined_Functions/eval_Function") }}

diff --git a/files/ja/web/javascript/guide/regular_expressions/assertions/index.html b/files/ja/web/javascript/guide/regular_expressions/assertions/index.html new file mode 100644 index 0000000000..e92e05b312 --- /dev/null +++ b/files/ja/web/javascript/guide/regular_expressions/assertions/index.html @@ -0,0 +1,246 @@ +--- +title: 言明 +slug: Web/JavaScript/Guide/Regular_Expressions/Assertions +tags: + - Assertions + - JavaScript + - Reference + - Regular Expressions + - regex +translation_of: Web/JavaScript/Guide/Regular_Expressions/Assertions +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

言明には、 行や単語の始まり・終わりを示す、境界や、(先読み、後読み、条件式を含む)何らかの方法でマッチが可能なことを示す、その他のパターンが含まれます。

+ +

種類

+ +

境界型の言明

+ + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
^ +

入力の先頭にマッチします。複数行フラグが true にセットされている場合は、改行文字の直後にもマッチします。例えば /^A/ は "an A" の 'A' にはマッチしませんが、"An E" の 'A' にはマッチします。

+ +
+

この文字は、文字集合パターンの先頭にある場合は異なる意味を持ちます。

+
+
$ +

入力の末尾にマッチします。複数行フラグが true にセットされている場合は、改行文字の直前にもマッチします。例えば /t$/ は "eater" の "t" にはマッチしませんが、"eat" の "t" にはマッチします。

+
\b +

単語の区切りにマッチします。これは、単語構成文字と後に続く非単語構成文字の間、または非単語構成文字と後に続く単語構成文字の間、または文字列の先頭・最後です。単語の区切りはマッチする「文字」ではありません。アンカーのように、単語の区切りはマッチした部分に含まれません。言い換えると、マッチした単語の区切りの長さは 0 です。

+ +

入力文字に "moon" を使用した例:

+ +
    +
  • /\bm/ は "m" にマッチします。これは `\b` が文字列の先頭に存在するからです。
  • +
  • /oo\b/ は "oo" にマッチしません。これは '\b' の前後に単語構成文字があるためです。
  • +
  • /oon\b/ は "oon" にマッチします。これは、文字列の終端であるためです。
  • +
  • /\w\b\w/ はどこにもマッチしないでしょう。これは、'\b' の前後に単語構成文字があるためです。
  • +
+ +

バックスペース文字 ([\b]) については文字クラスを見てください。

+
\B +

単語の区切り以外にマッチします。マッチするのは以下の場合です:

+ +
    +
  • 文字列の先頭の文字の前
  • +
  • 文字列の終端の文字の後
  • +
  • 単語内の 2 文字の間
  • +
  • 2 つの単語ではない文字の間
  • +
  • 空文字列
  • +
+ +

例えば /\B../ は "noonday" の 'oo' に、/y\B./ は "possibly yesterday" の 'ye' にマッチします。

+
+ +

その他の言明

+ +
+

? 文字は数量詞として使うことができます。

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
x(?=y) +

先読み言明: xy が続く場合のみ x にマッチします。例えば /Jack(?=Sprat)/ は "Jack" の後に "Sprat" が続く場合のみ "Jack" にマッチします。
+ /Jack(?=Sprat|Frost)/ は "Jack" の後ろに "Sprat" または "Frost" が続く場合のみ "Jack" にマッチします。しかしながら、"Sprat" も "Frost" もマッチの結果には表れません。

+
x(?!y) +

否定先読み言明: xy が続かない場合のみ x にマッチします。例えば /\d+(?!\.)/ は後ろに小数点が続かない数値にマッチします。正規表現 /\d+(?!\.)/.exec("3.141") は "141" にマッチしますが "3.141" にはマッチしません。

+
(?<=y)x +

後読み言明: yx が続く場合のみ x にマッチします。例えば、/(?<=Jack)Sprat/ は "Jack" に続く "Sprat" のみにマッチします。 /(?<=Jack|Tom)Sprat/ は "Jack" または "Tom" に続く "Sprat" のみにマッチします。しかしながら、"Jack" も "Tom" もマッチの結果には表れません。

+
(?<!y)x +

否定後読み言明: yx が続かない場合のみ x にマッチします。例えば、/(?<!-)\d+/ は、マイナス記号のつかない数字のみにマッチします。 /(?<!-)\d+/.exec('3') は "3" がマッチします。 /(?<!-)\d+/.exec('-3') はマイナス記号に数字が続いているため、マッチが見つかりません。

+
+ +

+ +

基本的な境界型の例

+ +
// おかしい文字列を修正するために正規表現の境界を利用します。
+buggyMultiline = `tey, ihe light-greon apple
+tangs on ihe greon traa`;
+
+// 1) 文字列の最初と改行の直後のマッチを修正するために ^ を利用します。
+buggyMultiline = buggyMultiline.replace(/^t/gim,'h');
+console.log(1, buggyMultiline); // 'tey', 'tangs' を 'hey', 'hangs' に修正します。 'traa' は対象外です。
+
+// 2) テキストの末尾を修正するために $ を利用します。
+buggyMultiline = buggyMultiline.replace(/aa$/gim,'ee.');
+console.log(2, buggyMultiline); // 'traa' を 'tree' に修正します。
+
+// 3) 単語と空白の間の境界の右の文字にマッチさせるために \b を利用します。
+buggyMultiline = buggyMultiline.replace(/\bi/gim,'t');
+console.log(3, buggyMultiline); // 'ihe' を修正しますが、'light'は対象外です。
+
+// 4) エンティティの境界内の文字にマッチするために \B を利用します。
+fixedMultiline = buggyMultiline.replace(/\Bo/gim,'e');
+console.log(4, fixedMultiline); // 'greon' を修正しますが、'on' は対象外です。
+ +

^ 制御文字を利用した入力の開始へのマッチ

+ +

 ^ は、通常、単語の開始にマッチさせるために利用します。この例では、/^A/ という正規表現で 'A' で始まるフルーツを取得します。ここでの ^ は、入力の開始を示すという、たった 1 つの役割を果たしています。適切なフルーツを選択するためにアロー 関数で filter メソッドを用います。

+ +
let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];
+
+// /^A/ 正規表現で 'A' で始まるフルーツを選択します。
+// ここでの'^' 制御記号は「入力の開始にマッチする」という 1 つの役割だけで利用されています。
+
+let fruitsStartsWithA = fruits.filter(fruit => /^A/.test(fruit));
+console.log(fruitsStartsWithA); // [ 'Apple', 'Avocado' ]
+ +

2 番目の例での ^ は、入力の開始へのマッチと、グル―プで用いられた場合の文字集合の否定または補集合という、両方で利用されています。

+ +
let fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];
+
+// /^[^A]/ という正規表現で 'A' で始まらないフルーツを選択します。
+// この例では、'^' 制御記号は 2 つの意味を表しています。
+// 1) 入力の開始にマッチ
+// 2) [^A]という文字集合の否定または補集合: 
+// つまり、角括弧で囲まれたものでないあらゆるものにマッチします
+
+let fruitsStartsWithNotA = fruits.filter(fruit => /^[^A]/.test(fruit));
+
+console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]
+ +

単語の境界にマッチ

+ +
let fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"];
+
+// 単語の終わりに 'en' または 'ed' を含む記述を選択します。
+let enEdSelection = fruitsWithDescription.filter(descr => /(en|ed)\b/.test(descr));
+
+console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]
+ +

先読み言明

+ +
// JS Lookahead assertion x(?=y)
+
+let regex = /First(?= test)/g;
+
+console.log('First test'.match(regex)); // [ 'First' ]
+console.log('First peach'.match(regex)); // null
+console.log('This is a First test in a year.'.match(regex)); // [ 'First' ]
+console.log('This is a First peach in a month.'.match(regex)); // null
+ +

基本的な否定先読み言明

+ +

例えば、/\d+(?!\.)/ は小数点が後に続かない数値にだけマッチします。/\d+(?!\.)/.exec('3.141') は "141" にマッチしますが、 "3" にはマッチしません。

+ +
console.log(/\d+(?!\.)/g.exec('3.141')); // [ '141', index: 2, input: '3.141' ]
+ +

言明と範囲における '?!' の組み合わせの異なる意味での利用

+ +

 ?! の組み合わせを利用するとき、言明 /x(?!y)/ 範囲 [^?!]では異なる意味を持ちます。

+ +
let orangeNotLemon = "Do you want to have an orange? Yes, I do not want to have a lemon!";
+
+// 言明 /x(?!y)/ と範囲 /[^?!]/ では '?!' の組み合わせの利用は異なる意味を持ちます。
+let selectNotLemonRegex = /[^?!]+have(?! a lemon)[^?!]+[?!]/gi
+console.log(orangeNotLemon.match(selectNotLemonRegex)); // [ 'Do you want to have an orange?' ]
+
+let selectNotOrangeRegex = /[^?!]+have(?! an orange)[^?!]+[?!]/gi
+console.log(orangeNotLemon.match(selectNotOrangeRegex)); // [ ' Yes, I do not want to have a lemon!' ]
+ +

後読み言明

+ +
let oranges = ['ripe orange A ', 'green orange B', 'ripe orange C',];
+
+let ripe_oranges = oranges.filter( fruit => fruit.match(/(?<=ripe )orange/));
+console.log(ripe_oranges); // [ 'ripe orange A ', 'ripe orange C' ]
+ +

仕様

+ + + + + + + + + + + + + + +
仕様策定状況コメント
{{SpecName('ESDraft', '#sec-assertion', 'RegExp: Assertions')}}{{Spec2('ESDraft')}}
+ +

ブラウザサポート

+ +
+ + +

{{Compat("javascript.builtins.RegExp.assertions")}}

+
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/guide/regular_expressions/character_classes/index.html b/files/ja/web/javascript/guide/regular_expressions/character_classes/index.html new file mode 100644 index 0000000000..accc601eef --- /dev/null +++ b/files/ja/web/javascript/guide/regular_expressions/character_classes/index.html @@ -0,0 +1,216 @@ +--- +title: 文字クラス +slug: Web/JavaScript/Guide/Regular_Expressions/Character_Classes +tags: + - JavaScript + - Reference + - RegExp + - Regular Expressions +translation_of: Web/JavaScript/Guide/Regular_Expressions/Character_Classes +--- +

{{JSSidebar("JavaScript Guide")}}{{Draft}}

+ +

文字クラスは、文字や数字の区別など、文字の種類を区別します。

+ +

種類

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
. +

次のいずれかの意味を持ちます。

+ +
    +
  • 行末文字 ( \n\r\u2028\u2029 ) を除くあらゆる 1 文字とマッチします。例えば、/.y/ は "my" と "ay" にマッチし、"yes make my day" の "yes" にはマッチしません。
  • +
  • 文字セット内では . はその特別な意味を失い、文字通りの "."と一致します。
  • +
+ +

複数行フラグ (m)  は "." の意味を変えないことに注意してください。そのため、複数行にわたるパターンに一致させるには、(IEの古いバージョン以外なら)文字集合 [^] を使うことで、改行を含む任意の文字に一致します。

+ +

ES2018 では s "dotAll" フラグが追加されました。これは行末文字と一致することを可能にします。

+
\d +

あらゆる(アラビア)数字にマッチします。[0-9] に相当します。例えば /\d//[0-9]/ は "B2 is the suite number" の "2" にマッチします。

+
\D +

あらゆる(アラビア)数字以外の文字にマッチします。[^0-9] に相当します。例えば /\D//[^0-9]/ は "B2 is the suite number" の "B" にマッチします。

+
\w +

アンダースコアを含むあらゆる半角英数字(基本ラテンアルファベット)にマッチします。[A-Za-z0-9_] に相当します。例えば /\w/ は、"apple," の 'a' や "$5.28," の "5" や "3D" の "3" にマッチします。

+
\W +

前述以外の文字にマッチします。[^A-Za-z0-9_] に相当します。例えば /\W//[^A-Za-z0-9_]/ は、"50%" の "%" にマッチします。

+
\s +

スペース、タブ、改ページ、改行を含むホワイトスペース文字にマッチします。[ \f\n\r\t\v​\u00a0\u1680​\u180e\u2000​-\u200a​\u2028\u2029\u202f\u205f​\u3000\ufeff] に相当します。例えば /\s\w*/"foo bar"" bar" にマッチします。

+
\S +

ホワイトスペース以外の文字にマッチします。[^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff] に相当します。例えば /\S\w*/ は "foo bar" の "foo" にマッチします。

+
\tタブ (U+0009) にマッチします。
\r復帰文字 (U+000D) にマッチします。
\n改行文字 (U+000A) にマッチします。
\v垂直タブ (U+000B) にマッチします。
\f改ページ (U+000C) にマッチします。
[\b]後退文字(バックスペース、U+0008)にマッチします。単語境界文字 (\b) については境界を見てください。
\0NULL 文字 (U+0000) にマッチします。この後ろに他の数字を続けてはいけません。\0 の後に(0 から 7 までの)数字が続くと 8 進数のエスケープシーケンスとなるからです。
\cX +

X には A から Z のうち 1 文字が入ります。文字列中の制御文字にマッチします。例えば /\cM/ は文字列中の control-M (U+000D) にマッチします。

+
\xhhhh(2 桁の 16 進数)コードからなる文字にマッチします。
\uhhhhhhhh(4 桁の 16 進数)の値からなる UTF-16 コードユニットにマッチします。
\u{hhhh} または \u{hhhhh} +

(u フラグがセットされた時のみ) U+hhhh または U+hhhhh (16 進数) Unicode 値からなる文字にマッチします。

+
\ +

次の文字を特別に扱うこと、「エスケープ」することを示します。 その振る舞いは、2 通りのうちのどちらか 1 つです。

+ +
    +
  • 通常文字の前に付けられた場合、次の文字が特別なもので、文字通りには評価されないことを示します。例えば b は文字 "b" にマッチします。しかし "b" の前にバックスラッシュを置いて \b とすると、単語区切りを意味するようになります。
  • +
  • 特殊文字の前に付けられた場合、次の文字が特別なものでなく、文字通りに評価されることを表します。例えば、"*" は、先行文字の 0 回以上の出現が一致する必要があることを意味する特殊文字です。例えば、/a*/ は 0 回以上の "a" とマッチします。文字通りの * にマッチさせるには、その直前にバックスラッシュを入れます。例えば、/a\*/"a*" とマッチします。
  • +
+ +
+

この文字を文字通りにマッチさせるには、それ自身をエスケープします。つまり、 /\\/ を使って \ を検索します。

+
+
+ +

+ +

一連の数字を探す

+ +
var randomData = "015 354 8787 687351 3512 8735";
+var regexpFourDigits = /\b\d{4}\b/g;
+// \b は境界を示します(つまり、単語の真ん中からマッチを開始しません)
+// \d{4} は 4 つの数字を示します
+// \b は別の境界を示します(つまり、単語の真ん中でマッチが終わりません)
+
+
+console.table(randomData.match(regexpFourDigits));
+// ['8787', '3512', '8735']
+ +

A から始まる(ラテンアルファベットの)単語を探す

+ +
var aliceExcerpt = "I’m sure I’m not Ada,’ she said, ‘for her hair goes in such long ringlets, and mine doesn’t go in ringlets at all.";
+var regexpWordStartingWithA = /\b[aA]\w+/g;
+// \b は境界を示します(つまり、単語の真ん中からマッチを開始しません)
+// [aA] は a または A の文字を示します
+// \w+ は複数回の *ラテンアルファベットからなる* 任意の文字を示します
+
+console.table(aliceExcerpt.match(regexpWordStartingWithA));
+// ['Ada', 'and', 'at', 'all']
+ +

(ユニコード文字の)単語を探す

+ +

単語を表すために、ラテンアルファベットではなく、 Unicode 文字の範囲が使えます。(つまり、ロシア語やアラビア語のような他の言語のテキストを扱えます。) Unicode の 「基本多言語面」には、世界中で使われているほとんどの文字が含まれており、それらの文字で書かれた単語にマッチするための文字クラスと範囲を利用できます。

+ +
var nonEnglishText = "Приключения Алисы в Стране чудес";
+var regexpBMPWord = /([\u0000-\u0019\u0021-\uFFFF])+/gu;
+// U+0000 から U+FFFF までの BMP、ただし、U+0020 は空白
+
+console.table(nonEnglishText.match(regexpBMPWord));
+[ 'Приключения', 'Алисы', 'в', 'Стране', 'чудес' ]
+ + + +

仕様

+ + + + + + + + + + + + + + + + + + +
仕様書策定状況コメント
{{SpecName('ESDraft', '#sec-characterclass', 'RegExp: Character classes')}}{{Spec2('ESDraft')}}
+ +

ブラウザサポート

+ + + +

{{Compat("javascript.builtins.RegExp.character_classes")}}

+ +

関連情報

+ + diff --git a/files/ja/web/javascript/guide/regular_expressions/groups_and_ranges/index.html b/files/ja/web/javascript/guide/regular_expressions/groups_and_ranges/index.html new file mode 100644 index 0000000000..d79009b14e --- /dev/null +++ b/files/ja/web/javascript/guide/regular_expressions/groups_and_ranges/index.html @@ -0,0 +1,162 @@ +--- +title: グループと範囲 +slug: Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges +tags: + - Guide + - JavaScript + - Reference + - Regular Expressions + - regex +translation_of: Web/JavaScript/Guide/Regular_Expressions/Groups_and_Ranges +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

グループと範囲は、式にある文字のグループと範囲を示します。

+ +

種類

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
x|y +

"x" または "y" にマッチします。例えば /green|red/ は "green apple" の "green" や "red apple" の "red" にマッチします。

+
[xyz]
+ [a-c]
+

文字集合です。角括弧で囲まれた文字のいずれか 1 個にマッチします。ハイフンを用いて文字の範囲を指定することも可能ですが、ハイフンが括弧に囲まれた最初または最後の文字に現れている場合、それはハイフンリテラルとみなされて、通常文字として文字集合に含まれます。文字集合には文字クラスを含めることができます。

+ +

例えば [abcd][a-d] と同じです。これは "brisket" の "b" や "chop" の "c" にマッチします。

+ +

例えば、[abcd-][-abcd] は "brisket" の "b" と "chop" の "c" と "non-profit" の "-" (ハイフン)とマッチします。

+ +

例えば、[\w-][A-Za-z0-9_-] と同じです。これは "brisket" の "b" や "chop" の "c" 、"non-profit" の "n" にマッチします。

+
+

[^xyz]
+ [^a-c]

+
+

文字集合の否定または補集合です。角括弧で囲まれた文字ではない文字にマッチします。ハイフンを用いて文字の範囲を指定することも可能ですが、ハイフンが括弧に囲まれた最初または最後の文字に現れている場合、それはハイフンリテラルとみなされて、通常文字として文字集合に含まれます。例えば [^abc][^a-c] と同じです。これは "bacon" の 'o' や "chop" の 'h' にマッチします。

+ +
+

^ 文字は入力の先頭を示すこともできます。

+
+
(x) +

キャプチャグループ: x にマッチし、マッチした内容を記憶します。例えば /(foo)/ は "foo bar" の "foo" にマッチし、記憶します。

+ +

正規表現は複数のキャプチャグループを持つことができます。結果、一般的にキャプチャグループ内の左括弧と同じ順にある、配列の要素のキャプチャグループに一致しています。たいていの場合、これはキャプチャグループ自身の順番です。これはキャプチャグループがネストしている場合に重要です。マッチは結果の要素のインデックス ([1], ..., [n]) や、あらかじめ定義されている RegExp オブジェクトのプロパティ ($1, ..., $9) を使ってアクセスできます。

+ +

キャプチャグループはパフォーマンスペナルティがあります。マッチした部分文字列を使わない場合はキャプチャしない括弧(後述)を使ったほうがいいでしょう。

+ +

全体マッチ (/.../g) がある場合、{{JSxRef("String.match()")}} はグループを返せません。ですが、 {{JSxRef("String.matchAll()")}} によってすべてのマッチを取得できます。

+
\n +

n に正の整数が入ります。正規表現内において n 番目の括弧の部分にマッチした最新の部分文字列への後方参照となります(括弧の数は左からカウントします)。例えば /apple(,)\sorange\1/ は "apple, orange, cherry, peach" の "apple, orange," にマッチします。A complete example follows this table.

+
(?<Name>x) +

名前付きキャプチャグループ: x にマッチし、<Name> で指定された名前に従い、返されるマッチの groups プロパティに記憶されます。三角括弧 ('<' と '>') にはグループ名が必須です。

+ +

例えば、電話番号からアメリカのエリアコードを取り出す際、/\((?<area>\d\d\d)\)/ を使うことができます。 結果の番号は matches.groups.area に表示されます。

+
(?:x) +

非キャプチャグループ: x にマッチしますが、マッチした内容は記憶しません。マッチの部分文字列は、結果の配列の要素 ([1], ..., [n]) や、あらかじめ定義されている RegExp オブジェクトのプロパティ ($1, ..., $9) から呼び出すことはできません。.

+
+ +

+ +

母音を数える

+ +
var aliceExcerpt = "There was a long silence after this, and Alice could only hear whispers now and then.";
+var regexpVowels = /[aeiouy]/g;
+
+console.log("母音の数:", aliceExcerpt.match(regexpVowels).length);
+// 母音の数: 25
+ +

グループの使い方

+ +
let personList = `First_Name: John, Last_Name: Doe
+First_Name: Jane, Last_Name: Smith`;
+
+let regexpNames =  /First_Name: (\w+), Last_Name: (\w+)/mg;
+let match = regexpNames.exec(personList);
+do {
+  console.log(`Hello ${match[1]} ${match[2]}`);
+} while((match = regexpNames.exec(personList)) !== null);
+
+ +

名前付きグループの使い方

+ +
let personList = `First_Name: John, Last_Name: Doe
+First_Name: Jane, Last_Name: Smith`;
+
+let regexpNames =  /First_Name: (?<firstname>\w+), Last_Name: (?<lastname>\w+)/mg;
+let match = regexpNames.exec(personList);
+do {
+  console.log(`Hello ${match.groups.firstname} ${match.groups.lastname}`);
+} while((match = regexpNames.exec(personList)) !== null);
+ +
+

注: すべてのブラウザがこの機能をサポートしているわけではありません。以下の互換性の表を参照してください。

+
+ +

仕様

+ + + + + + + + + + + + + + +
仕様策定状況コメント
{{SpecName('ESDraft', '#sec-classranges', 'RegExp: Ranges')}}{{Spec2('ESDraft')}}
+ +

ブラウザサポート

+ +
+ + + + +

{{Compat("javascript.builtins.RegExp.groups_ranges")}}

+
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/guide/regular_expressions/index.html b/files/ja/web/javascript/guide/regular_expressions/index.html new file mode 100644 index 0000000000..a6a571bb88 --- /dev/null +++ b/files/ja/web/javascript/guide/regular_expressions/index.html @@ -0,0 +1,800 @@ +--- +title: 正規表現 +slug: Web/JavaScript/Guide/Regular_Expressions +tags: + - Guide + - Intermediate + - JavaScript + - Reference + - RegExp + - Regular Expressions + - regex +translation_of: Web/JavaScript/Guide/Regular_Expressions +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Indexed_collections")}}
+ +

正規表現とは、文字列内で文字の組み合わせを照合するために用いられるパターンです。JavaScript では、正規表現はオブジェクトでもあります。これらのパターンは {{jsxref("RegExp")}} の {{jsxref("RegExp.exec", "exec")}} および {{jsxref("RegExp.test", "test")}} メソッドや、{{jsxref("String")}} の {{jsxref("String.match", "match")}}、 {{jsxref("String.matchAll", "matchAll")}}、{{jsxref("String.replace", "replace")}}、{{jsxref("String.search", "search")}}、および {{jsxref("String.split", "split")}} メソッドで使用できます。本章では、JavaScript の正規表現について説明します。

+ +

正規表現の作成

+ +

正規表現は 2 種類の方法で作成できます :

+ +

次のように、スラッシュによって囲まれたパターンからなる正規表現リテラルを使用します :

+ +
var re = /ab+c/;
+
+ +

正規表現リテラルはスクリプトのロード時にその正規表現をコンパイルします。正規表現が一定のままの場合、この方法を使うとよいパフォーマンスが得られます。

+ +

また、次のように {{jsxref("RegExp")}} オブジェクトのコンストラクタ関数を呼び出す方法があります :

+ +
var re = new RegExp('ab+c');
+
+ +

コンストラクタ関数を使用すると、実行時にその正規表現をコンパイルします。正規表現パターンが変わることがわかっている場合や、パターンがわからない場合、ユーザーが入力するなど別のソースからパターンを取得する場合は、コンストラクタ関数を使用してください。

+ +

正規表現パターンの記述

+ +

正規表現パターンは、/abc/ のような単純な文字、または /ab*c//Chapter (\d+)\.\d*/ のような単純な文字と特殊文字との組み合わせからなります。最後の例には記憶装置として用いられる丸括弧があります。パターンのこの丸括弧で囲まれた部分でマッチした箇所は、後で使用できるように記憶されます。詳しくは{{anch("Using_Parenthesized_Substring_Matches", "括弧で囲まれた部分文字列のマッチの使用")}}を参照してください。

+ +

単純なパターンの使い方

+ +

単純なパターンとは、直接マッチしている部分を見つけたい文字から構成されたものです。例えば /abc/ というパターンは、実際に 'abc' という文字が一緒にその順で存在しているときだけ、文字列中の文字の組み合わせにマッチします。"Hi, do you know your abc's?" や "The latest airplane designs evolved from slabcraft." といった文字列でのマッチは成功します。どちらの場合でも 'abc' という部分文字列にマッチします。"Grab crab" という文字列では、'abc' という部分文字列が含まれていないためマッチしません。

+ +

特殊文字の使い方

+ +

1 個以上の b を見つけたり、ホワイトスペースを見つけたりといった直接マッチより高度なマッチの検索では、パターンに特殊文字を使用します。例えば /ab*c/ というパターンでは、1 個の 'a' とその後ろに続く 0 個以上の 'b' (* は直前のアイテムの 0 回以上の出現を意味します)、そしてそのすぐ後ろに続く 'c' で構成される文字の組み合わせにマッチします。"cbbabbbbcdebc," という文字列では、このパターンは 'abbbbc' という部分文字列にマッチします。

+ +

以下のページで、正規表現で使用できる特殊文字の完全なリストとその意味を詳しく説明します。

+ +
+
言明
+
言明には、 行や単語の始まり・終わりを示す、境界や、(先読み、後読み、条件式を含む)何らかの方法でマッチが可能なことを示す、その他のパターンが含まれます。
+
文字クラス
+
文字や数字の区別など、文字の種類を区別します。
+
グループと範囲
+
式にある文字のグループと範囲を示します。
+
数量詞
+
マッチする文字や式の数を示します。
+
Unicode プロパティエスケープ
+
大文字と小文字、数学記号、句読点など、Unicode文字のプロパティに基づき区別します。
+
+ +

正規表現で利用可能なすべての特殊文字を単一の表で見たい場合は、以下を参照してください。

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
正規表現における特殊文字
文字意味
\ +

以下のルールに基づいてマッチします :

+ +

特別な意味を持たない文字の前に付けられたバックスラッシュ文字は、次の文字が特別なもので、文字通りには評価されないことを表します。例えば、前に '\' がない 'b' は文字列中のあらゆる箇所の小文字の 'b' にマッチします。つまり、その文字は文字通り評価されます。しかし '\b' という表現はどんな文字にもマッチしません。これは単語区切りを意味します。
+
+ 特別な意味を持つ文字の前に付けられたバックスラッシュ文字は、次の文字が特別なものでなく、文字通りに評価されることを表します。詳しくは "Escaping" の章を見てください。

+ +

RegExp コンストラクタの引数に文字列を指定して使う場合、文字列リテラル内でのバックスラッシュはエスケープ文字であることを忘れないでください。つまり、パターン内でバックスラッシュを使うためには、文字列リテラル内でそれをエスケープする必要があるのです。 /[a-z]\s/inew RegExp("[a-z]\\s", "i") は同じ正規表現を作成します。この表現は、A から Z までの範囲の任意の文字とそれに続く 1 つの空白を探します(\s は次以降を見てください)。文字列を引数として指定した新しい RegExp インスタンスでリテラルとしての バックスラッシュを表現するには、文字列レベルと正規表現レベルの両方でバックスラッシュをエスケープする必要があります。つまり、 /[a-z]:\\/inew RegExp("[a-z]:\\\\","i") は "C:\" にマッチする同じ表現を作成します。

+
^ +

入力の先頭にマッチします。複数行フラグが true にセットされている場合は、改行文字の直後にもマッチします。
+
+ 例えば、/^A/ は "an A" の 'A' にはマッチしませんが、"An E" の 'A' にはマッチします。

+ +

この文字は、文字集合パターンの先頭にある場合は異なる意味を持ちます。例と詳細については相補文字集合をご覧ください。

+
$ +

入力の末尾にマッチします。複数行フラグが true にセットされている場合は、改行文字の直前にもマッチします。

+ +

例えば、/t$/ は "eater" の 't' にはマッチしませんが、"eat" の 't' にはマッチします。

+
* +

直前の文字の 0 回以上の繰り返しにマッチします。{0,}に相当します。

+ +

例えば、 /bo*/ は "A ghost booooed" の 'boooo' や "A bird warbled" の 'b' にマッチしますが、"A goat grunted" ではマッチしません。

+
+ +

直前の文字の 1 回以上の繰り返しにマッチします。{1,}に相当します。

+ +

例えば、/a+/  は "candy" の 'a' や "caaaaaaandy" のすべての a にマッチします。

+
?直前の文字の 0 回か 1 回の出現にマッチします。{0,1}に相当します。
+
+ 例えば、 /e?le?/ +

は "angel" の 'el' や "angle" の 'le'、あるいは "oslo" の 'l' にマッチします。

+ *、+、?、{} といった量指定子の直後に使用した場合、その量指定子をデフォルトとは逆の{{原語併記("非貪欲","non-greedy")}} (最短)マッチにします。デフォルトは{{原語併記("欲張り","greedy")}}(最長)マッチです。例えば、/\d+/ は "123abc" の "123" にマッチしますが、/\d+?/ の場合は "1" にだけマッチします。
+
+ この特殊文字は、この表の x(?=y) および x(?!y) + +

の項目で説明する先読みアサーションでも使用できます。

+
. +

(小数点) はデフォルトでは改行文字以外のどの 1 文字にもマッチします。

+ +

例えば、 /.n/ は "nay, an apple is on the tree" の 'an' や 'on' にはマッチしますが、'nay' にはマッチしません。

+ +

s ("dotAll") フラグが true にセットされている場合は、改行文字にもマッチします。

+
(x) +

'x' にマッチし、マッチした内容を記憶します。この括弧はキャプチャリング(格納)括弧と呼ばれます。
+
+ 例えば、パターン/(foo) (bar)\1 \2/内の '(foo)' と '(bar)' は、文字列 "foo bar foo bar" の最初の 2 個の単語にマッチし、それを記憶します。パターン内の \1\2 の 1 個目と 2 個目の括弧内の文字、すなわち foobarを表し、文字列の最後の 2 個の単語にマッチします。\1, \2, ..., \n は正規表現のマッチ部分で使用することに注意してください。詳しくは下記の \n を参照してください。 置換部分で使用する際は $1, $2, ..., $n とする必要があります。例えば、 'bar foo'.replace(/(...) (...)/, '$2 $1')というように。$& はマッチした文字列全体を意味します。

+
(?:x) +

'x' にマッチしますが、マッチした内容は記憶しません。この括弧は非キャプチャリング(非格納)括弧と呼ばれ、パターンをグルーピングして、正規表現演算子と一緒に使う際の部分正規表現式を定義することができます。 見本として式 /(?:foo){1,2}/ を見てみましょう。式が /foo{1,2}/であれば、{1,2} の文字は 'foo' の最後の 'o' にのみ適用されます。非キャプチャリング括弧を使うと、{1,2} は'foo' という単語全体に適用されます。詳しい情報は、下記の括弧を使うを見てください。

+
x(?=y) +

'x' に 'y' が続く場合のみ 'x' にマッチします。この特殊文字は先読みと呼ばれます。

+ +

例えば、/Jack(?=Sprat)/ は 'Jack' の後に 'Sprat' が続く場合のみ 'Jack' にマッチします。 /Jack(?=Sprat|Frost)/ は 'Jack' の後ろに 'Sprat' または 'Frost' が続く場合のみ 'Jack' にマッチします。しかしながら、'Sprat' も 'Frost' もマッチの結果には表れません。

+
x(?!y) +

'x' に 'y' が続かない場合のみ 'x' にマッチします。これは否定先読みと呼ばれます。

+ +

例えば、 /\d+(?!\.)/ は後ろに小数点が続かない数値にマッチします。正規表現 /\d+(?!\.)/.exec("3.141") は'141' にマッチしますが '3.141' にはマッチしません。

+
(?<=y)x +

x の前に y がある場合のみxにマッチします。 これは後読みと呼ばれます。

+ +

例えば、 /(?<=Jack)Sprat/ は "Sprat" の前に "Jack" がある場合にのみマッチし、
+ /(?<=Jack|Tom)Sprat/ は "Sprat" の前に "Jack" または "Tom" がある場合にのみマッチします。
+ しかしながら、"Jack"も "Tom" もマッチの結果には表れません。

+
(?<!y)x +

x の前に yがない場合のみ x にマッチします。これは否定後読みと呼ばれます。

+ +

例えば、 /(?<!-)\d+/ は前にマイナス符号がない数値にのみマッチします。
+ /(?<!-)\d+/.exec('3') は "3"にマッチしていますが、
+ /(?<!-)\d+/.exec('-3') にマッチは見つかりません。なぜなら' -3' の前にはマイナス符号があるからです。

+
x|y +

'x', または 'y' にマッチします。('x' にマッチする必要はありません。)

+ +

例えば、/green|red/ は "green apple" の 'green' や "red apple." の 'red' にマッチします。'x' と 'y' の順番は重要です。例えば a*|b は"b" の空文字列にマッチしますが、 b|a* は同じ文字列の "b" にマッチします。

+
{n}直前の文字がちょうど n 回出現するものにマッチします。n には正の整数が入ります。
+
+ 例えば、 /a{2}/ は "candy" の 'a' にはマッチしませんが、"caaandy" の最初の 2 個の a にはマッチします。
{n,} +

直前の式の少なくとも n 回の出現にマッチします。n には正の整数が入ります。

+ +

例えば、 /a{2,}/ は "aa", "aaaa", "aaaaa" にマッチしますが "a" にはマッチしません。

+
{n,m} +

直前の文字が少なくとも n 回、多くても m 回出現するものにマッチします。n および m には正の整数が入ります。m を省略した場合は ∞ とみなされます。

+ +

例えば、 /a{1,3}/ は "cndy" ではマッチせず、"candy," の 'a'、"caandy," の 最初の 2 個の a、"caaaaaaandy" の最初の 3 個の a にマッチします。"caaaaaaandy" では元の文字列に a が 4 個以上ありますが、マッチするのは "aaa" であることに注意してください。

+
[xyz] +

文字集合を表します。このパターンでは、角括弧で囲まれた文字のいずれか 1 個にマッチします。対象の文字はエスケープシーケンスも含みます。 文字の集合内では、特殊文字 (例えばドット (.) やアスタリスク (*)) は特別な意味を持たないので、それらにエスケープは不要です。以下で例示するように、ハイフンを用いて文字の範囲を指定することも可能です。
+
+ 例えば [abcd][a-d] と同じです。これは "brisket" の 'b' や "city" の 'c' にマッチします。/[a-z.]+/ および /[\w.]+/ はどちらも、"test.i.ng" の全体にマッチします。

+
[^xyz] +

文字集合の否定または補集合です。角括弧で囲まれた文字ではない文字にマッチします。ハイフンを用いて文字の範囲を指定することも可能です。文字集合パターンで動作するものすべてがこちらでも機能します。

+ +

例えば、 [^abc][^a-c]と同じです。これは "brisket" の 'r' や "chop" の 'h' といった一番最初の該当文字にマッチします。

+
[\b]後退文字(バックスペース、U+0008)にマッチします。 後退文字自体にマッチさせるには角括弧を使う必要があります。(\b と混同しないように。)
\b +

単語の区切りにマッチします。単語の区切りは、単語構成文字と後に続く非単語構成文字の間、または非単語構成文字と後に続く単語構成文字の間、または文字列の先頭、または文字列の最後とマッチします。単語の区切りはマッチする「文字」ではありません。アンカーのように、単語の区切りはマッチした部分に含まれません。言い換えると、マッチした単語の区切りの長さは 0 です。([\b] と混同してはいけません。)

+ +

入力文字に "moon" を使用した例:
+ /\bm/ はマッチします。これは `\b` が文字列の先頭に存在するからです。
+ /oo\b/ の '\b' はマッチしません。これは '\b' の前後に単語構成文字があるためです。
+ /oon\b/ の '\b' はマッチします。これは、文字列の終端であるためです。
+ /\w\b\w/ の '\b' はどこにもマッチしないでしょう。これは、'\b' の前後に単語構成文字があるためです。

+ +
+

注記 : JavaScript の正規表現エンジンでは「{{原語併記("単語","word")}}」を構成する文字として 特定の文字集合を定義しています。 この集合内にない文字は非単語構成文字と見なされます。この文字集合はかなり限定的なもので、ローマ字の大文字小文字のアルファベット、10 進数字とアンダースコアのみが含まれます。"é" や "ü" といった文字{{訳注("そして日本語を構成する文字たちも")}}、残念ながら、一般的な表意文字と同様に、単語の区切りのために非単語構成文字として扱われます。

+
+
\B +

単語の区切り以外にマッチします。マッチするのは以下の場合です:

+ +
    +
  • 文字列の先頭の文字の前
  • +
  • 文字列の終端の文字の後
  • +
  • 単語内の 2 文字の間
  • +
  • 2 つの単語ではない文字の間
  • +
  • 空文字列
  • +
+ +

例えば、/\B../ は "noonday" の 'oo' に、/y\B./ は "possibly yesterday" の 'ye' にマッチします。

+
\cX +

文字列中の制御文字にマッチします。 X には A から Z のうち 1 文字が入ります。

+ +

例えば、 /\cM/ は文字列中の control-M (U+000D) にマッチします。

+
\d +

数字にマッチします。[0-9] に相当します。

+ +

例えば、 /\d//[0-9]/ は "B2 is the suite number" の '2' にマッチします。

+
\D +

数字以外の文字にマッチします。[^0-9] に相当します。

+ +

例えば、/\D//[^0-9]/ は "B2 is the suite number" の 'B' にマッチします。

+
\f改ページ (U+000C) にマッチします。
\n改行文字 (U+000A) にマッチします。
\r復帰文字 (U+000D) にマッチします。
\s +

スペース、タブ、改ページ、改行を含むホワイトスペース文字にマッチします。[ \f\n\r\t\v​\u00a0\u1680​\u180e\u2000​-\u200a​\u2028\u2029\u202f\u205f​\u3000\ufeff] に相当します。

+ +

例えば /\s\w*/ は "foo bar" の ' bar' にマッチします。

+
\S +

ホワイトスペース以外の文字にマッチします。 [^ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff] に相当します。

+ +

例えば、 /\S*/ は "foo bar" の 'foo' にマッチします。

+
\tタブ (U+0009) にマッチします。
\v垂直タブ (U+000B) にマッチします。
\w +

アンダースコアを含むどの英数字にもマッチします。[A-Za-z0-9_] に相当します。

+ +

例えば /\w/ は、"apple," の 'a' や "$5.28," の '5' や "3D" の '3' にマッチします。

+
\W +

前述以外の文字にマッチします。[^A-Za-z0-9_] に相当します。

+ +

例えば、/\w//[^A-Za-z0-9_]/ は、"50%" の '%' にマッチします。

+
\n +

n に正の整数が入る場合、正規表現内において n 番目の括弧の部分にマッチした最新の部分文字列への後方参照となります(括弧の数は左からカウントします)。

+ +

例えば /apple(,)\sorange\1/ は "apple, orange, cherry, peach" の 'apple, orange,' にマッチします。

+
\0NULL 文字 (U+0000) にマッチします。この後ろに他の数字を続けてはいけません。\0 の後に(0 から 7 までの)数字が続くと 8 進数の エスケープシーケンスとなるからです。
\xhhhh(2 桁の 16 進数)コードからなる文字列にマッチします。
\uhhhhhhhh(4 桁の 16 進数)コードからなる文字列にマッチします。
\u{hhhh}(u フラグがセットされた時のみ) Unicode 値 hhhh (16 進数) からなる文字列にマッチします。
+
+
+
+ +

エスケープする

+ +

もし特殊な文字を使う必要があるのなら(例えば実際に * を検索したい場合)、その文字の前にバックスラッシュを付けてエスケープする必要があります。例えば、a と * と b が続くのを検索する場合、/a\*b/ とします。これはバックスラッシュが * を特殊な文字ではなく、リテラルとして扱うようにエスケープしています。

+ +

同様に、もし正規表現リテラルを書いていてスラッシュ('/')とマッチさせる必要があるならば、スラッシュをエスケープする必要があります(そうしないとスラッシュがパターンを終了してしまいます)。例えば、"/example/"の文字列とそれに続く1つ以上のアルファベットを探すためには、/\/example\/[a-z]+/i とします。各スラッシュ前のバックスラッシュが、スラッシュをリテラルにしています。

+ +

リテラルのバックスラッシュにマッチするためには、バックスラッシュをエスケープする必要があります。例えば、'C' は任意の文字である "C:\" という文字列にマッチするためには、/[A-Z]:\\/とします。最初のバックスラッシュはその後のバックスラッシュをエスケープし、この表現は単一のリテラルバックスラッシュを探します。

+ +

RegExp コンストラクタを文字列リテラルを引数に指定して利用する場合は、バックスラッシュは文字列リテラル内でのエスケープ文字であることを思い出してください。つまり、バックスラッシュを正規表現で用いるには文字列リテラルレベルでエスケープする必要があります。 /a\*b/new RegExp("a\\*b") は、 'a' の次に '*'、その次に 'b' を探す同じ表現を作成します。

+ +

エスケープ文字がパターンに追加されてないなら、{{jsxref("String.replace")}} を使用して追加することができます:

+ +
function escapeRegExp(string) {
+  return string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&'); // $&はマッチした部分文字列全体を意味します
+}
+ +

正規表現の後の g はグローバルサーチを行うオプション/フラグで、全体の文字列を見てすべてのマッチを返します。下の{{anch("Advanced_Searching_With_Flags", "フラグを用いた高度な検索")}}に詳しく説明されています。

+ +

括弧の使い方

+ +

正規表現パターンの一部を括弧で囲むことで、マッチした部分文字列を記憶しておくことができます。いったん記憶されれば、後からその部分文字列を呼び出すことができます。これに関しては{{anch("Using_Parenthesized_Substring_Matches", "括弧で囲まれた部分文字列のマッチの使用")}}で説明しています。

+ +

例として /Chapter (\d+)\.\d*/ というパターンを使い、エスケープ文字と特殊文字についても説明した上で、どのようにパターンの一部が記憶されるかを示します。これは 'Chapter ' という文字列に正確にマッチし、それに続く 1 文字以上の数字 (\d はいずれかの数字を、+ は 1 回以上の繰り返しを意味します)、それに続く小数点(それ自体は特殊文字であり、小数点の前の \ はパターンが '.' という文字そのものを探すようにすることを意味します)、それに続く 0 文字以上の数字 (\d は数字を、* は 0 回以上の繰り返しを意味します)にマッチします。さらに、最初にマッチした数字の記憶に括弧が使われています。

+ +

このパターンは "Open Chapter 4.3, paragraph 6" という文字列で検索され、'4' が記憶されます。このパターンは "Chapter 3 and 4" では見つかりません。この文字列は '3' の後にピリオドがないからです。

+ +

マッチした部分を記憶させることなく部分文字列にマッチさせたい場合は、その括弧においてパターンの前に ?: をつけてください。例えば (?:\d+) は 1 文字以上の数字にマッチしますが、マッチした文字列は記憶しません。

+ +

JavaScriptでの正規表現の使い方

+ +

正規表現は、RegExptest および exec メソッド、Stringmatchreplacesearchsplit メソッドとともに使用します。これらのメソッドの詳細は JavaScript リファレンスで説明しています。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
正規表現を使用するメソッド
メソッド説明
{{jsxref("RegExp.exec", "exec")}}文字列中で一致するものを検索する RegExp のメソッドです。結果情報の配列を返します。
{{jsxref("RegExp.test", "test")}}文字列中で一致するものがあるかをテストする RegExp のメソッドです。true または false を返します。
{{jsxref("String.match", "match")}}文字列中で一致するものを検索する String のメソッドです。結果情報の配列を返します。マッチしない場合は null を返します。
{{jsxref("String.matchAll", "matchAll")}}キャプチャグループを含んだ、すべてのマッチをもつ iterator を返す String のメソッドです。 
{{jsxref("String.search", "search")}}文字列中で一致するものがあるかをテストする String のメソッドです。マッチした場所のインデックスを返します。検索に失敗した場合は -1 を返します。
{{jsxref("String.replace", "replace")}}文字列中で一致するものを検索し、マッチした部分文字列を別の部分文字列に置換する String のメソッドです。
{{jsxref("String.split", "split")}}正規表現または固定文字列を用いて文字列を分割し、部分文字列の配列に入れる String のメソッドです。
+ +

あるパターンが文字列に存在するかを知りたいときは、test または search メソッドを使用してください。詳細な情報が知りたいときは(実行時間が長くなりますが)exec または match メソッドを使用してください。execmatch を使用してマッチが成功した場合、これらのメソッドは配列を返し、また結びつけられた正規表現オブジェクトと定義済みオブジェクトである RegExp オブジェクトのプロパティを更新します。マッチが失敗すると、exec メソッドは nullfalse に変換します)を返します。

+ +

次の例では、exec メソッドを使用して文字列を検索します。

+ +
var myRe = /d(b+)d/g;
+var myArray = myRe.exec("cdbbdbsbz");
+
+ +

正規表現のプロパティにアクセスする必要がない場合は、次のスクリプトが myArray を作成する別の方法になります:

+ +
var myArray = /d(b+)d/g.exec('cdbbdbsbz'); // similar to "cdbbdbsbz".match(/d(b+)d/g); however,
+    // the latter outputs Array [ "dbbd" ], while
+    // /d(b+)d/g.exec('cdbbdbsbz') outputs Array [ 'dbbd', 'bb', index: 1, input: 'cdbbdbsbz' ].
+ +

(異なるふるまいの詳しい情報は {{anch("g-different-behaviors", "g フラグによる振る舞いの違い")}}を参照してください。)

+ +

ある文字列から正規表現を組み立てたい場合は、次のスクリプトのような方法があります:

+ +
var myRe = new RegExp('d(b+)d', 'g');
+var myArray = myRe.exec('cdbbdbsbz');
+
+ +

これらのスクリプトではマッチが成功すると、配列を返すとともに次表で示されるプロパティを更新します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
正規表現の実行結果
オブジェクトプロパティまたはインデックス説明この例の場合
myArrayマッチした文字列と、すべての記憶された部分文字列です。['dbbd', 'bb', index: 1, input: 'cdbbdbsbz']
index入力文字列でマッチした位置を示す、0 から始まるインデックスです。1
input元の文字列です。"cdbbdbsbz"
[0]最後にマッチした文字列です。"dbbd"
myRelastIndex次のマッチが始まるインデックスです。(このプロパティは、g オプションを用いる正規表現でのみセットされます。これについては{{anch("Advanced_Searching_With_Flags", "フラグを用いた高度な検索")}}で説明します。)5
sourceパターンのテキストです。正規表現の実行時ではなく作成時に更新されます。"d(b+)d"
+ +

この例の 2 つ目の形式で示したように、オブジェクト初期化子を使用して、変数に代入せずに正規表現を使うことができます。しかしながら、この方法では生成される正規表現はすべて、別の正規表現として作成されます。このため、変数に代入しないこの形式を使用する場合は、その正規表現のプロパティに後からアクセスすることができません。例えば、次のようなスクリプトを使用するとしましょう :

+ +
var myRe = /d(b+)d/g;
+var myArray = myRe.exec('cdbbdbsbz');
+console.log('The value of lastIndex is ' + myRe.lastIndex);
+
+// "The value of lastIndex is 5"
+
+ +

しかし、このスクリプトの場合は次のようになります:

+ +
var myArray = /d(b+)d/g.exec('cdbbdbsbz');
+console.log('The value of lastIndex is ' + /d(b+)d/g.lastIndex);
+
+// "The value of lastIndex is 0"
+ +

この 2 つの文中の /d(b+)d/g は別の正規表現オブジェクトであり、そのためにそれぞれの lastIndex プロパティの値も異なるのです。オブジェクト初期化子で作成する正規表現のプロパティにアクセスする必要がある場合は、まずそれを変数に代入するようにしてください。

+ +

括弧で囲まれた部分文字列のマッチの使用

+ +

正規表現パターンに括弧を含めることで、対応するサブマッチが記憶されます。例えば /a(b)c/ は 'abc' という文字列にマッチし、'b' が記憶されます。この括弧で囲まれた部分文字列のマッチは、Array の要素 [1], ..., [n] を使用して呼び出すことができます。

+ +

括弧で囲まれた部分文字列は何個でも使用できます。返された配列には、見つかったものすべてが存在します。以下の例では、括弧で囲まれた部分文字列の使用法を説明します。

+ +

次のスクリプトは {{jsxref("String.replace", "replace()")}} メソッドを使用して文字列中の単語を入れ替えます。テキスト置き換えのために、スクリプトで $1$2 を使用して、最初とその次の括弧で囲まれた部分文字列のマッチを示しています。

+ +
var re = /(\w+)\s(\w+)/;
+var str = 'John Smith';
+var newstr = str.replace(re, '$2, $1');
+console.log(newstr);
+
+// "Smith, John"
+
+ +

フラグを用いた高度な検索

+ +

正規表現には、グローバルな検索や大文字/小文字を区別しない検索を可能にする 4 種類のオプションフラグがあります。これらのフラグは、単独で使用することもまとめて使用することもできます。順番は問いません。フラグは正規表現の一部として含まれます。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
正規表現フラグ
フラグ説明
gグローバルサーチ。
i大文字・小文字を区別しない検索。
m複数行検索。
s. を改行文字と一致するようにします。
u"unicode"; パターンをユニコードのコードポイントの連続として扱う
y対象文字列で最後に見つかったマッチの位置から検索を開始する{{原語併記("先頭固定","sticky")}} 検索を行います。{{jsxref("RegExp.sticky", "sticky")}} のページをご覧ください。
+ +

フラグを正規表現に含めるには、次のようにしてください :

+ +
var re = /pattern/flags;
+
+ +

または

+ +
var re = new RegExp('pattern', 'flags');
+
+ +

フラグは正規表現を作る際になくてはならないものであることに注意してください。後から加えたり取り除いたりすることはできません。

+ +

例えば re = /\w+\s/g は、1 個以上の文字とそれに続くスペースを探す正規表現を作成します。また、正規表現は文字列全体を通してこの組み合わせを探します。

+ +
var re = /\w+\s/g;
+var str = 'fee fi fo fum';
+var myArray = str.match(re);
+console.log(myArray);
+
+// ["fee ", "fi ", "fo "]
+
+ +

この例では次の行 :

+ +
var re = /\w+\s/g;
+
+ +

を次の行 :

+ +
var re = new RegExp('\\w+\\s', 'g');
+
+ +

に置き換えることができます。得られる結果は同じです。

+ +

.exec() メソッドが使われた時には 'g' に関連したふるまいは異なります。("class" と "argument" の役割が反対になります: .match() の場合、文字クラス(やデータ型) がメソッドを持ち、正規表現は単なる引数で、.exec() の場合、正規表現がメソッドを持ち、文字は引数です。str.match(re)re.exec(str) を比較します) 'g' フラグが .exec() メソッドで使われる時は繰り返して進むためです。

+ +
var xArray; while(xArray = re.exec(str)) console.log(xArray);
+// produces:
+// ["fee ", index: 0, input: "fee fi fo fum"]
+// ["fi ", index: 4, input: "fee fi fo fum"]
+// ["fo ", index: 7, input: "fee fi fo fum"]
+ +

m フラグは複数行の入力文字列が複数行として扱われるように使われます。m が使われた場合、^$ は文字列全体の最初と最後の代わりに、入力文字列内のあらゆる行の開始と終了にマッチします。

+ +

+ +

以下では、正規表現の使用法をいくつか例示します。

+ +

入力文字列の順序変更

+ +

次の例では、正規表現の構造と string.split() および string.replace() の使用法を示します。空白、タブ、1 個のセミコロンで分割された名前(ファーストネームが先頭)からなる、大まかに整形された入力文字列をきれいにフォーマットします。最終的に名前の順序を逆転し(ラストネームが先頭)、リストをソートします。

+ +
// 名前の文字列は複数の空白やタブを含む。
+// また、ファーストネームとラストネームの間に複数の空白があることもある
+var names = 'Orange Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ';
+
+var output = ['---------- Original String\n', names + '\n'];
+
+// 2 種類の正規表現パターンと、格納用の配列を用意する。
+// 文字列を分割して配列の要素に収める。
+
+// パターン: ホワイトスペースの 0 回以上の繰り返しのあとにセミコロン、そのあとにホワイトスペースの 0 回以上の繰り返し
+var pattern = /\s*;\s*/;
+
+// 上記のパターンで文字列を断片に分割し、
+// nameList という配列に断片を格納する。
+var nameList = names.split(pattern);
+
+// 新たなパターン: 1 個以上の文字、1 個以上のホワイトスペース、1 個以上の文字
+// 括弧を用いてパターンの断片を記憶する。
+// 記憶した断片は後から参照される。
+pattern = /(\w+)\s+(\w+)/;
+
+// 処理された名前を格納する新しい配列。
+var bySurnameList = [];
+
+// 名前の配列を表示し、新しい配列にカンマ区切りで名前を
+// ラストネーム、ファーストネームの順で格納する。
+//
+// replace メソッドはパターンにマッチしたものを除去し、
+// 「2 番目の記憶文字列のあとにカンマとスペース、
+// さらにその後に続く 1 番目の記憶文字列」に置き換える。
+//
+// 変数 $1 および $2 は、パターンにマッチさせた際に
+// 記憶しておいた部分文字列を参照する
+
+output.push('---------- After Split by Regular Expression');
+
+var i, len;
+for (i = 0, len = nameList.length; i < len; i++){
+  output.push(nameList[i]);
+  bySurnameList[i] = nameList[i].replace(pattern, '$2, $1');
+}
+
+// 新しい配列を表示する。
+output.push("---------- Names Reversed");
+for (i = 0, len = bySurnameList.length; i < len; i++){
+  output.push(bySurnameList[i]);
+}
+
+// ラストネームについてソートし、ソートした配列を表示する。
+bySurnameList.sort();
+output.push('---------- Sorted');
+for (i = 0, len = bySurnameList.length; i < len; i++){
+  output.push(bySurnameList[i]);
+}
+
+output.push('---------- End');
+
+console.log(output.join('\n'));
+
+// produces:
+//
+// ---------- Original String
+//
+// Orange Carrot ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand
+//
+// ---------- After Split by Regular Expression
+// Orange Carrot
+// Fred Barney
+// Helen Rigby
+// Bill Abel
+// Chris Hand
+// ---------- Names Reversed
+// Carrot, Orange
+// Barney, Fred
+// Rigby, Helen
+// Abel, Bill
+// Hand, Chris
+// ---------- Sorted
+// Abel, Bill
+// Barney, Fred
+// Carrot, Orange
+// Hand, Chris
+// Rigby, Helen
+// ---------- End
+
+
+ +

特殊文字を用いた入力の確認

+ +

次の例では、ユーザーは電話番号を入力します。ユーザーが "Check" ボタンを押すと、スクリプトがその番号の妥当性を確認します。その番号が正当である(正規表現で指定した文字の連続にマッチする)場合、スクリプトはユーザーへの感謝のメッセージを表示し、その番号を承認します。番号が正当でない場合は、その番号が妥当でないことをユーザーに通知します。

+ +

正規表現は、0 または 1 個の左括弧 \(?、その後に 3 個の数字 \d{3}、その後に 0 または 1 個の右括弧 \)?、その後、見つかった際に記憶される 1 個のダッシュ、スラッシュ、または小数点 ([-\/\.])、その後に 3 個の数字 \d{3}、その後、記憶された 1 個のダッシュ、スラッシュ、または小数点のマッチ \1、その後に 4 個の数字 \d{4} を探します。

+ +

ユーザーが Enter ボタンを押した際に発動する Change イベントにより RegExp.input の値が設定されます。

+ +

HTML

+ +
<p>
+  電話番号(市外局番含む)を入力して "チェック" をクリックしてください。
+  <br>
+  適切な形式は ###-###-#### のようなものです。
+</p>
+<form action="#">
+  <input id="phone">
+    <button onclick="testInfo(document.getElementById('phone'));">チェック</button>
+</form>
+ +

JavaScript

+ +
var re = /(?:\d{3}|\(\d{3}\))([-\/\.])\d{3}\1\d{4}/;
+function testInfo(phoneInput) {
+  var OK = re.exec(phoneInput.value);
+  if (!OK) {
+    console.error(phoneInput.value + ' は市外局番付電話番号ではありません!');
+  } else {
+    console.log('ありがとう、あなたの電話番号は ' + OK[0]);}
+} 
+ +

結果

+ +
+

{{ EmbedLiveSample('Using_Special_Characters_to_Verify_Input', '', '', '', 'Web/JavaScript/Guide/Regular_Expressions') }}

+ +

仕様

+ + + + + + + + + + + + + + +
仕様策定状況コメント
{{SpecName('ESDraft', '#sec-regexp-regular-expression-objects', 'RegExp')}}{{Spec2('ESDraft')}}
+ +

ブラウザサポート

+ +
+ + +

{{Compat("javascript.builtins.RegExp")}}

+
+
+ +
{{PreviousNext("Web/JavaScript/Guide/Text_formatting", "Web/JavaScript/Guide/Indexed_collections")}}
diff --git a/files/ja/web/javascript/guide/regular_expressions/quantifiers/index.html b/files/ja/web/javascript/guide/regular_expressions/quantifiers/index.html new file mode 100644 index 0000000000..273fc82ff1 --- /dev/null +++ b/files/ja/web/javascript/guide/regular_expressions/quantifiers/index.html @@ -0,0 +1,152 @@ +--- +title: 数量詞 +slug: Web/JavaScript/Guide/Regular_Expressions/Quantifiers +tags: + - JavaScript + - Reference + - Regular Expressions + - quantifiers + - regex +translation_of: Web/JavaScript/Guide/Regular_Expressions/Quantifiers +--- +

{{jsSidebar("JavaScript Guide")}}{{draft}}

+ +

数量詞はマッチする文字や式の数を示します。

+ +

種類

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
x* +

直前の文字 x の 0 回以上の繰り返しにマッチします。例えば /bo*/ は "A ghost booooed" の "boooo" や "A bird warbled" の "b" にマッチしますが、"A goat grunted" ではマッチしません。

+
x+ +

直前の文字 x の 1 回以上の繰り返しにマッチします。{1,} に相当します。例えば /a+/ は "candy" の "a" や "caaaaaaandy" のすべての "a" にマッチします。

+
x? +

直前の文字 x の 0 回か 1 回の出現にマッチします。例えば /e?le?/ は "angel" の "el" や "angle" の "le"、あるいは "oslo" の "l" にマッチします。

+ +

*+?{} といった量指定子の直後に使用した場合、その量指定子をデフォルトとは逆の{{原語併記("非貪欲", "non-greedy")}} (最短)マッチにします。デフォルトは{{原語併記("欲張り", "greedy")}}(最長)マッチです。

+
x{n} +

n には正の整数が入ります。直前の文字 x がちょうど n 回出現するものにマッチします。例えば /a{2}/ は "candy" の "a" にはマッチしませんが、"caaandy" の最初の 2 個の "a" にはマッチします。

+
x{n,} +

n には正の整数が入ります。直前の文字 x の少なくとも n 回の出現にマッチします。例えば、/a{2,}/ は "candy" の "a" にはマッチしませんが、"caandy" や "caaaaaaandy" の "a" のすべてにマッチします。

+
x{n,m} +

n には 0 と正の整数が、m には n より大きい正の整数が入ります。直前の文字 x が少なくとも n 回、多くても m 回出現するものにマッチします。例えば /a{1,3}/ は "cndy" ではマッチせず、"candy" の 'a'、"caandy" の 最初の 2 個の "a"、"caaaaaaandy" の最初の 3 個の "a" にマッチします。"caaaaaaandy" では元の文字列に "a" が 4 個以上ありますが、マッチするのは "aaa" であることに注意してください。

+
+

x*?
+ x+?
+ x??
+ x{n}?
+ x{n,}?
+ x{n,m}?

+
+

既定では *+ といった数量詞は{{原語併記("貪欲", "greedy")}} です。つまり、できる限り多くの文字列とマッチしようとします。数量詞の後にある ? 文字は{{原語併記("非貪欲", "non-greedy")}} 数量詞をつくります: つまり、マッチが見つかるとすぐに停止します。例えば、"some <foo> <bar> new </bar> </foo> thing" といった文字列が与えられたなら:

+ +
    +
  • /<.*>/ はおそらく "<foo> <bar> new </bar> </foo>" にマッチするでしょう
  • +
  • /<.*?>/ はおそらく "<foo>" にマッチするでしょう
  • +
+
+ +

+ +

任意の文字

+ +
var britishText = "He asked his neighbour a favour.";
+var americanText = "He asked his neighbor a favor.";
+
+var regexpEnding = /\w+ou?r/g;
+// \w+ 1つ以上の文字
+// o   "o" が続く
+// u?  任意で "u" が続く
+// r   "r" が続く
+
+console.table(britishText.match(regexpEnding));
+// ["neighbour", "favour"]
+
+console.table(americanText.match(regexpEnding));
+// ["neighbor", "favor"]
+
+ +

貪欲と非貪欲の比較

+ +
var text = "I must be getting somewhere near the centre of the earth.";
+var greedyRegexp = /[\w ]+/;
+// [\w ]      ラテンアルファベットまたは空白
+//      +     1回以上
+
+console.log(text.match(greedyRegexp)[0]);
+// "I must be getting somewhere near the centre of the earth."
+// テキストのすべてがマッチ
+
+var nonGreedyRegexp = /[\w ]+?/; // クエスチョンマークに注目
+console.log(text.match(nonGreedyRegexp));
+// "I"
+// マッチは可能なもので最小
+
+ +

仕様

+ + + + + + + + + + + + + + +
仕様策定状況コメント
{{SpecName('ESDraft', '#sec-quantifier', 'RegExp: Quantifiers')}}{{Spec2('ESDraft')}}
+ +

ブラウザサポート

+ +
+ + +

{{Compat("javascript.builtins.RegExp.quantifiers")}}

+
+ +

関連情報

+ + diff --git a/files/ja/web/javascript/guide/text_formatting/index.html b/files/ja/web/javascript/guide/text_formatting/index.html new file mode 100644 index 0000000000..9df0e489e9 --- /dev/null +++ b/files/ja/web/javascript/guide/text_formatting/index.html @@ -0,0 +1,256 @@ +--- +title: テキスト処理 +slug: Web/JavaScript/Guide/Text_formatting +tags: + - Guide + - JavaScript + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Text_formatting +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
+ +

本章では JavaScript で文字列やテキストを操作する方法を紹介します。

+ +

文字列

+ +

JavaScript の{{Glossary("String","文字列")}}型はテキストデータを表すために使われます。テキストデータ型は 16 ビット符号なし整数値 (UTF-16) からなる「要素」の集合体です。文字列の各要素は、その文字列内で所定の位置を占めています。最初の要素のインデックスは 0 で、次の要素のインデックスは 1 、といった具合に。文字列の長さはその要素数となります。文字列リテラルか文字列オブジェクトを使用して文字列を生成できます。

+ + + +

文字列リテラル

+ +

単一引用符または二重引用符のいずれかを使用して、単純な文字列を作成できます :

+ +
'foo'
+"bar"
+ +

また、エスケープシーケンスを使用してより高度な文字列を作成できます :

+ +

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

+ +

\x の後の数値は 16 進法による数として解釈されます。

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

Unicode エスケープシーケンス

+ +

Unicode エスケープシーケンスは \u の後に少なくとも文字が 4 個必要です。

+ +
'\u00A9' // "©"
+ +

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

+ +

ECMAScript 2015 の新機能です。Unicode コードポイントエスケープを使えば、どんな文字でも 16 進数を使用してエスケープすることができます。これにより、0x10FFFF まで Unicode コードポイントを利用できます。単純な Unicode エスケープを使用して同じ結果を得るには、多くの場合要素を半分に分け、サロゲートペアにする必要があります。

+ +

{{jsxref("String.fromCodePoint()")}} や {{jsxref("String.prototype.codePointAt()")}} も参考にしてください。

+ +
'\u{2F804}'
+
+// 単純な Unicode エスケープでも同じです。
+'\uD87E\uDC04'
+ +

String オブジェクト

+ +

{{jsxref("String")}} オブジェクトは文字列プリミティブデータ型のためのラッパです。

+ +
const foo = new String('foo'); // 文字列オブジェクトを作る
+console.log(foo); // Displays: [String: 'foo']
+typeof foo; // Returns 'object'
+
+ +

文字列リテラル値に対しても String オブジェクトのメソッドを呼び出すことができます ― JavaScript は自動的に文字列リテラルを一時的な String オブジェクトに変換し、メソッドを呼び出し、そして一時的に作られた String オブジェクトを破棄します。文字列リテラルでは String.length プロパティも利用できます。

+ +

String オブジェクトを使用する明確な必要性がなければ、文字列リテラルを使用してください。というのも、String オブジェクトは直感的でない振る舞いをします。例えば :

+ +
const firstString = '2 + 2'; // 文字列リテラル値を作成
+const secondString = new String('2 + 2'); // 文字列オブジェクトを作成
+eval(firstString); // 数値の 4 を返す
+eval(secondString); // 文字列 "2 + 2" を返す
+ +

String オブジェクトのプロパティの 1 つには、文字列内の UTF-16 コード単位の数を示す length があります。例えば、次のコードでは、helloLength には値 13 が代入されます。"Hello, World!" は 13 文字で、それぞれが 1 つの UTF-16 コード単位で表されるからです。配列の角括弧書式を使用して、各コード単位にアクセスできます。文字列は不変の配列のようなオブジェクトなので、個々の文字を変更することはできません:

+ +
const hello = 'Hello, World!';
+const helloLength = hello.length;
+hello[0] = 'L'; // 文字列は不変なので、これは効果がありません
+hello[0]; // これは "H" を返します
+
+ +

Unicode のスカラー値が U+FFFF より大きい文字 (中国語/日本語/韓国語/ベトナム語の特殊な文字や絵文字など) は、それぞれ 2 つのサロゲートコード単位で UTF-16 に格納されます。たとえば、単一の文字 U+1F600 (笑顔の絵文字) から成る文字列の長さは 2 になります。このような文字列の括弧で囲まれた個々のコード単位にアクセスすると、一致しないサロゲートコード単位の文字列が生成されるなど、Unicode 標準違反という好ましくない結果になります。(その例は、MDN のバグ 857438 が修正された後にこのページに追加する必要があります。) {{jsxref("String.fromCodePoint()")}} または{{jsxref("String.prototype.codePointAt()")}} も参照してください。

+ +

String オブジェクトはさまざまなメソッドを持っています。例えば、substringtoUpperCase のような文字列自体のバリエーションを返すメソッドがあります。

+ +

次の表は {{jsxref("String")}} オブジェクトのメソッドをまとめたものです。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+

String のメソッド

+
メソッド説明
{{jsxref("String.charAt", "charAt")}}、{{jsxref("String.charCodeAt", "charCodeAt")}}、{{jsxref("String.codePointAt", "codePointAt")}}文字列内の指定された位置の文字または文字コードを返します。
{{jsxref("String.indexOf", "indexOf")}}, {{jsxref("String.lastIndexOf", "lastIndexOf")}}それぞれ、文字列内にある指定された部分文字列の先頭位置、および末尾の位置を返します。
{{jsxref("String.startsWith", "startsWith")}}, {{jsxref("String.endsWith", "endsWith")}}, {{jsxref("String.includes", "includes")}}文字列が指定した文字列で始まるか、終わるか、それを含むかどうかを返します。
{{jsxref("String.concat", "concat")}}2 つの文字列をテキストとしてつなげた新しい文字列を返します。
{{jsxref("String.fromCharCode", "fromCharCode")}}, {{jsxref("String.fromCodePoint", "fromCodePoint")}}指定の Unicode 値シーケンスから文字列を構築します。これは、String インスタンスではなく、String クラスにあるメソッドです。
{{jsxref("String.split", "split")}}文字列を部分文字列へと分けることで、String オブジェクトを文字列の配列に分割します。
{{jsxref("String.slice", "slice")}}文字列の一部分を取り出し、新しい文字列を返します。
{{jsxref("String.substring", "substring")}}, {{jsxref("String.substr", "substr")}}開始インデックスから終了インデックスまで、または開始インデックスと長さ、このいずれかを指定することで文字列における特定の部分集合を返します。
{{jsxref("String.match", "match")}}, {{jsxref("String.matchAll", "matchAll")}}, {{jsxref("String.replace", "replace")}}, {{jsxref("String.replaceAll", "replaceAll")}}, {{jsxref("String.search", "search")}}正規表現と共に機能します。
{{jsxref("String.toLowerCase", "toLowerCase")}}, {{jsxref("String.toUpperCase", "toUpperCase")}} +

それぞれ、すべて小文字またはすべて大文字にした文字列を返します。

+
{{jsxref("String.normalize", "normalize")}}呼び出し元となる文字列値の Unicode 正規化形式を返します。
{{jsxref("String.repeat", "repeat")}}所定回数繰り返したオブジェクト要素からなる文字列を返します。
{{jsxref("String.trim", "trim")}}文字列の先頭と末尾から空白文字を取り除きます。
+ +

マルチラインテンプレート文字列

+ +

テンプレート文字列は式を埋め込むことができる文字列リテラルです。複数行の文字列や文字列の補間機能で使用することができます。

+ +

テンプレート文字列は二重引用符または一重引用符のかわりにバックティック (` `) (抑音アクセント)文字で囲まれています。テンプレート文字列にはプレースホルダーを含めることができます。プレースホルダーはドル記号と波括弧 (${expression}) によって示されます。

+ +

マルチライン

+ +

ソースに挿入されたいかなる改行文字も、テンプレート文字列の一部となります。通常の文字列を使って複数行の文字列を取得するには、次のような構文を使用しなければなりません :

+ +
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"
+ +

組み込み式

+ +

通常の文字列内に式を埋め込むには、次のような構文を用います :

+ +
const five = 5;
+const ten = 10;
+console.log('Fifteen is ' + (five + ten) + ' and not ' + (2 * five + ten) + '.');
+// "Fifteen is 15 and not 20."
+ +

テンプレート文字列を使えば、糖衣構文を利用してこれをより読みやすくすることができます。:

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

詳細については、JavaScript リファレンス内のテンプレート文字列をご覧ください。

+ +

国際化

+ +

{{jsxref("Intl")}} オブジェクトは ECMAScript 国際化 API のための名前空間です。ECMAScript 国際化 API は、各言語に応じた文字列比較、数値フォーマット、日時フォーマットを提供します。{{jsxref("Collator")}}、{{jsxref("NumberFormat")}}、{{jsxref("DateTimeFormat")}} オブジェクトのコンストラクタは Intl オブジェクトのプロパティとなっています。

+ +

日時フォーマット

+ +

{{jsxref("DateTimeFormat")}} オブジェクトは日時をフォーマットするのに便利です。次の例では、日付をアメリカ英語のフォーマットにします(結果は別のタイムゾーンで異なります)。

+ +
const msPerDay = 24 * 60 * 60 * 1000;
+
+// July 17, 2014 00:00:00 UTC.
+const july172014 = new Date(msPerDay * (44 * 365 + 11 + 197));
+
+const options = { year: '2-digit', month: '2-digit', day: '2-digit',
+                hour: '2-digit', minute: '2-digit', timeZoneName: 'short' };
+const americanDateTime = new Intl.DateTimeFormat('en-US', options).format;
+
+console.log(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT
+
+ +

数値フォーマット

+ +

{{jsxref("NumberFormat")}} オブジェクトは数値、例えば通貨をフォーマットするのに有用です。

+ +
const gasPrice = new Intl.NumberFormat('en-US',
+                        { style: 'currency', currency: 'USD',
+                          minimumFractionDigits: 3 });
+
+console.log(gasPrice.format(5.259)); // $5.259
+
+const hanDecimalRMBInChina = new Intl.NumberFormat('zh-CN-u-nu-hanidec',
+                        { style: 'currency', currency: 'CNY' });
+
+console.log(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五
+
+ + +

照合

+ +

{{jsxref("Collator")}} オブジェクトは文字列を比較しソートするのに便利です。

+ +

例えば、ドイツ語には二つの異なるソート順、phonebook(電話帳順)と dictionary(辞書順)が存在します。電話帳順ソートは音を強調し、ソート前に “ä”、“ö” といった文字があたかも “ae”、“oe” などであるかのように解釈されます。

+ +
const names = ['Hochberg', 'Hönigswald', 'Holzman'];
+
+const germanPhonebook = new Intl.Collator('de-DE-u-co-phonebk');
+
+// ["Hochberg", "Hoenigswald", "Holzman"] としてソートされる:
+console.log(names.sort(germanPhonebook.compare).join(', '));
+// "Hochberg, Hönigswald, Holzman" がログ出力される
+
+ +

ドイツ語の単語の中にはウムラウト記号によって変化するものがあるため、辞書順では(schön の前は schon といったような、ウムラウトのみ異なるような単語をソートする場合を除けば)ウムラウトを無視してソートするのが賢明です。

+ +
const germanDictionary = new Intl.Collator('de-DE-u-co-dict');
+
+// ["Hochberg", "Honigswald", "Holzman"] としてソートされる:
+console.log(names.sort(germanDictionary.compare).join(', '));
+// "Hochberg, Holzman, Hönigswald" とログ出力される
+
+ +

{{jsxref("Intl")}} API の詳細については、Introducing the JavaScript Internationalization API もご覧ください。

+ +
{{PreviousNext("Web/JavaScript/Guide/Numbers_and_dates", "Web/JavaScript/Guide/Regular_Expressions")}}
diff --git a/files/ja/web/javascript/guide/the_employee_example/creating_the_hierarchy/index.html b/files/ja/web/javascript/guide/the_employee_example/creating_the_hierarchy/index.html new file mode 100644 index 0000000000..2340536ff7 --- /dev/null +++ b/files/ja/web/javascript/guide/the_employee_example/creating_the_hierarchy/index.html @@ -0,0 +1,134 @@ +--- +title: Creating the Hierarchy +slug: Web/JavaScript/Guide/The_Employee_Example/Creating_the_Hierarchy +--- +

階層の作成

+

Employee の階層を実装するための適当なコンストラクタ関数を定義する方法はいくつかあります。これの定義に何を選択するかは、アプリケーションで何ができるようにしたいかに大きくよります。

+

このセクションではとても単純(かつ比較的柔軟でない)定義の使用方法を示し、継承を機能させる方法を実際に示します。これらの定義では、オブジェクト作成時に何らかのプロパティの値を指定することはできません。新しく作成されるオブジェクトは単にデフォルトの値を取得するだけです。これは後から変更できます。図 8.2 ではこれらの単純な定義を備えた階層を例示します。

+

実際のアプリケーションでは、オブジェクト作成時にプロパティの値を設定できるようにするコンストラクタを定義することになるでしょう(詳しくは より柔軟なコンストラクタ を参照)。今回はこれらの単純な定義を使用して、継承はどのようにして起こるのかを実際に示していくことにします。

+

Image:hier02.gif
+ 図 8.2:Employee オブジェクトの定義

+

以下に示すように、Java と JavaScript の Employee の定義は似ています。唯一の相違点は、Java では各プロパティに対して型を指定する必要があるのに対して、JavaScript ではその必要がないことです。また、Java のクラスでは明示的なコンストラクタメソッドを作成する必要があります。

+ + + + + + + + + + + +
JavaScriptJava
+
+function Employee () {
+this.name = "";
+this.dept = "general";
+}
+
+
+
+public class Employee {
+   public String name;
+   public String dept;
+   public Employee () {
+      this.name = "";
+      this.dept = "general";
+   }
+}
+
+
+

Manager および WorkerBee の定義では、継承の連鎖において上である次のオブジェクトの指定方法に違いがあります。JavaScript では原型的なインスタンスをコンストラクタ関数の prototype プロパティとして追加します。コンストラクタを定義した後ならいつでもそれをすることができます。Java ではクラス定義内でスーパークラスを指定します。クラス定義の外部でスーパークラスを変更することはできません。

+ + + + + + + + + + + +
JavaScriptJava
+
+function Manager () {
+this.reports = [];
+}
+Manager.prototype = new Employee;
+
+function WorkerBee () {
+this.projects = [];
+}
+WorkerBee.prototype = new Employee;
+
+
+
+public class Manager extends Employee {
+   public Employee[] reports;
+   public Manager () {
+      this.reports = new Employee[0];
+   }
+}
+
+public class WorkerBee extends Employee {
+   public String[] projects;
+   public WorkerBee () {
+      this.projects = new String[0];
+   }
+}
+
+
+

Engineer および SalesPerson の定義は、WorkerBee の子孫、それゆえに Employee の子孫であるオブジェクトを作成します。これらの種類のオブジェクトは連鎖において上にある全オブジェクトのプロパティを持ちます。さらに、これらの定義は dept プロパティの継承された値をこれらのオブジェクト固有の新しい値で上書きします。

+ + + + + + + + + + + +
JavaScriptJava
+
+function SalesPerson () {
+   this.dept = "sales";
+   this.quota = 100;
+}
+SalesPerson.prototype = new WorkerBee;
+
+function Engineer () {
+   this.dept = "engineering";
+   this.machine = "";
+}
+Engineer.prototype = new WorkerBee;
+
+
+
+public class SalesPerson extends WorkerBee {
+   public double quota;
+   public SalesPerson () {
+      this.dept = "sales";
+      this.quota = 100.0;
+   }
+}
+
+public class Engineer extends WorkerBee {
+   public String machine;
+   public Engineer () {
+      this.dept = "engineering";
+      this.machine = "";
+   }
+}
+
+
+

これらの定義を使用して、そのプロパティのデフォルト値を取得するこれらのオブジェクトのインスタンスを作成することができます。図 8.3 ではこれらの JavaScript の定義を使用して新しいオブジェクトを作成する方法を示しています。また、新しいオブジェクトに対するプロパティの値も示しています。

+

注意インスタンスという用語はクラスベース言語においてはある特定の技術的な意味を持っています。これらの言語では、インスタンスとはクラスの個々のメンバであり、クラスとは根本的に異なるものです。JavaScript では「インスタンス」はこの技術的な意味を持っていません。なぜならば JavaScript にはクラスとインスタンスとの間のこの違いがないからです。しかしながら、JavaScript について話す際に、「インスタンス」をある特定のコンストラクタ関数を用いて作成したオブジェクトを意味する言葉として正式ではない形で使用することがあります。例えば、janeEngineer のインスタンスであると砕けた言い方をすることもできます。同様に、祖先、そして子孫という用語は JavaScript において正式な意味を持ちませんが、プロトタイプチェーンにおいて上や下にあるオブジェクトについて言及する際にそれらを正式ではない形で使用してもかまいません。

+

Image:hier03.gif
+ 図 8.3:単純な定義を用いたオブジェクトの作成

+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:The_Employee_Example", "Core_JavaScript_1.5_Guide:The_Employee_Example:Object_Properties") }}

+
diff --git a/files/ja/web/javascript/guide/the_employee_example/index.html b/files/ja/web/javascript/guide/the_employee_example/index.html new file mode 100644 index 0000000000..63176fa7e2 --- /dev/null +++ b/files/ja/web/javascript/guide/the_employee_example/index.html @@ -0,0 +1,31 @@ +--- +title: The Employee Example +slug: Web/JavaScript/Guide/The_Employee_Example +--- +

従業員の例

+

この章の残りは次の図で示す従業員の階層を使用していきます。

+

Image:hier01.gif

+

図 8.1:単純なオブジェクト階層

+

これの例では以下のオブジェクトを使用しています。

+ +

残りの例:

+ +
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:Class-Based_vs._Prototype-Based_Languages", "Core_JavaScript_1.5_Guide:The_Employee_Example:Creating_the_Hierarchy") }}

+
+

 

diff --git a/files/ja/web/javascript/guide/the_employee_example/object_properties/adding_properties/index.html b/files/ja/web/javascript/guide/the_employee_example/object_properties/adding_properties/index.html new file mode 100644 index 0000000000..c6d536602b --- /dev/null +++ b/files/ja/web/javascript/guide/the_employee_example/object_properties/adding_properties/index.html @@ -0,0 +1,19 @@ +--- +title: Adding Properties +slug: Web/JavaScript/Guide/The_Employee_Example/Object_Properties/Adding_Properties +--- +

プロパティの追加

+

JavaScript では実行時にどんなオブジェクトにもプロパティを追加することができます。コンストラクタ関数で与えられるプロパティだけを使う必要はありません。ある 1 つのオブジェクト固有のプロパティを追加するには、次のようにしてオブジェクトに値を代入します。

+
mark.bonus = 3000;
+
+

すると、mark オブジェクトには bonus プロパティができます。しかし、他のどの WorkerBee にもこのプロパティは存在しません。

+

あるコンストラクタ関数に対するプロトタイプとして使用されているオブジェクトに新しいプロパティを追加する場合、プロトタイプからプロパティを継承する全オブジェクトへそのプロパティを追加することになります。例えば、次の文を使用すると specialty プロパティをすべての従業員に対して追加することができます。

+
Employee.prototype.specialty = "none";
+
+

JavaScript がこの文を実行するとすぐに mark オブジェクトも "none" という値を持つ specialty プロパティを持つようになります。次の図ではこのプロパティを Employee プロトタイプに追加し、さらに Engineer プロトタイプに対するそれを上書きしたときの効果を示します。

+

Image:hier04.gif
+ 図 8.4:プロパティの追加

+
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:The_Employee_Example:Object_Properties:Inheriting_Properties", "Core_JavaScript_1.5_Guide:The_Employee_Example:More_Flexible_Constructors") }}

+
+

 

diff --git a/files/ja/web/javascript/guide/the_employee_example/object_properties/index.html b/files/ja/web/javascript/guide/the_employee_example/object_properties/index.html new file mode 100644 index 0000000000..e529b8bb52 --- /dev/null +++ b/files/ja/web/javascript/guide/the_employee_example/object_properties/index.html @@ -0,0 +1,13 @@ +--- +title: Object Properties +slug: Web/JavaScript/Guide/The_Employee_Example/Object_Properties +--- +

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

+

このセクションでは、プロトタイプチェーンにおいてオブジェクトが他のオブジェクトからどのようにプロパティを継承するのか、また、実行時にプロパティを追加すると何が起きるのかについて論じます。

+ +
+

{{ PreviousNext("Core_JavaScript_1.5_Guide:The_Employee_Example:Creating_the_Hierarchy", "Core_JavaScript_1.5_Guide:The_Employee_Example:Object_Properties:Inheriting_Properties") }}

+
diff --git a/files/ja/web/javascript/guide/the_employee_example/object_properties/inheriting_properties/index.html b/files/ja/web/javascript/guide/the_employee_example/object_properties/inheriting_properties/index.html new file mode 100644 index 0000000000..798746ead6 --- /dev/null +++ b/files/ja/web/javascript/guide/the_employee_example/object_properties/inheriting_properties/index.html @@ -0,0 +1,24 @@ +--- +title: Inheriting Properties +slug: >- + Web/JavaScript/Guide/The_Employee_Example/Object_Properties/Inheriting_Properties +--- +

プロパティの継承

+

次の文を用いて(図 8.3 で示したように)mark オブジェクトを WorkerBee として作成するとします。

+
mark = new WorkerBee;
+
+

JavaScript は new 演算子に出くわすと、新しく汎用オブジェクトを生成し、この新しいオブジェクトを this キーワードの値として WorkerBee コンストラクタ関数に渡します。コンストラクタ関数は明示的に projects プロパティの値をセットします。さらに、内部的な __proto__ プロパティの値として WorkerBee.prototype の値をセットします。(このプロパティ名は最初と最後に 2 文字ずつのアンダースコアが付いています。)__proto__ プロパティはプロパティの値を返すのに使用されるプロトタイプチェーンを決定します。これらのプロパティがセットされると JavaScript は新しいオブジェクトを返し、代入文は変数 mark にそのオブジェクトをセットします。

+

このプロセスでは mark がプロトタイプチェーンから継承するプロパティとして明示的には mark オブジェクトに値(ローカルの値)を格納しません。プロパティの値を使用するとき、JavaScript はまずその値がそのオブジェクトに存在しているかどうかを確認します。存在している場合はその値が返されます。値がローカルには存在していない場合、JavaScript はプロトタイプチェーンを確認します(__proto__ プロパティを使用)。プロトタイプチェーン内のオブジェクトがそのプロパティの値を持っている場合、その値が返されます。そのようなプロパティが見つからない場合は JavaScript はそのオブジェクトにはそのプロパティがないと報告します。このようにして、mark オブジェクトには次のようなプロパティと値が入ることになります。

+
mark.name = "";
+mark.dept = "general";
+mark.projects = [];
+
+

mark オブジェクトは mark.__proto__ の原型的なオブジェクトから name および dept プロパティの値を継承します。WorkerBee コンストラクタによって projects プロパティにローカルの値が代入されます。このことでプロパティとその値を継承することができます。このプロセスの細かいところは プロパティの継承、再び にて議論します。

+

これらのコンストラクタにインスタンス固有の値を渡せないため、この情報は汎用的になります。プロパティの値は WorkerBee によって作成されるすべての新しいオブジェクトに共有される、デフォルトの値になります。もちろん、これらのどのプロパティのでもその値を変えることができます。そのためには次のようにして mark に固有の情報を与えます。

+
mark.name = "Doe, Mark";
+mark.dept = "admin";
+mark.projects = ["navigator"];
+
+
+

{{ PreviousNext("Core JavaScript 1.5 Guide:The Employee Example:Object Properties", "Core JavaScript 1.5 Guide:The Employee Example:Object Properties:Adding Properties") }}

+
diff --git a/files/ja/web/javascript/guide/using_promises/index.html b/files/ja/web/javascript/guide/using_promises/index.html new file mode 100644 index 0000000000..df6cd820bc --- /dev/null +++ b/files/ja/web/javascript/guide/using_promises/index.html @@ -0,0 +1,358 @@ +--- +title: Promiseを使う +slug: Web/JavaScript/Guide/Using_promises +tags: + - Guide + - Intermediate + - JavaScript + - Promise + - Promises + - asynchronous + - 'l10n:priority' +translation_of: Web/JavaScript/Guide/Using_promises +--- +
{{jsSidebar("JavaScript Guide")}}
+ +

{{jsxref("Promise")}} は非同期処理の最終的な完了もしくは失敗を表すオブジェクトです。多くの人々は既存の用意された Promise を使うことになるため、このガイドでは、Promise の作成方法の前に、関数が返す Promise の使い方から説明します。

+ +

本質的に、Promise はコールバックを関数に渡すかわりに、関数が返したオブジェクトに対してコールバックを登録するようにする、というものです。

+ +

例えば createAudioFileAsync() という非同期に音声ファイルを生成する関数を考えましょう。この関数はコンフィグオブジェクトと 2 つのコールバック関数を受け取り、片方のコールバックは音声ファイルが無事作成されたときに呼び出され、もう一つはエラーが発生したときに呼び出されます。

+ +

以下のコードは createAudioFileAsync() を使用したものです。

+ +
function successCallback(result) {
+  console.log("Audio file ready at URL: " + result);
+}
+
+function failureCallback(error) {
+  console.log("Error generating audio file: " + error);
+}
+
+createAudioFileAsync(audioSettings, successCallback, failureCallback);
+ +

最近では関数は Promise を返し、代わりにその Promise にコールバックを登録することができます。

+ +

もし createAudioFileAsync() が Promise を返すように書き換えられたとすれば、以下のようにシンプルに使用することができます。

+ +
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
+ +

これは以下のコードの短縮形です。

+ +
const promise = createAudioFileAsync(audioSettings);
+promise.then(successCallback, failureCallback);
+ +

これを非同期関数呼び出し(asynchronnous function call)と呼びます。この記述方法にはいくつか利点があるので、順に説明します。

+ +

保証

+ +

旧来のコールバック渡しとは異なり、Promise では以下が保証されています。

+ + + +

とはいえ、最もすぐわかる Promise の利点は Promise チェーンでしょう。

+ +

Promise チェーン

+ +

一般的なニーズとしては、複数の非同期処理を順番に実行し、前の処理が完了してからその結果を次の処理で使うというものがあります。これは Promise チェーンを作成することで行えます。

+ +

さあ魔法の時間です。then() 関数は元の Promise とは別の新しい Promise を返します。

+ +
const promise = doSomething();
+const promise2 = promise.then(successCallback, failureCallback);
+
+ +

もしくは、以下のように書いても構いません。

+ +
const promise2 = doSomething().then(successCallback, failureCallback);
+
+ +

2 つ目の Promise は doSomething() の完了を表すだけではなく、渡した successCallback もしくは failureCallback の完了も表し、これらのコールバックは Promise を返すまた別の非同期関数であっても構いません。その場合、promise2 に追加されたコールバックはいずれも Promise のキューにおいて、successCallback または failureCallback が返す Promise の後ろに追加されます。

+ +

基本的に、それぞれの Promise はチェーン(連鎖)上の各非同期処理の完了を表します。

+ +

昔は、複数の非同期処理を順番に実行するには、従来のコールバック地獄を作ることになりました。

+ +
doSomething(function(result) {
+  doSomethingElse(result, function(newResult) {
+    doThirdThing(newResult, function(finalResult) {
+      console.log('Got the final result: ' + finalResult);
+    }, failureCallback);
+  }, failureCallback);
+}, failureCallback);
+
+ +

モダンな関数を使えば、その代わりに戻り値の Promise にコールバックを付加して Promise チェーンとして記述できます。

+ +
doSomething()
+.then(function(result) {
+  return doSomethingElse(result);
+})
+.then(function(newResult) {
+  return doThirdThing(newResult);
+})
+.then(function(finalResult) {
+  console.log('Got the final result: ' + finalResult);
+})
+.catch(failureCallback);
+
+ +

 then 関数の引数はオプション(必須ではない)です。また、catch(failureCallback)then(null, failureCallback) の短縮形です。記述にはアロー関数を使っても構いません。

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => {
+  console.log(`Got the final result: ${finalResult}`);
+})
+.catch(failureCallback);
+
+ +

重要: コールバック関数から処理結果を返すのを忘れないでください。さもないと後続のコールバック関数からその処理結果を利用することができなくなります (アロー関数を使った () => x は () => { return x; } の短縮形です)。

+ +

catch後のチェーン

+ +

失敗、つまり catch の後にチェーンするのも可能で、これはチェーン内の動作が失敗した後でも新しい動作を行うのに便利です。次の例を読んでください:

+ +
new Promise((resolve, reject) => {
+    console.log('Initial');
+
+    resolve();
+})
+.then(() => {
+    throw new Error('Something failed');
+
+    console.log('Do this');
+})
+.catch(() => {
+    console.log('Do that');
+})
+.then(() => {
+    console.log('Do this whatever happened before');
+});
+ +

これは下記のテキストを出力します:

+ +
Initial
+Do that
+Do this whatever happened before
+ +

注意:Do this のテキストは Something failed エラーが reject を引き起こしたため出力されないことに注意してください。

+ +

エラーの伝播

+ +

以前のコールバック地獄形式の記述方法では failureCallback を 3 回書く必要がありましたが、Promise チェーンでは failureCallback は 1 回で済みます。

+ +
doSomething()
+.then(result => doSomethingElse(result))
+.then(newResult => doThirdThing(newResult))
+.then(finalResult => console.log(`Got the final result: ${finalResult}`))
+.catch(failureCallback);
+
+ +

例外が発生すると、ブラウザーはチェーンをたどって .catch() ハンドラーか onRejected を探します。この振る舞いは同期的なコードの動作と非常によく類似しています。

+ +
try {
+  const result = syncDoSomething();
+  const newResult = syncDoSomethingElse(result);
+  const finalResult = syncDoThirdThing(newResult);
+  console.log(`Got the final result: ${finalResult}`);
+} catch(error) {
+  failureCallback(error);
+}
+
+ +

ECMAScript 2017 のシンタックスシュガー async/await を使えば、完全にそっくりのコードになります。

+ +
async function foo() {
+  try {
+    const result = await doSomething();
+    const newResult = await doSomethingElse(result);
+    const finalResult = await doThirdThing(newResult);
+    console.log(`Got the final result: ${finalResult}`);
+  } catch(error) {
+    failureCallback(error);
+  }
+}
+
+ +

async/await は Promise の上に成り立っています。例えば上記の doSomething() はこれまでと同じ(Promise を返す)関数です。この書き方の詳細についてはこちらをご覧ください。

+ +

Promise は例外やプログラミングエラーを含むすべてのエラーをとらえることで、コールバック地獄の根本的な問題を解決します。これは非同期処理を合成するのに不可欠です。

+ +

Promise の失敗イベント

+ +

Promise が失敗するたびに、グローバルスコープ(通常 {{domxref("window")}} オブジェクトか、Web Worker 内ならば Worker か Worker ベースのインターフェイスをもつオブジェクト)に以下の 2 つのイベントのどちらかが送られます:

+ +
+
rejectionhandled
+
Promise が失敗したとき、それが reject 関数などによって処理されたあとに送られる。
+
unhandledrejection
+
Promise が失敗して、ハンドラーが存在しないときに送られる。
+
+ +

いずれの場合でも、イベントオブジェクト( PromiseRejectionEvent 型)は失敗した Promise を表す promise プロパティと、その Promise が失敗した理由を表す reason プロパティを持ちます。

+ +

これらのイベントを使えば、Promise のエラーハンドラーのフォールバックを指定することができ、また Promise を管理する際の問題をデバッグするのにも役立ちます。これらのイベントのハンドラーはコンテキストごとにグローバルであり、どこから発生したかに関わらず、すべてのエラーは同じイベントハンドラーによって処理されます。

+ +

特に便利なケースとして、{{Glossary("Node.js")}} 用のコードを書いているときにプロジェクト内のモジュールで Promise が失敗しハンドルされないことがよくあります。これらは Node.js の実行環境によりコンソールに出力されます。これらの失敗を分析したりハンドラーを設定したいとき、あるいは単にコンソールがこれらで埋め尽くされないようにしたいとき、以下のように unhandledrejection イベントのハンドラーを追加することができます。

+ +
window.addEventListener("unhandledrejection", event => {
+  /* ここで該当の Promise を event.promise で、失敗の理由を
+     event.reason で取得して調べることができます */
+
+  event.preventDefault();
+}, false);
+ +

イベントの preventDefault() メソッドを呼び出すことによって、失敗した Promise がハンドルされないときの JavaScript の実行環境のデフォルトの動作を防ぐことができます。特に Node.js がそうですが、通常はデフォルトの動作ではエラーがコンソールに出力されます。

+ +

当然ながら理想的には、これらのイベントを捨てる前に失敗した Promise を調べて、いずれもコードのバグによるものではないことを確かめるべきです。

+ +

古いコールバック API をラップする Promise の作成

+ +

{{jsxref("Promise")}} はコンストラクタを使って 1 から作ることもできます。これは古い API をラップする場合にのみ必要となるはずです。

+ +

理想的には、すべての非同期関数は Promise を返すはずですが、残念ながら API の中にはいまだに古いやり方で成功/失敗用のコールバックを渡しているものがあります。典型的な例としては setTimeout() 関数があります。

+ +
setTimeout(() => saySomething("10 seconds passed"), 10*1000);
+
+ +

古い形式のコールバックと Promise の混在は問題を引き起こします。というのは、saySomething() が失敗したりプログラミングエラーを含んでいた場合にそのエラーをとらえられないからです。setTimeout にその責任があります。

+ +

幸いにも setTimeout を Promise の中にラップすることができます。ベストプラクティスは、問題のある関数を可能な限り低いレベルでラップした上で、二度と直接呼ばないようにするというものです。

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait(10*1000).then(() => saySomething("10 seconds")).catch(failureCallback);
+
+ +

基本的に、Promise のコンストラクタには、手動で Promise を resolve もしくは reject できるようにする実行関数を渡します。setTimeout() は失敗することはないので、reject は省略しました。

+ +

合成 (Composition)

+ +

{{jsxref("Promise.resolve()")}} と {{jsxref("Promise.reject()")}} はそれぞれ既に resolve もしくは reject された Promise を手動で作成するショートカットで、たまに役立つことがあります。

+ +

{{jsxref("Promise.all()")}} と {{jsxref("Promise.race()")}} は同時並行で実行中の非同期処理を合成するためのツールです。

+ +

以下のように複数の処理を並行に開始し、すべてが終了するのを待つことができます。

+ +
Promise.all([func1(), func2(), func3()])
+.then(([result1, result2, result3]) => { /* result1, result2, result3 が使える */ });
+ +

以下のように工夫すれば、逐次実行をする直列的な合成も記述することができます。

+ +
[func1, func2].reduce((p, f) => p.then(f), Promise.resolve())
+.then(result3 => { /* result3 が使える */ });
+ +

基本的に、これは非同期関数の配列を  Promise.resolve().then(func1).then(func2).then(func3); と同等の Promise チェーンへと reduce しています。

+ +

このような処理は以下のように、関数型プログラミングでよくある再利用可能な合成関数にすることがすることができます。

+ +
const applyAsync = (acc,val) => acc.then(val);
+const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
+ +

composeAsync 関数は任意の個数の関数を引数として受け取って、1本のパイプラインとして合成された関数を返します。この関数に渡された初期値は合成された関数を通過していきます。

+ +
const transformData = composeAsync(func1, func2, func3);
+const result3 = transformData(data);
+ +

ECMAScript 2017 では直列的な合成は async/await でもっと単純に書くことができます。

+ +
let result;
+for (const f of [func1, func2, func3]) {
+  result = await f(result);
+}
+/* 最終的な結果(result3)が使える */
+ +

タイミング

+ +

想定外の事態とならないよう、たとえすでに resolve された Promise であっても、then() に渡される関数が同期的に呼ばれることはありません。

+ +
Promise.resolve().then(() => console.log(2));
+console.log(1); // 1, 2
+
+ +

渡された関数は、すぐに実行されるのではなくマイクロタスクのキューに入れられます。現在のイベントループの終わりにこのキューは空になったときに、この関数が実行されます(つまりかなり早い段階です)。

+ +
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
+
+wait().then(() => console.log(4));
+Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
+console.log(1); // 1, 2, 3, 4
+ +

ネスト

+ +

単純な Promise チェーンならば、ネストは不用意な合成の結果生まれるものなので、ネストせずに平らにしておくのがベストです。よくある間違いを参照してください。

+ +

ネストとは catch ステートメントのスコープを制限するための制御構造です。正確には、ネストされた catch はそのスコープ内の失敗しかキャッチせず、Promise チェーン上でスコープ外のエラーには反応しません。正しく使えばより正確にエラーからの回復ができるようになります。

+ +
doSomethingCritical()
+.then(result => doSomethingOptional(result)
+  .then(optionalResult => doSomethingExtraNice(optionalResult))
+  .catch(e => {})) // オプションの処理が失敗すれば無視して進める
+.then(() => moreCriticalStuff())
+.catch(e => console.log("Critical failure: " + e.message));
+ +

インデントではなく外側の括弧 () によってオプションの処理がネストされていることに注意してください。

+ +

内側の catch ステートメントは doSomethingOptional() と doSomethingExtraNice() からの失敗だけをキャッチし、キャッチしたあと moreCriticalStuff() へと処理が続きます。重要なのは、もし doSomethingCritical() が失敗したらそのエラーは最後の catch によってだけキャッチされるということです。

+ +

よくある間違い

+ +

Promise チェーンを合成するときは以下のようなよくある間違いに気をつける必要があります。以下の例にいくつかの間違いが含まれています。

+ +
// 悪い例。間違いを 3 つ見つけてください。
+
+doSomething().then(function(result) {
+  doSomethingElse(result) // 内側のチェーンから Promise を返していない + 不必要なネスト
+  .then(newResult => doThirdThing(newResult));
+}).then(() => doFourthThing());
+// チェーンの最後を catch で終わらせていない
+
+ +

最初の間違いは適切にチェーンを構成できていないことです。これは、新しい Promise を作成したがそれを返すのを忘れているときに起きます。結果としてチェーンは壊れ、2 つのチェーンが独立に実行されることになります。これはつまり doFourthThing() は doSomethingElse() や doThirdThing() の終了を待たないことになり、おそらく意図せず並行して実行されることになります。別々のチェーンでは別々のエラーハンドリングが行われるため、キャッチされないエラーが発生することになります。

+ +

2 つ目の間違いは不必要にネストしていることであり、1 つめの間違いを可能にしているものでもあります。ネストするということは内側のエラーハンドラーが制限されるということであり、もしこれが意図していないものであれば、エラーがキャッチされないということが起こりえます。これの変化形で Promise コンストラクターアンチパターンというものがあり、ネストに加えて、Promise を既に使用しているコードを不必要な Promise コンストラクターでラップするというものです。

+ +

3 つ目の間違いはチェーンを catch で終わらせていないことです。ほとんどのブラウザーではそのようなチェーンは Promise の失敗がキャッチされないことになります。

+ +

よい経験則としては、Promise チェーンは常に return するか catch で終わらせ、新しい Promise を得るたびにすぐに return してチェーンを平らにすることです。

+ +
doSomething()
+.then(function(result) {
+  return doSomethingElse(result);
+})
+.then(newResult => doThirdThing(newResult))
+.then(() => doFourthThing())
+.catch(error => console.log(error));
+
+ +

() => x は () => { return x; } の短縮形であることに注意してください。

+ +

これで適切なエラーハンドリングがされた 1本のチェーンができました。

+ +

async/await を使えば、すべてではないにしてもほとんどの問題は解決しますが、このシンタックスで最もよくある間違いが await キーワードを忘れることであるという欠点があります。

+ +

Promises とタスクが衝突するとき

+ +

(イベントとコールバックのような) Promise とタスクが予知できない順序で発火するような状況に陥る場合、Promise が条件付きで作成されて Promise の状態をチェックしたり帳尻合わせしたりするマイクロタスクを利用できることがあります。

+ +

マイクロタスクでこの問題を解決できると考えたなら、microtask guide を見て、関数をマイクロタスクでキューに入れる queueMicrotask() の使い方を学んでください。

+ +

関連項目

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Details_of_the_Object_Model", "Web/JavaScript/Guide/Iterators_and_Generators")}}

diff --git a/files/ja/web/javascript/guide/using_the_arguments_object/index.html b/files/ja/web/javascript/guide/using_the_arguments_object/index.html new file mode 100644 index 0000000000..10c2d9e3ff --- /dev/null +++ b/files/ja/web/javascript/guide/using_the_arguments_object/index.html @@ -0,0 +1,36 @@ +--- +title: arguments オブジェクトの使用 +slug: Web/JavaScript/Guide/Using_the_arguments_object +--- +
+

arguments オブジェクトの使用

+

関数の引数は配列のようなオブジェクトで管理されます。関数内では、次のようにして渡された引数を指すことができます。

+
arguments[i]
+
+

ここで i は引数の順序を表す数を指します。これは 0 から始まります。関数に渡された第 1 引数は arguments{{ mediawiki.external(0) }} となります。引数のトータルの数は arguments.length で示されます。

+

arguments オブジェクトを使用すると、宣言時の仮引数の数よりも多くの引数を使って関数を呼び出すことができます。これはその関数に渡す引数の数が前もってわかっていない場合に役立ちます。arguments.length を使用することで実際にその関数に渡された引数の数を特定することができます。また、arguments オブジェクトを使用することで各引数を扱うことができます。

+

例えば、複数の文字列を連結する関数を考えます。この関数の仮引数は、連結するアイテムを区切るのに用いる文字列のみです。この関数は次のように定義されています。

+
function myConcat(separator) {
+   var result = ""; // リストを初期化する
+   // 引数について繰り返し
+   for (var i = 1; i < arguments.length; i++) {
+      result += arguments[i] + separator;
+   }
+   return result;
+}
+
+

この関数に引数をいくつも渡すことができます。そして各引数を文字列のリストに連結します。

+
// "red, orange, blue, " を返す
+myConcat(", ", "red", "orange", "blue");
+
+// "elephant; giraffe; lion; cheetah; " を返す
+myConcat("; ", "elephant", "giraffe", "lion", "cheetah");
+
+// "sage. basil. oregano. pepper. parsley. " を返す
+myConcat(". ", "sage", "basil", "oregano", "pepper", "parsley");
+
+

さらなる情報については、コア JavaScript リファレンスの Function オブジェクト をご覧ください。

+

JavaScript 1.3 以前のバージョン
+ arguments オブジェクトは Function オブジェクトのプロパティであり、次のように関数の名前を前に付けることができます。

+ functionName.arguments{{ mediawiki.external('i') }}
+

{{ PreviousNext("JavaScript/Guide/Calling_Functions", "JavaScript/Guide/Predefined_Functions") }}

diff --git a/files/ja/web/javascript/guide/variables/index.html b/files/ja/web/javascript/guide/variables/index.html new file mode 100644 index 0000000000..cebaecc949 --- /dev/null +++ b/files/ja/web/javascript/guide/variables/index.html @@ -0,0 +1,62 @@ +--- +title: 変数 +slug: Web/JavaScript/Guide/Variables +--- +

{{ 英語版章題("Variables") }}

+

変数

+

アプリケーションで値を識別する名前として変数を使用します。変数の名前はあるルールに従って付けなくてはなりません。変数の名前は識別子とも呼ばれます。

+

JavaScript の識別子は必ずアルファベットかアンダースコア (_) かドル記号 ($) から始まらなくてはなりません。続く文字は数字 (0-9) も使えます。JavaScript は大文字・小文字を区別するため、使えるアルファベットは "A" から "Z"(大文字)と "a" から "z"(小文字)です。

+

JavaScript 1.5 からは å や ü といった ISO 8859-1 や Unicode のアルファベットも識別子に使えます。Unicode エスケープシーケンス のページに列挙されている \uXXXX 形式の Unicode エスケープシーケンスも識別子に使用できます。

+

Number_hitstemp99_name が使用できる名前の例です。

+

{{ 英語版章題("Declaring Variables") }}

+

変数の宣言

+

2 つの方法で変数を宣言できます。

+ +

{{ 英語版章題("Evaluating Variables") }}

+

変数の評価

+

var 文を使用し、初期化せずに宣言された変数は undefined の値をとります。

+

未宣言の変数にアクセスしようとすると、ReferenceError 例外が投げられます。

+
var a;
+print("a の値は " + a); // "a の値は undefined" を出力
+print("b の値は " + b); // ReferenceError 例外を投げる
+
+

undefined を使うと変数に値が入っているかどうかを確かめられます。以下のコードでは、変数 input には値が代入されておらず、if 文での評価結果は true です。

+
var input;
+if(input === undefined){
+  doThis();
+} else {
+  doThat();
+}
+
+

Not sure how the following is related to "Variables" section undefined は真偽値コンテキストで使用されると false として振る舞います。例えば以下のコードでは、myArray の要素が未定義であるために関数 myFunction が実行されます。

+
var myArray = new Array();
+if (!myArray[0]) myFunction();
+
+

null 変数を評価すると、数値コンテキストにおいては null 値は 0 として振る舞います。また、真偽値コンテキストでは false として振る舞います。

+
var n = null;
+print(n * 32); // prints 0
+
+

{{ 英語版章題("Variable Scope") }}

+

変数のスコープ

+

変数を関数の外側で宣言すると、その変数はその文書のどのコードからも使用できるようになるため、グローバル(大域)変数と呼ばれます。変数を関数の内部で宣言すると、その変数はその関数の中でしか使用できないため、ローカル(局所)変数と呼ばれます。

+

JavaScript には ブロック文 のスコープがありません。むしろ、そのブロックを内包しているコードに対して局所化されます。例えば以下のコードは conditionfalse のとき、例外を投げずに 0 が出力されます。

+
if (condition) {
+  var x = 5;
+}
+print(x ? x : 0);
+
+

JavaScript の変数に関する独特なこととして、後に宣言される変数を例外を発生させることなく参照できるというのも挙げられます。

+
print(x === undefined); // "true" を出力
+var x = 3;
+
+

{{ 英語版章題("Global Variables") }}

+

グローバル変数

+

need links to pages discussing scope chains and the global object グローバル変数は実際にはグローバルオブジェクトのプロパティです。ウェブページではグローバルオブジェクトは window です。そのため、window.variable という構文を使うことでグローバル変数をセットしたり、グローバル変数にアクセスしたりすることができます。

+

したがって、あるウィンドウやフレームで宣言したグローバル変数に、そのウィンドウやフレームの名前を指定すれば別のウィンドウやフレームからアクセスできます。例えば、phoneNumber という変数を FRAMESET 文書内で宣言すると、子フレームから parent.phoneNumber としてこの変数を参照することができます。

+

{{ 英語版章題("See Also") }}

+

関連項目

+

JavaScript のシャープ変数

+

{{ PreviousNext("JavaScript/Guide/Values", "JavaScript/Guide/Constants") }}

diff --git a/files/ja/web/javascript/guide/working_with_objects/index.html b/files/ja/web/javascript/guide/working_with_objects/index.html new file mode 100644 index 0000000000..6200e1aa36 --- /dev/null +++ b/files/ja/web/javascript/guide/working_with_objects/index.html @@ -0,0 +1,496 @@ +--- +title: オブジェクトでの作業 +slug: Web/JavaScript/Guide/Working_with_Objects +tags: + - Beginner + - Document + - Guide + - JavaScript + - Object + - 'l10n:priority' + - オブジェクトの比較 + - コンストラクター +translation_of: Web/JavaScript/Guide/Working_with_Objects +--- +
{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Keyed_collections", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}
+ +

JavaScript は、シンプルなオブジェクトベースの枠組みを持つ言語として設計されています。JavaScript におけるオブジェクトはプロパティの集まりであり、プロパティは名前 (あるいはキー) と値との関連付けから成り立っています。プロパティの値を関数にすることもでき、これはいわゆるオブジェクトのメソッドとなります。ブラウザーにあらかじめ定義されているオブジェクトに加え、独自のオブジェクトを定義することもできます。この節ではオブジェクト、プロパティ、関数、メソッドの使い方と、独自のオブジェクトを作成する方法を説明します。

+ +

オブジェクトの概要

+ +

他の多くのプログラミング言語と同様、JavaScript におけるオブジェクトも、現実世界の「もの」 (すなわちオブジェクト) になぞらえることができます。JavaScript におけるオブジェクトの概念は、現実世界に実在する「もの」との対比で解釈できます。

+ +

JavaScript において、オブジェクトはプロパティと型を持つ独立した存在です。カップを例に考えてみましょう。カップは様々なプロパティ (特性) をもったもの (オブジェクト) です。カップは、色や形状、重さや材質といったプロパティを持っています。同様に、JavaScript のオブジェクトもプロパティを持つことができ、プロパティによってそのオブジェクトの特徴を定義することができます。

+ +

オブジェクトとプロパティ

+ +

JavaScript のオブジェクトは、自身に関連付けられたプロパティを持ちます。オブジェクトのプロパティは、オブジェクトに関連付けられている変数と捉えることができます。オブジェクトのプロパティは、オブジェクトに属するものという点を除けば、基本的に通常の JavaScript 変数と同じようなものです。オブジェクトのプロパティは、オブジェクトの特性を定義します。オブジェクトのプロパティには、単純なドット表記でアクセスします。

+ +
objectName.propertyName
+
+ +

すべての JavaScript の変数と同じく、オブジェクト名 (通常の変数にもなります) とプロパティ名では、大文字と小文字は厳密に区別されます。プロパティに値を代入することでプロパティを定義する事ができます。以下のようにして、myCar という名前のオブジェクトを作成し、makemodelyear という名前のプロパティを付与することができます

+ +
var myCar = new Object();
+myCar.make = 'Ford';
+myCar.model = 'Mustang';
+myCar.year = 1969;
+
+ +

上記の例は、オブジェクト初期化子を使用して作成することもできます。オブジェクト初期化子は、中括弧 ({}) で囲まれたオブジェクトのプロパティ名と関連する値の 0 個以上のペアをカンマで区切ったリストです。

+ +
var myCar = {
+    make: 'Ford',
+    model: 'Mustang',
+    year: 1969
+};
+
+ +

オブジェクトに割り当てられていないプロパティは {{jsxref("undefined")}} です ({{jsxref("null")}} ではありません)。

+ +
myCar.color; // undefined
+ +

JavaScript オブジェクトのプロパティは、ブラケット (角括弧) 記述法でもアクセスすることができます (詳しくはプロパティのアクセサーを参照してください)。個々のプロパティが文字列値と関連付けられてアクセスできるため、オブジェクトは連想配列と呼ばれることがあります。ですから例えば、myCar オブジェクトのプロパティに次のようにアクセスできます。

+ +
myCar['make'] = 'Ford';
+myCar['model'] = 'Mustang';
+myCar['year'] = 1969;
+
+ +

オブジェクトプロパティの名前には、あらゆる有効な JavaScript 文字列 (空文字列を含む) か、文字列に変換できるものが使用できます。しかしながら、JavaScript 識別子として有効ではないプロパティ名 (例えば空白やダッシュを含んでいたり、数字で始まったりするプロパティ名) には、ブラケット (角括弧) 表記法でのみアクセスできます。この表記法はプロパティ名を動的に決める場合 (プロパティ名が実行時に決まる場合) に便利です。例を示します。

+ +
// カンマで区切られた 4 つの変数が作成され、
+// 1 つに割り当てられます。
+var myObj = new Object(),
+    str = 'myString',
+    rand = Math.random(),
+    obj = new Object();
+
+myObj.type              = 'ドット表記';
+myObj['date created']   = '空白入りの文字列';
+myObj[str]              = '文字列の値';
+myObj[rand]             = '乱数';
+myObj[obj]              = 'オブジェクト';
+myObj['']               = '空文字列も可能';
+
+console.log(myObj);
+
+ +

なお、JavaScript のオブジェクトのプロパティ名 (キー) は文字列かシンボルしか扱えないので、各括弧表記の中のキーはすべて、シンボルを除いて文字列に変換されます (将来、クラスフィールドの提案が進行すると、プライベート名も追加される予定ですが、[] の形は使用できません)。例えば、上記のコードで obj キーが myObj に追加されるとき、JavaScript は obj.toString() メソッドを呼び出し、結果の文字列を新しいキーとして使用します。

+ +

変数内の文字列値を使ってプロパティにアクセスすることもできます。

+ +
var propertyName = 'make';
+myCar[propertyName] = 'Ford';
+
+propertyName = 'model';
+myCar[propertyName] = 'Mustang';
+
+ +

ブラケット表記法を用いて for...in でオブジェクトの列挙可能なプロパティすべてを巡回することができます。どのように動作するかを説明するため、以下にオブジェクトとオブジェクト名を引数として渡すと、オブジェクトのプロパティを表示する関数を示します。

+ +
function showProps(obj, objName) {
+  var result = '';
+  for (var i in obj) {
+    // obj.hasOwnProperty() はオブジェクトのプロトタイプチェーンからプロパティを絞り込むために使用しています
+    if (obj.hasOwnProperty(i)) {
+      result += objName + '.' + i + ' = ' + obj[i] + '\n';
+    }
+  }
+  return result;
+}
+
+ +

そして、showProps(myCar, "myCar") のように関数を呼び出すと次の結果が返ります。

+ +
myCar.make = Ford
+myCar.model = Mustang
+myCar.year = 1969
+ +

オブジェクトの全プロパティの列挙

+ +

ECMAScript 5 以降では、オブジェクトのプロパティをリストアップ/トラバース (横断走査) する言語特有の方法が 3 つあります。

+ + + +

ECMAScript 5 よりも前では、オブジェクトの全プロパティを列挙する言語特有の方法はありません。しかし、次の関数で実現できます。

+ +
function listAllProperties(o) {
+	var objectToInspect;
+	var result = [];
+
+	for(objectToInspect = o; objectToInspect !== null;
+           objectToInspect = Object.getPrototypeOf(objectToInspect)) {
+        result = result.concat(
+            Object.getOwnPropertyNames(objectToInspect)
+        );
+    }
+
+	return result;
+}
+
+ +

これは「隠された」プロパティ (プロトタイプチェーンのより近いところに他の同名のプロパティがあるために、オブジェクトを通してアクセスすることができないプロトタイプチェーン上のプロパティ) を見つけるのに便利です。アクセス可能なプロパティを列挙するには、配列内の重複を削除するだけで簡単に実現できます。

+ +

新しいオブジェクトの作成

+ +

JavaScript には数多くの定義済みオブジェクトがあります。さらに、独自のオブジェクトを定義できます。オブジェクトは{{jsxref("Operators/Object_initializer","オブジェクト初期化子","","true")}}を使って作成することができます。他にも、まずコンストラクター関数を作り、その関数を new 演算子との組み合わせで呼び出すことでオブジェクトをインスタンス化することもできます。

+ +

オブジェクト初期化子の使用

+ +

コンストラクター関数を使ったオブジェクトの作成のほかに、オブジェクト初期化子を使用してオブジェクトを作成することができます。オブジェクト初期化子を使うことを、オブジェクトをリテラル表記法で作ると表現することがあります。「オブジェクト初期化子」は、C++ で使われる用語と同じ意味です。

+ +

オブジェクト初期化子を使ったオブジェクトの構文は次のようになります。

+ +
var obj = { property_1:   value_1,   // property_# は識別子だったり、
+            2:            value_2,   // 数値だったり、
+            // ...,
+            'property n': value_n }; // 文字列だったりします
+
+ +

obj は新しいオブジェクトの名前、property_i は識別子 (名前、数値、または文字列リテラルのいずれか)、value_i は式で、その値が property_i に代入されます。obj と代入は任意です。もし他の場所でこのオブジェクトを参照する必要がないのなら、変数への代入は不要です。(なお、もしオブジェクトが文の書かれる場所に現れる場合は、リテラルがブロック文と混同されないように、オブジェクトリテラルを括弧で囲む必要がある場合があります。)

+ +

オブジェクト初期化子は式であり、それぞれのオブジェクト初期化子は、それが現れる文が実行されるたびにオブジェクトを作成する結果になります。オブジェクト初期化子が同一であっても、作成されるオブジェクトは互いに等しいとはみなされません。オブジェクトは new Object() の呼び出しが行われたかのように作成されます。つまり、オブジェクトリテラル式から作成されるオブジェクトは Object のインスタンスです。

+ +

次の文では、式 cond が true の場合にのみオブジェクトを作り、変数 x に代入します。

+ +
if (cond) var x = {greeting: 'hi there'};
+
+ +

次の例では 3 つのプロパティを持った myHonda を作ります。なお、engine プロパティもまた、プロパティを持つオブジェクトです。

+ +
var myHonda = {color: 'red', wheels: 4, engine: {cylinders: 4, size: 2.2}};
+
+ +

配列を作るためにオブジェクト初期化子を使うこともできます。配列リテラルを参照してください。

+ +

コンストラクター関数の使用

+ +

別の方法として、次の 2 つの手順でオブジェクトを作ることができます。

+ +
    +
  1. コンストラクター関数を記述してオブジェクトの型を定義します。この時、便宜上の理由から慣習的に、1 文字目は大文字とします。
  2. +
  3. new でオブジェクトのインスタンスを作成します。
  4. +
+ +

オブジェクトの型を定義するには、名前、プロパティ、メソッドを指定するオブジェクト型用の関数を作ります。例えば、車についてのオブジェクト型を作りたいとしましょう。このオブジェクト型は car と呼ばれ、make、model、year のプロパティを持たせたいとします。これを行うには、以下のような関数を書きます。

+ +
function Car(make, model, year) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+}
+
+ +

this を使うことで、関数に渡されたオブジェクトのプロパティに対し値を代入していることに注意してください。

+ +

以下のようにして mycar と呼ばれるオブジェクトを作成できるようになりました。

+ +
var mycar = new Car('Eagle', 'Talon TSi', 1993);
+
+ +

この文では mycar を作り、プロパティに指定した値を代入します。mycar.make の値は文字列 "Eagle" になり、mycar.year は整数 1993 になり、といった具合です。

+ +

new を使って car オブジェクトをいくつでも作れます。例えば、

+ +
var kenscar = new Car('Nissan', '300ZX', 1992);
+var vpgscar = new Car('Mazda', 'Miata', 1990);
+
+ +

オブジェクトは、別のオブジェクトをプロパティとして持つことができます。例えば、person という名前のオブジェクトを次のように定義しましょう。

+ +
function Person(name, age, sex) {
+  this.name = name;
+  this.age = age;
+  this.sex = sex;
+}
+
+ +

それから、2 個の新しい person オブジェクトを次のようにインスタンス化します。

+ +
var rand = new Person('Rand McKinnon', 33, 'M');
+var ken = new Person('Ken Jones', 39, 'M');
+
+ +

そして、Car の定義を person オブジェクトを取る owner プロパティを含むよう、以下のように書き換えることができます。

+ +
function Car(make, model, year, owner) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+  this.owner = owner;
+}
+
+ +

新しいオブジェクトをインスタンス化するには、以下のようにします。

+ +
var car1 = new Car('Eagle', 'Talon TSi', 1993, rand);
+var car2 = new Car('Nissan', '300ZX', 1992, ken);
+
+ +

新しいオブジェクトを作成する際、上の文ではリテラル文字列や整数値を渡す代わりに、オブジェクト randken を引数 owner として渡していることに注意してください。そして、car2 の owner の名前を知りたければ、以下のプロパティでアクセスできます。

+ +
car2.owner.name
+
+ +

なお、既に定義されたオブジェクトにはいつでもプロパティを追加することができます。例えば、以下の文は、

+ +
car1.color = 'black';
+
+ +

car1 にプロパティ color を追加し、そこに "black" という値を代入します。しかしながら、これは他のどのオブジェクトにも影響しません。同じ型のすべてのオブジェクトに新しいプロパティを追加するには、car オブジェクト型の定義にそのプロパティを追加する必要があります。

+ +

Object.create メソッドの使用

+ +

オブジェクトは {{jsxref("Object.create()")}} メソッドを使用して作成することもできます。このメソッドは、コンストラクター関数の定義なしに作りたいオブジェクトのプロトタイプを選べるため、とても便利です。

+ +
// Animal のプロパティとメソッドをカプセル化
+var Animal = {
+  type: 'Invertebrates', // プロパティの既定値、「無脊椎動物」
+  displayType: function(){  // Animal の種類を表示するメソッド
+    console.log(this.type);
+  }
+}
+
+// animal1 という新しい animal 型を作成
+var animal1 = Object.create(Animal);
+animal1.displayType(); // 出力 : Invertebrates
+
+// Fishes という新しい animal 型を作成
+var fish = Object.create(Animal);
+fish.type = 'Fishes';
+fish.displayType(); // 出力 : Fishes
+ +

継承

+ +

JavaScript のすべてのオブジェクトは、1 つ以上の他のオブジェクトを継承しています。継承元になるオブジェクトはプロトタイプと呼ばれ、継承されたプロパティはコンストラクターの prototype オブジェクトにあります。詳細は継承とプロトタイプチェーンを参照してください。

+ +

オブジェクトプロパティのインデックス付け

+ +

オブジェクトのプロパティは、プロパティ名または番号インデックスで参照することができます。名前によってプロパティを初期定義した場合、常に名前を使って参照する必要があり、インデックスによってプロパティを初期定義した場合、常にインデックスを使って参照する必要があります。

+ +

この制限は、(以前に Car オブジェクト型に対して行ったように) コンストラクター関数でオブジェクトとプロパティを作るときや、個々のプロパティを明示的に定義した場合 (例えば myCar.color = "red") に適用されます。初めにオブジェクトプロパティをインデックスで、たとえば myCar[5] = "25 mpg" のように定義した場合、以降そのプロパティは myCar[5] としてしか参照できません。

+ +

このルールの例外は、forms 配列型オブジェクトのような HTML から反映された配列型オブジェクトです。この配列型オブジェクトにあるオブジェクトは、いつでもインデックス (文書中に現れる位置を基準としたもの) と名前 (定義されていれば) のどちらからも参照できます。例えば、文書内の 2 つ目の <FORM> タグが NAME 属性として "myForm" という値を持つとき、フォームは document.forms[1]、document.forms["myForm"]document.forms.myForm のいずれかで参照できます。

+ +

オブジェクト型に対するプロパティの定義

+ +

prototype プロパティを使用すると、定義済みのオブジェクト型に対してプロパティを追加することができます。このプロパティはオブジェクトの 1 つのインスタンスだけではなく、指定された型のすべてのオブジェクトで共有されます。次のコードはすべての car 型のオブジェクトに color プロパティを追加し、オブジェクト car1color プロパティに値を代入します。

+ +
Car.prototype.color = null;
+car1.color = 'black';
+
+ +

詳しくは、JavaScript リファレンス内にある、Function オブジェクトの prototype プロパティを参照してください。

+ +

メソッドの定義

+ +

メソッドはオブジェクトに関連付けられた関数です。簡単に言えば、オブジェクトのプロパティである関数です。メソッドは通常の関数と同じ方法で定義されますが、オブジェクトのプロパティに代入される点が異なります。詳細はメソッドの定義を参照してください。例えば、

+ +
objectName.methodname = functionName;
+
+var myObj = {
+  myMethod: function(params) {
+    // ...処理を行う
+  }
+
+  // これでも動作します
+
+  myOtherMethod(params) {
+    // ...他の処理を行う
+  }
+};
+
+ +

ここで objectName は既存のオブジェクトを、methodname はメソッドを割り当てたい名前を、function_name は関数の名前を指しています。

+ +

そして次のようにオブジェクトに続けてメソッドを呼び出します。

+ +
object.methodname(params);
+
+ +

オブジェクトのコンストラクター関数にメソッドの定義を含めることで、オブジェクト型に対してメソッドを定義することができます。以前に定義した car オブジェクトのプロパティを整形して表示する関数を定義するとします。例えば以下の通りです。

+ +
function displayCar() {
+  var result = '美しい ' + this.year + '年式 ' + this.make
+    + ' ' + this.model;
+  pretty_print(result);
+}
+
+ +

pretty_print は水平線と文字列を表示する関数です。this を使ってメソッドが属するオブジェクトを参照していることに注意してください。

+ +

次の文をオブジェクトの定義に追加すると、この関数を car のメソッドにできます。

+ +
this.displayCar = displayCar;
+
+ +

そして、car の完全な定義は次のようになります。

+ +
function Car(make, model, year, owner) {
+  this.make = make;
+  this.model = model;
+  this.year = year;
+  this.owner = owner;
+  this.displayCar = displayCar;
+}
+
+ +

次のようにして、個々のオブジェクトに対して displayCar メソッドを呼び出せます。

+ +
car1.displayCar();
+car2.displayCar();
+
+ +

オブジェクト参照のための this の使用

+ +

JavaScript には、メソッド内で現在のオブジェクトを参照するための this +という特別なキーワードがあります。以下の例には、ManagerIntern という 2 つのオブジェクトがあり、それぞれが独自の nameagejob を持っています。関数 sayHi() の中に this.name があることに注目してください。2 つのオブジェクトに追加してそれらを呼び出すことで、'Hello, My name is' を返し、その特定のオブジェクトから name の値を追加しています。

+ +
const Manager = {
+  name: "John",
+  age: 27,
+  job: "Software Engineer"
+}
+const Intern = {
+  name: "Ben",
+  age: 21,
+  job: "Software Engineer Intern"
+}
+
+function sayHi() {
+    console.log('Hello, my name is', this.name)
+}
+
+// 両方のオブジェクトに sayHi 関数を追加
+Manager.sayHi = sayHi;
+Intern.sayHi = sayHi;
+
+Manager.sayHi() // Hello, my name is John'
+Intern.sayHi() // Hello, my name is Ben'
+
+ +

this は自身が入っているオブジェクトを参照します。上記の例に howOldAmI() という新しい関数を作って、その人の年齢を示す文をログに出力できます。

+ +
function howOldAmI (){
+  console.log('I am ' + this.age + ' years old.')
+}
+Manager.howOldAmI = howOldAmI;
+Manager.howOldAmI() // I am 27 years old.
+
+ +

ゲッターとセッターの定義

+ +

ゲッターは、特定のプロパティの値を取得するメソッドです。セッター は、特定のプロパティの値を設定するメソッドです。ゲッターとセッターは、新しいプロパティの追加をサポートする定義済みのコアオブジェクト、またはユーザー定義オブジェクト上で定義できます。

+ +

ゲッターとセッターは次のどちらの方法でも作れます。

+ + + +

オブジェクト初期化子を使用してゲッターとセッターを定義するには、ゲッターメソッドの前に get を、セッターメソッドの前に set を記述するだけです。当然ですがゲッターメソッドは引数を想定してはいけませんし、セッターメソッドは正確に 1 つの引数(新しい設定値)を期待します。 +例えば、以下のようになります。

+ +
var o = {
+  a: 7,
+  get b() {
+    return this.a + 1;
+  },
+  set c(x) {
+    this.a = x / 2;
+  }
+};
+
+console.log(o.a); // 7
+console.log(o.b); // 8 <-- この時点で get b() メソッドが開始されます。initiated.
+o.c = 50;         //   <-- この時点で set c(x) メソッドが開始されます。
+console.log(o.a); // 25
+
+ +

o オブジェクトのプロパティは以下の通りです。

+ + + +

[gs]et propertyName(){ } という構文により誤解を招くかもしれませんが、オブジェクトリテラル内で "[gs]et property()" によって定義されたゲッターやセッターの関数名は、(__define[GS]etter__ とは対照的に)ゲッターやセッター自体の名前ではないことに注意してください。

+ +

ゲッターとセッターはまた、Object.defineProperties メソッドを使用して、生成後のオブジェクトにいつでも追加できます。このメソッドの第1引数はゲッターまたはセッターを定義するオブジェクトです。第2引数はプロパティ名がゲッターまたはセッターの名前で、プロパティ値がゲッターまたはセッター関数を定義するオブジェクトです。前回の例と同じゲッターとセッターを定義する例を見てみましょう。

+ +
var o = { a: 0 };
+
+Object.defineProperties(o, {
+    'b': { get: function() { return this.a + 1; } },
+    'c': { set: function(x) { this.a = x / 2; } }
+});
+
+o.c = 10; // 'a' プロパティに 10 / 2 (5) を代入するセッターを実行します
+console.log(o.b); // a + 1 つまり 6 を与えるゲッターを実行します
+
+ +

2 つの方法のどちらを選ぶのかは、自身のプログラミングスタイルや行っている作業によります。すでにオブジェクト初期化子を気に入っているのなら、プロトタイプの定義時にほとんどの場合、最初の書式を選ぶでしょう。この書式はより簡潔で自然です。しかしながら、ゲッターやセッターを後から追加しなければならないとき — 自分がプロトタイプやオブジェクトの詳細を書いていない場合 — には、2番目の書式だけが使えます。2番目の書式には JavaScript の動的な性質が表現されています — ただし、コードを読みにくく理解しづらいものにする可能性があります。

+ +

プロパティの削除

+ +

継承されたものでないプロパティは {{jsxref("Operators/delete","delete")}} 演算子を使って削除できます。以下のコードはプロパティを削除する方法です。

+ +
// 2 つのプロパティ a と b を持つ新しいオブジェクト myobj を作成。
+var myobj = new Object;
+myobj.a = 5;
+myobj.b = 12;
+
+// プロパティ a を削除すると、myobj には b プロパティだけが残る。
+delete myobj.a;
+console.log ('a' in myobj); // yields "false"
+
+ +

delete 演算子はまた、var キーワードを使わずに定義されたグローバル変数の削除にも使えます。

+ +
g = 17;
+delete g;
+
+ +

オブジェクトの比較

+ +

JavaScript では、オブジェクトは参照型です。2 つの異なるオブジェクトは、同じプロパティを持っていても等値とは見なされません。同じオブジェクトへの参照を比較した時のみ真となります。

+ +
// 2 つの変数は、同じプロパティを持つ 2 つの異なるオブジェクト
+var fruit = {name: 'apple'};
+var fruitbear = {name: 'apple'};
+
+fruit == fruitbear; // false が返される
+fruit === fruitbear; // false が返される
+ +
// 2 つの変数、オブジェクトは 1 つ
+var fruit = {name: 'apple'};
+var fruitbear = fruit;  // fruitbear に fruit オブジェクトへの参照を代入
+
+// fruit と fruitbear は同じオブジェクトを指している
+fruit == fruitbear; // true が返される
+fruit === fruitbear; // true が返される
+
+fruit.name = 'grape';
+console.log(fruitbear); // { name: "apple" } ではなく { name: "grape" } と出力される
+
+ +

比較演算子についての詳細は、リファレンスの比較演算子の節をご覧ください。

+ +

関連情報

+ + + +

{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Details_of_the_Object_Model")}}

diff --git a/files/ja/web/javascript/guide/writing_a_regular_expression_pattern/index.html b/files/ja/web/javascript/guide/writing_a_regular_expression_pattern/index.html new file mode 100644 index 0000000000..64da075317 --- /dev/null +++ b/files/ja/web/javascript/guide/writing_a_regular_expression_pattern/index.html @@ -0,0 +1,193 @@ +--- +title: 正規表現パターンの記述 +slug: Web/JavaScript/Guide/Writing_a_Regular_Expression_Pattern +--- +

正規表現パターンを書く

+ +

正規表現パターンは、/abc/ のような単純な文字、または /ab*c//Chapter (\d+)\.\d*/ のような単純な文字と特殊文字との組み合わせからなります。最後の例では記憶装置として使われている丸括弧が含まれています。パターンのこの部分でなされたマッチは後で使用できるように記憶されます。詳しくは 括弧で囲まれた部分文字列のマッチの使用 を参照してください。

+ +

単純なパターンの使用

+ +

単純なパターンは、直接マッチしている部分を見つけたい文字で構成されます。例えば、/abc/ というパターンは、実際に 'abc' という文字が一緒にその順で存在しているときにだけ、文字列中の文字の組み合わせにマッチします。"Hi, do you know your abc's?" や "The latest airplane designs evolved from slabcraft." といった文字列でのマッチは成功します。どちらの場合でも 'abc' という部分文字列にマッチします。"Grab crab" という文字列では 'abc' という部分文字列が含まれていないためマッチしません。

+ +

特殊文字の使用

+ +

1 つ以上の b を見つけたり、ホワイトスペースを見つけたりといった直接マッチより高度なマッチの検索では、パターンに特殊文字を使用します。例えば /ab*c/ というパターンでは 1 つの 'a' とその後ろに続く 0 個以上の 'b'(* は直前のアイテムの 0 回以上の出現を意味する)とそのすぐ後ろに続く 'c' からなる文字の組み合わせにマッチします。"cbbabbbbcdebc" という文字列ではこのパターンは 'abbbbc' という部分文字列にマッチします。

+ +

以下の表で正規表現で使用できる特殊文字とその意味を詳しく説明します。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
文字意味
\次のうちのどちらか。 +
    +
  • 通常は文字どおり扱われる文字に対して、次の文字は特殊であり、文字どおりに解釈すべきではないと指示する。例えば、/b/ は 'b' という文字にマッチする。b の前にバックスラッシュを置き、/\b/ とすると、その文字は単語の区切りにマッチすることを意味する特殊文字になる。
  • +
  • 通常は特殊文字として扱われる文字に対して、次の文字は特殊ではなく、文字どおりに解釈すべきであると指示する。例えば、* は直前のアイテムの 0 回以上の出現にマッチさせることを意味する特殊文字である。つまり、例えば /a*/ は a の 0 文字以上の a へのマッチを意味する。* という文字そのものにマッチさせるには、その直前にバックスラッシュを置く。例えば、/a\*/ は 'a*' にマッチする。
  • +
+
^入力の先頭にマッチする。複数行フラグが true にセットされている場合は、改行文字直後にもマッチする。 例えば、/^A/ は "an A" の 'A' にはマッチしないが、"An A" の最初の 'A' にはマッチする。
$入力の末尾にマッチする。複数行フラグが true にセットされている場合は、改行文字直前にもマッチする。 例えば、/t$/ は "eater" の 't' にはマッチしないが、"eat" の 't' にはマッチする。
*直前の文字の 0 回以上の繰り返しにマッチする。 例えば、/bo*/ は "A ghost booooed" の 'boooo' や "A bird warbled" の 'b' にはマッチするが、"A goat grunted" ではマッチしない。
+直前の文字の 1 回以上の繰り返しにマッチする。{1,} と同等。 例えば、/a+/ は "candy" の 'a' や、"caaaaaaandy" のすべての a にマッチする。
?直前の文字の 0 回か 1 回の繰り返しにマッチする。 +

例えば、/e?le?/ は "angel" の 'el' や "angle" の 'le' にマッチする。

+ +

*、+、?、{} といった量指定子の直後に使用した場合、その量指定子をスキップ優先(最小回数にマッチ)にする。これはデフォルトとは逆であり、デフォルトは繰り返し優先(最大回数にマッチ)。例えば、/\d+/ は非グローバルで "123abc" の "123" にマッチするが、/\d+?/ の場合、"1" だけにマッチする。

+ 先読み表現内でも使用できるが、これはこの表の x(?=y) および x(?!y) にて説明。
.小数点は改行文字以外のどの 1 文字にもマッチする。 例えば、/.n/ は "nay, an apple is on the tree" の 'an' や 'on' にはマッチするが、'nay' にはマッチしない。
(x)'x' にマッチし、マッチしたものを記憶しておく。これはキャプチャする括弧と呼ぶ。 例えば、/(foo)/ は "foo bar" の 'foo' にマッチし、これを記憶する。マッチした部分文字列は結果として生成される配列の要素 1, ..., b から参照できる。
(?:x)'x' にマッチするが、マッチしたものは記憶しない。これはキャプチャしない括弧と呼ぶ。マッチした部分文字列は先程のような配列の要素 1, ..., n から参照することはできない。
x(?=y)'x' に 'y' が続く場合のみ 'x' にマッチする。例えば、/Jack(?=Sprat)/ は 'Jack' の後ろに 'Sprat' が続く場合のみ 'Jack' にマッチする。/Jack(?=Sprat|Frost)/ は 'Jack' の後ろに 'Sprat' または 'Frost' が続く場合のみ 'Jack' にマッチする。しかしながら、'Sprat' も 'Frost' もマッチの結果には現れない。
x(?!y)'x' に 'y' が続かない場合のみ 'x' にマッチする。例えば、/\d+(?!\.)/ はある数に小数点が続かない場合のみその数にマッチする。正規表現 /\d+(?!\.)/.exec("3.141") は 141 にはマッチするが 3.141 にはマッチしない。
x|y'x' または 'y' にマッチする。 例えば、/green|red/ は "green apple" の "green' や "red apple" の 'red' にマッチする。
{n}n には正の整数が入る。直前の文字がちょうど n 回出現するものにマッチする。 例えば、/a{2}/ は "candy" の 'a' にはマッチしないが、"caandy" の すべての a にマッチする。また、"caaandy" の最初の 2 つの a にマッチする。
{n,}n には正の整数が入る。直前の文字が少なくとも n 回出現するものにマッチする。 例えば、/a{2,}/ は "candy" の 'a' にはマッチしないが、"caandy" や "caaaaaaandy" の すべての a にマッチする。
{n,m}n および m には正の整数が入る。直前の文字が少なくとも n 回、多くとも m 回出現するものにマッチする。 例えば、/a{1,3}/ は "cndy" ではマッチせず、"candy" の 'a'、"caandy" の最初の 2 つの a、"caaaaaaandy" の最初の 3 つの a にマッチする。"caaaaaaandy" では元の文字列に a が 4 つ以上あるが、マッチするのは "aaa" であることに注意。
[xyz]文字の集合。囲まれた文字のどれにでもマッチする。ハイフンを用いて文字の範囲を指定することも可能。 例えば、/[abcd]//[a-d]/ と同じ。これは "brisket" の 'b' や "city" の 'c' にマッチする。
[^xyz]文字の集合の否定または補集合。角括弧で囲まれていないものにマッチする。ハイフンを用いて文字の範囲を指定することも可能。 例えば、/[^abc]//[^a-c]/ と同じ。これは "brisket" の 'r' や "chop" の 'h' にマッチする。
[\b]後退にマッチする。(\b と混同してはならない。)
\bスペースや改行文字のような単語の区切りにマッチする。([\b] と混同してはならない。) 例えば、/\bn\w/ は "noonday" の 'no' にマッチする。また、/\wy\b/ は "possibly yesterday" の 'ly' にマッチする。
\B単語の区切り以外の文字にマッチする。 例えば、/\w\Bn/ は "noonday" の 'on' にマッチする。また、/y\B\w/ は "possibly yesterday" の 'ye' にマッチする。
\cXX には制御文字が入る。文字列中の制御文字にマッチする。 例えば、/\cM/ は文字列中の control-M にマッチする。
\d数字にマッチする。[0-9] と同等。 例えば、/\d//[0-9]/ は "B2 is the suite number" の '2' にマッチする。
\D数字以外の文字にマッチする。[^0-9] と同等。 例えば、/\D//[^0-9]/ は "B2 is the suite number" の 'B' にマッチする。
\f改ページにマッチする。
\n改行にマッチする。
\r復帰にマッチする。
\sスペース、タブ、改ページ、改行を含む、1 つのホワイトスペース文字にマッチする。 [ \f\n\r\t\v\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF] と同等。 例えば、/\s\w*/ は "foo bar" の ' bar' にマッチする。
\Sホワイトスペース以外の 1 文字にマッチする。[^ \f\n\r\t\v\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF] と同等。 例えば、/\S\w*/ は "foo bar" の 'foo' にマッチする。
\tタブにマッチする。
\v垂直タブにマッチする。
\wアンダースコアを含むどの英数字にもマッチする。[A-Za-z0-9_] と同等。 例えば、/\w/ は "apple" の 'a' や "$5.28" の '5' や "3D" の '3' にマッチする。
\W前述以外の文字にマッチする。[^A-Za-z0-9_] と同等。 例えば、/\W//[^$A-Za-z0-9_]/ は "50%" の '%' にマッチする。
\nn には正の整数が入る。その正規表現の n 番目の括弧の部分にマッチする最後の部分文字列への後方参照(左括弧をカウントする)。 例えば、/apple(,)\sorange\1/ は "apple, orange, cherry, peach" の 'apple, orange,' にマッチする。
\0NUL 文字にマッチする。この後ろに他の数字を続けてはならない。
\xhhhh(2 桁の 16 進数)というコードを持つ文字にマッチする。
\uhhhhhhhh(4 桁の 16 進数)というコードを持つ文字にマッチする。
+ +

表 4.1正規表現における特殊文字

+ +

括弧の使用

+ +

正規表現パターンの一部分を括弧で囲むことで、マッチした部分文字列のその部分を記憶しておくことができます。一度記憶すると、後からその部分文字列を呼び戻すことができます。これに関しては 括弧で囲まれた部分文字列のマッチの使用 で説明しています。

+ +

例えば、/Chapter (\d+)\.\d*/ というパターンでは、エスケープされた文字と特殊文字の部分がその例で、その部分を記憶するように指示しています。これは 'Chapter ' という文字列、それに続く 1 文字以上の数字(\d はいずれかの数字を意味し、+ は 1 回以上の繰り返しを意味する)、それに続く小数点(それ自体は特殊文字であり、小数点の前の \ はパターンが '.' という文字そのものを探すようにすることを意味する)、それに続く 0 文字以上の数字(\d は数字を意味し、* は 0 回以上の繰り返しを意味する)にマッチします。さらに、括弧を使うことで最初のマッチした数値を記憶させます。

+ +

このパターンは "Open Chapter 4.3, paragraph 6" という文字列で見つかり、'4' が記憶されます。このパターンは "Chapter 3 and 4" では見つかりません。この文字列は '3' の後ろにピリオドがないためです。

+ +

マッチした部分を記憶させることなく部分文字列にマッチさせたい場合は、その括弧においてパターンの前に ?: を付けてください。例えば、(?:\d+) は 1 文字以上の数字にマッチしますが、マッチした文字は記憶されません。

+ +

{{ PreviousNext("JavaScript/Guide/Creating_a_Regular_Expression", "JavaScript/Guide/Working_with_Regular_Expressions") }}

-- cgit v1.2.3-54-g00ecf