通常の{...}
構文を使用すると、1 つのオブジェクトを作成できます。しかし、多くの場合、複数のユーザーやメニュー項目など、同様のオブジェクトを多数作成する必要があります。
これは、コンストラクター関数と"new"
演算子を使用して実行できます。
コンストラクター関数は技術的には通常の関数です。ただし、次の 2 つの規則があります。
これらは最初に大文字で名前が付けられます。
これらは、 "new"
演算子を使用してのみ実行する必要があります。
例えば:
関数 ユーザー(名前) { this.name = 名前; this.isAdmin = false; } let user = new User("Jack"); アラート(ユーザー名); // ジャック アラート(user.isAdmin); // 間違い
関数がnew
で実行されると、次の手順が実行されます。
新しい空のオブジェクトが作成され、 this
に割り当てられます。
関数本体が実行されます。通常、 this
変更し、新しいプロパティを追加します。
this
値が返されます。
つまり、 new User(...)
次のようなことを行います。
関数 ユーザー(名前) { // これ = {}; (暗黙的に) // これにプロパティを追加します this.name = 名前; this.isAdmin = false; // これを返します。 (暗黙的に) }
したがって、 let user = new User("Jack")
次と同じ結果が得られます。
ユーザー = { にします 名前:「ジャック」、 isAdmin: false };
ここで、他のユーザーを作成したい場合は、 new User("Ann")
、 new User("Alice")
などを呼び出すことができます。毎回リテラルを使用するよりもはるかに短く、読みやすいです。
コンストラクターの主な目的は、再利用可能なオブジェクト作成コードを実装することです。
もう一度注意してください – 技術的には、どの関数も ( this
がないためアロー関数を除く) コンストラクターとして使用できます。 new
で実行でき、上記のアルゴリズムが実行されます。 「最初に大文字」は、関数がnew
で実行されることを明確にするための共通の取り決めです。
新しい関数() { … }
単一の複雑なオブジェクトの作成に関するコード行が多数ある場合は、次のように、すぐに呼び出されるコンストラクター関数でコード行をラップできます。
// 関数を作成し、すぐに new で呼び出します let user = new function() { this.name = "ジョン"; this.isAdmin = false; // ...ユーザー作成用のその他のコード // おそらく複雑なロジックとステートメント // ローカル変数など };
このコンストラクターはどこにも保存されず、作成されて呼び出されるだけであるため、再度呼び出すことはできません。したがって、このトリックは、単一のオブジェクトを構築するコードを、将来再利用することなくカプセル化することを目的としています。
高度なもの
このセクションの構文はほとんど使用されないため、すべてを知りたくない場合はスキップしてください。
関数内では、特別なnew.target
プロパティを使用して、関数がnew
を使用して呼び出されたか、new を使用せずに呼び出されたかを確認できます。
通常の呼び出しでは定義されておらず、 new
で呼び出された場合は関数と同じになります。
関数 User() { アラート(新しい.ターゲット); } // 「新規」なし: ユーザー(); // 未定義 // 「新規」の場合: 新しいユーザー(); // 関数 ユーザー { ... }
これを関数内で使用すると、 new
を使用して呼び出されたのか、「コンストラクター モードで」呼び出されたのか、それとも new を使用せずに「通常モードで」呼び出されたのかを知ることができます。
次のように、 new
呼び出しと定期呼び出しの両方を行って同じことを行うこともできます。
関数 ユーザー(名前) { if (!new.target) { // new なしで実行した場合 新しいユーザー(名前)を返します; // ...新しいものを追加します } this.name = 名前; } let john = User("ジョン"); // 呼び出しを新しいユーザーにリダイレクトします アラート(ジョン.名前); // ジョン
このアプローチは、構文をより柔軟にするためにライブラリで使用されることがあります。そのため、 new
付けても付けなくても関数を呼び出すことができ、関数は引き続き機能します。
ただし、 new
を省略すると何が起こっているのかわかりにくくなるため、どこでも使用するのはおそらく良いことではありません。 new
では、新しいオブジェクトが作成されていることを誰もが知っています。
通常、コンストラクターにはreturn
ステートメントがありません。彼らの仕事は、必要なものをすべてthis
に書き込むことであり、それが自動的に結果になります。
ただし、 return
ステートメントがある場合、ルールは簡単です。
return
がオブジェクトとともに呼び出された場合、 this
の代わりにオブジェクトが返されます。
return
がプリミティブで呼び出された場合、それは無視されます。
つまり、オブジェクトを指定してreturn
するとそのオブジェクトが返され、それ以外の場合はすべてthis
が返されます。
たとえば、ここではreturn
オブジェクトを返すことでthis
オーバーライドします。
関数 BigUser() { this.name = "ジョン"; return { 名前: "ゴジラ" }; // <-- このオブジェクトを返します } alert( new BigUser().name ); // ゴジラ、その物体を手に入れた
以下は空のreturn
の例です (または、その後にプリミティブを配置することもできますが、問題ありません)。
関数 SmallUser() { this.name = "ジョン"; 戻る; // <-- これを返します } alert( new SmallUser().name ); // ジョン
通常、コンストラクターにはreturn
ステートメントがありません。ここでは、主に完全を期すために、オブジェクトを返す特別な動作について説明します。
括弧の省略
ちなみに、 new
後の括弧は省略できます。
let user = 新しいユーザー; // <-- 括弧なし // と同じ let user = new User();
ここで括弧を省略することは「良いスタイル」とはみなされませんが、この構文は仕様で許可されています。
コンストラクター関数を使用してオブジェクトを作成すると、非常に高い柔軟性が得られます。コンストラクター関数には、オブジェクトの構築方法とオブジェクトに何を入れるかを定義するパラメーターがある場合があります。
もちろん、 this
にプロパティだけでなくメソッドも追加できます。
たとえば、以下のnew User(name)
指定されたname
とメソッドsayHi
持つオブジェクトを作成します。
関数 ユーザー(名前) { this.name = 名前; this.sayHi = function() { alert( "私の名前は: " + this.name ); }; } let john = new User("ジョン"); ジョン.sayHi(); // 私の名前はジョンです /* ジョン = { 名前:「ジョン」、 SayHi: function() { ... } } */
複雑なオブジェクトを作成するには、後で説明するより高度な構文であるクラスがあります。
コンストラクター関数 (簡単に言えばコンストラクター) は通常の関数ですが、最初に大文字で名前を付けるという共通の合意があります。
コンストラクター関数は、 new
使用してのみ呼び出す必要があります。このような呼び出しは、最初に空のthis
を作成し、最後に値が設定されたものを返すことを意味します。
コンストラクター関数を使用して、複数の同様のオブジェクトを作成できます。
JavaScript は、日付の場合はDate
、セットの場合はSet
など、これから検討する予定のその他の組み込み言語オブジェクトに対してコンストラクター関数を提供します。
オブジェクト、また戻ってきます!
この章では、オブジェクトとコンストラクターに関する基本のみを説明します。これらは、次の章でデータ型と関数について詳しく学ぶために不可欠です。
それを学んだ後、オブジェクトに戻り、「プロトタイプ」、「継承」、「クラス」の章で詳しく説明します。
重要性: 2
new A() == new B()
となるように関数A
とB
を作成することは可能ですか?
関数 A() { ... } 関数 B() { ... } a = 新しい A(); とします。 b = 新しい B(); とします。 アラート( a == b ); // 真実
そうであれば、コードの例を提供してください。
はい、可能です。
関数がオブジェクトを返す場合、 new
this
の代わりにそれを返します。
したがって、たとえば、同じ外部定義オブジェクトobj
を返すことができます。
obj = {} にします。 関数 A() { obj を返す; } 関数 B() { obj を返す; } alert( new A() == new B() ); // 真実
重要度: 5
3 つのメソッドでオブジェクトを作成するコンストラクター関数Calculator
を作成します。
read()
2 つの値の入力を求め、それぞれa
およびb
という名前のオブジェクト プロパティとして保存します。
sum()
これらのプロパティの合計を返します。
mul()
これらのプロパティの乗算結果を返します。
例えば:
let calculator = new Calculator(); 電卓.read(); alert( "Sum=" + calculator.sum() ); alert( "Mul=" + calculator.mul() );
デモを実行する
テストを含むサンドボックスを開きます。
関数電卓() { this.read = function() { this.a = +prompt('a?', 0); this.b = +prompt('b?', 0); }; this.sum = function() { this.a + this.b を返します。 }; this.mul = function() { this.a * this.b を返します。 }; } let calculator = new Calculator(); 電卓.read(); alert( "Sum=" + calculator.sum() ); alert( "Mul=" + calculator.mul() );
サンドボックス内のテストを含むソリューションを開きます。
重要度: 5
コンストラクター関数Accumulator(startingValue)
を作成します。
作成するオブジェクトは次のことを行う必要があります。
プロパティvalue
に「現在値」を格納します。開始値はコンストラクターstartingValue
の引数に設定されます。
read()
メソッドはprompt
を使用して新しい数値を読み取り、それをvalue
に追加する必要があります。
つまり、 value
プロパティは、初期値startingValue
を持つすべてのユーザー入力値の合計です。
コードのデモは次のとおりです。
アキュムレータ = 新しいアキュムレータ(1); とします。 // 初期値1 アキュムレータ.read(); // ユーザーが入力した値を追加します アキュムレータ.read(); // ユーザーが入力した値を追加します アラート(累積値); // これらの値の合計を表示します
デモを実行する
テストを含むサンドボックスを開きます。
関数アキュムレータ(開始値) { this.value = startingValue; this.read = function() { this.value += +prompt('いくら追加しますか?', 0); }; } アキュムレータ = 新しいアキュムレータ(1); とします。 アキュムレータ.read(); アキュムレータ.read(); アラート(累積値);
サンドボックス内のテストを含むソリューションを開きます。