diff options
author | Masahiro FUJIMOTO <mfujimot@gmail.com> | 2021-08-06 13:25:54 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-06 13:25:54 +0900 |
commit | fa091ee242d9e16d6187d176e0e2a3c77c37c045 (patch) | |
tree | cef60a6210d2ccef59002bcddca23fadeb62f729 /files/ja/web/javascript | |
parent | 0360bdcc1394dc5b65a190b557112f33baebefab (diff) | |
download | translated-content-fa091ee242d9e16d6187d176e0e2a3c77c37c045.tar.gz translated-content-fa091ee242d9e16d6187d176e0e2a3c77c37c045.tar.bz2 translated-content-fa091ee242d9e16d6187d176e0e2a3c77c37c045.zip |
Object.create の文書を Markdown に更新 (#1709)
- 文書を Markdown に変換
- 2021/07/26 時点の英語版に同期
Diffstat (limited to 'files/ja/web/javascript')
-rw-r--r-- | files/ja/web/javascript/reference/global_objects/object/create/index.html | 402 | ||||
-rw-r--r-- | files/ja/web/javascript/reference/global_objects/object/create/index.md | 398 |
2 files changed, 398 insertions, 402 deletions
diff --git a/files/ja/web/javascript/reference/global_objects/object/create/index.html b/files/ja/web/javascript/reference/global_objects/object/create/index.html deleted file mode 100644 index a1db7476d9..0000000000 --- a/files/ja/web/javascript/reference/global_objects/object/create/index.html +++ /dev/null @@ -1,402 +0,0 @@ ---- -title: Object.create() -slug: Web/JavaScript/Reference/Global_Objects/Object/create -tags: - - ECMAScript 5 - - JavaScript - - Method - - 'Null' - - Object - - Reference - - polyfill -translation_of: Web/JavaScript/Reference/Global_Objects/Object/create ---- -<p>{{JSRef}}</p> - -<p><code><strong>Object.create()</strong></code> メソッドは、既存のオブジェクトを新しく生成されるオブジェクトのプロトタイプとして使用して、新しいオブジェクトを生成します。</p> - -<div>{{EmbedInteractiveExample("pages/js/object-create.html", "taller")}}</div> - -<div class="hidden">このデモのソースファイルは GitHub リポジトリに格納されています。デモプロジェクトに協力したい場合は、 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> をクローンしてプルリクエストを送信してください。</div> - -<h2 id="Syntax" name="Syntax">構文</h2> - -<pre class="syntaxbox notranslate">Object.create(<var>proto</var>, [<var>propertiesObject</var>])</pre> - -<h3 id="Parameters" name="Parameters">引数</h3> - -<dl> - <dt><code><var>proto</var></code></dt> - <dd>新たに生成されるオブジェクトのプロトタイプになるべきオブジェクトです。</dd> - <dt><code><var>propertiesObject</var></code> {{Optional_inline}}</dt> - <dd>指定されていて、 {{jsxref("undefined")}} でない場合、それ自身が所有する一連の列挙可能なプロパティ (つまり、それ自身に定義されていて、プロトタイプチェインの中では<em>列挙可能でない</em>プロパティ) が、それらのプロパティ名を伴う一連のプロパティ記述子を指定し、新たに生成されるオブジェクトに追加されることになります。これらのプロパティは、 {{jsxref("Object.defineProperties()")}} の2番目の引数に対応するものです。</dd> -</dl> - -<h3 id="Return_value" name="Return_value">返値</h3> - -<p>指定したプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトです。</p> - -<h3 id="Exceptions" name="Exceptions">例外</h3> - -<p><code><var>proto</var></code> 引数は次のいずれかになります。</p> - -<ul> - <li>{{jsxref("null")}} または</li> - <li>{{jsxref("Object")}} ただし<a href="/ja/docs/Glossary/Primitive#Primitive_wrapper_objects_in_JavaScript">プリミティブラッパーオブジェクト</a>を除く</li> -</ul> - -<p><code>proto</code> がどちらでもない場合、 {{jsxref("TypeError")}} がスローされます。</p> - -<h2 id="Custom_and_Null_objects" name="Custom_and_Null_objects">カスタムオブジェクトと Null オブジェクト</h2> - -<p>完全にカスタムされたオブジェクトから作成された新しいオブジェクト (特に <code>null</code> オブジェクトから作成されたもの、基本的にはメンバーを持たないカスタムオブジェクト) は、予想外の振る舞いをすることがあります。これは特にデバッグ時に当てはまります。一般的なオブジェクト-プロパティ変換/検出ユーティリティ関数はエラーを生成したり、単に情報を失ったりする可能性があるからです (特にエラーを無視するサイレントエラートラップを使用している場合)。例えば、ここに二つのオブジェクトがあります。</p> - -<pre class="brush: js notranslate">oco = Object.create( {} ); // create a normal object -ocn = Object.create( null ); // create a "null" object - -> console.log(oco) // {} -- Seems normal -> console.log(ocn) // {} -- Seems normal here too, so far - -oco.p = 1; // create a simple property on normal obj -ocn.p = 0; // create a simple property on "null" obj - -> console.log(oco) // {p: 1} -- Still seems normal -> console.log(ocn) // {p: 0} -- Still seems normal here too. BUT WAIT... -</pre> - -<p>上記のように、今のところすべてが正常なように見えます。しかし、実際に使ってみると、その違いはすぐに明らかになります。</p> - -<pre class="brush: js notranslate">> "oco is: " + oco // shows "oco is: [object Object]" - -> "ocn is: " + ocn // throws error: Cannot convert object to primitive value -</pre> - -<p>多くの最も基本的な組み込み機能のほんの一部をテストするだけで、問題の大きさがより明確にわかります。</p> - -<pre class="brush: js notranslate">> alert(oco) // shows [object Object] -> alert(ocn) // throws error: Cannot convert object to primitive value - -> oco.toString() // shows [object Object] -> ocn.toString() // throws error: ocn.toString is not a function - -> oco.valueOf() // shows {} -> ocn.valueOf() // throws error: ocn.valueOf is not a function - -> oco.hasOwnProperty("p") // shows "true" -> ocn.hasOwnProperty("p") // throws error: ocn.hasOwnProperty is not a function - -> oco.constructor // shows "Object() { [native code] }" -> ocn.constructor // shows "undefined" -</pre> - -<p>このように、これらの違いにより、一見単純そうに見える問題であっても、デバッグがすぐに迷走してしまうことがあります。例えば、以下のようなものです。</p> - -<p><em>シンプルな共通デバッグ関数です。</em></p> - -<pre class="brush: js notranslate">// display top-level property name:value pairs of given object -function ShowProperties(obj){ - for(var prop in obj){ - console.log(prop + ": " + obj[prop] + "\n" ); - } -}</pre> - -<p><em>このような単純な結果ではありません。 (特にサイレントエラートラップがエラーメッセージを隠していた場合)</em></p> - -<pre class="brush: js notranslate">ob={}; ob.po=oco; ob.pn=ocn; // create a compound object using the test objects from above as property values - -> ShowProperties( ob ) // display top-level properties -- po: [object Object] -- Error: Cannot convert object to primitive value - -Note that only first property gets shown. -</pre> - -<p><em>(しかし、同じオブジェクトが単に順番が違うだけで作成されている場合 -- 少なくともいくつかの実装では...)</em></p> - -<pre class="brush: js notranslate">ob={}; ob.pn=ocn; ob.po=oco; // create same compound object again, but create same properties in different order - -> ShowProperties( ob ) // display top-level properties -- Error: Cannot convert object to primitive value - -Note that neither property gets shown.</pre> - -<p>Note that such a different order may arise statically via disparate fixed codings such as here, but also dynamically via whatever the order any such property-adding code-branches actually get executed at runtime as depends on inputs and/or random-variables. Then again, the actual iteration order is not guaranteed no matter what the order members are added.</p> - -<p>Be aware of, also, that using Object.entries() on an object created via Object.create() will result in an empty array being returned.</p> - -<pre class="brush: js notranslate">var obj = Object.create({ a: 1, b: 2 }); - -> console.log(Object.entries(obj)); // shows "[]" -</pre> - -<h4 id="Some_NON-solutions">Some NON-solutions</h4> - -<p>A good solution for the missing object-methods is not immediately apparent.</p> - -<p>Adding the missing object-method directly from the standard-object does NOT work:</p> - -<pre class="brush: js notranslate">ocn = Object.create( null ); // create "null" object (same as before) - -ocn.toString = Object.toString; // since new object lacks method then try assigning it directly from standard-object - -<span>> ocn.toString // shows "toString() { [native code] }" -- missing method seems to be there now</span> -> ocn.toString == Object.toString // shows "true" -- method seems to be same as the standard object-method - -> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function -</pre> - -<p><br> - Adding the missing object-method directly to new object's "prototype" does not work either, since the new object does not have a real prototype (which is really the cause of ALL these problems) and one cannot be <strong>directly</strong> added:</p> - -<pre class="brush: js notranslate">ocn = Object.create( null ); // create "null" object (same as before) - -ocn.prototype.toString = Object.toString; // Error: Cannot set property 'toString' of undefined - -ocn.prototype = {}; // try to create a prototype -ocn.prototype.toString = Object.toString; // since new object lacks method then try assigning it from standard-object <span> - -> ocn.toString() // error: ocn.toString is not a function</span> -</pre> - -<p><br> - Adding the missing object-method by using the standard-object<strong> </strong>as new object's prototype does not work either:</p> - -<pre class="brush: js notranslate">ocn = Object.create( null ); // create "null" object (same as before) -Object.setPrototypeOf(ocn, Object); // set new object's prototype to the standard-object - -> ocn.toString() // error: Function.prototype.toString requires that 'this' be a Function -</pre> - -<h4 id="Some_OK_solutions">Some OK solutions</h4> - -<p>Again, adding the missing object-method directly from the <strong>standard-object </strong>does NOT work. However, adding the <strong>generic</strong> method directly, DOES:</p> - -<pre class="brush: js notranslate">ocn = Object.create( null ); // create "null" object (same as before) - -ocn.toString = toString; // since new object lacks method then assign it directly from generic version - -> ocn.toString() // shows "[object Object]" -> "ocn is: " + ocn // shows "ocn is: [object Object]" - - -ob={}; ob.pn=ocn; ob.po=oco; // create a compound object (same as before) - -> ShowProperties(ob) // display top-level properties -- po: [object Object] -- pn: [object Object] -</pre> - -<p>However, setting the generic <strong>prototype</strong> as the new object's prototype works even better:</p> - -<pre class="brush: js notranslate">ocn = Object.create( null ); // create "null" object (same as before) -Object.setPrototypeOf(ocn, Object.prototype); // set new object's prototype to the "generic" object (NOT standard-object) -</pre> - -<p><em>(In addition to all the string-related functions shown above, this also adds:)</em></p> - -<pre class="brush: js notranslate">> ocn.valueOf() // shows {} -> ocn.hasOwnProperty("x") // shows "false" -> ocn.constructor // shows "Object() { [native code] }" - -// ...and all the rest of the properties and methods of Object.prototype. -</pre> - -<p>As shown, objects modified this way now look very much like ordinary objects.</p> - -<h2 id="Polyfill" name="Polyfill">ポリフィル</h2> - -<p>このポリフィルは、プロトタイプは選択されたが第二引数を考慮しない状況向けに、新規オブジェクトを生成する主要な利用法に対応します。</p> - -<p>実際の ES5 の <code>Object.create</code> では、<code>[[Prototype]]</code> として <code>null</code> を設定することがサポートされていますが、このポリフィルは ECMAScript5 以前のサポートをする制約上、null を使用できないことに注意してください。</p> - -<pre class="brush: js notranslate"> if (typeof Object.create !== "function") { - Object.create = function (proto, propertiesObject) { - if (typeof proto !== 'object' && typeof proto !== 'function') { - throw new TypeError('Object prototype may only be an Object: ' + proto); - } else if (proto === null) { - throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."); - } - - if (typeof propertiesObject != 'undefined') { - throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument."); - } - - function F() {} - F.prototype = proto; - - return new F(); - }; -} -</pre> - -<h2 id="Examples" name="Examples">例</h2> - -<h3 id="Classical_inheritance_with_Object.create" name="Classical_inheritance_with_Object.create"><code>Object.create()</code> を用いた古典的な継承</h3> - -<p>以下の例は、古典的な継承をするための <code>Object.create()</code> の使用方法です。これは、すべての JavaScript が対応している単一継承です。</p> - -<pre class="brush: js notranslate">// Shape - superclass -function Shape() { - this.x = 0; - this.y = 0; -} - -// superclass method -Shape.prototype.move = function(x, y) { - this.x += x; - this.y += y; - console.info('Shape moved.'); -}; - -// Rectangle - subclass -function Rectangle() { - Shape.call(this); // call super constructor. -} - -// subclass extends superclass -Rectangle.prototype = Object.create(Shape.prototype); - -//If you don't set Rectangle.prototype.constructor to Rectangle, -//it will take the prototype.constructor of Shape (parent). -//To avoid that, we set the prototype.constructor to Rectangle (child). -Rectangle.prototype.constructor = Rectangle; - -var rect = new Rectangle(); - -console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true -console.log('Is rect an instance of Shape?', rect instanceof Shape); // true -rect.move(1, 1); // Outputs, 'Shape moved.' -</pre> - -<p>複数のオブジェクトから継承したい場合は、ミックスインが可能です。</p> - -<pre class="brush: js notranslate">function MyClass() { - SuperClass.call(this); - OtherSuperClass.call(this); -} - -// inherit one class -MyClass.prototype = Object.create(SuperClass.prototype); -// mixin another -Object.assign(MyClass.prototype, OtherSuperClass.prototype); -// re-assign constructor -MyClass.prototype.constructor = MyClass; - -MyClass.prototype.myMethod = function() { - // do something -}; -</pre> - -<p>{{jsxref("Object.assign()")}} は OtherSuperClass プロトタイプから MyClass プロトタイプへプロパティをコピーし、 MyClass のすべてのインスタンスで利用できるようにします。 <code>Object.assign()</code> は ES2015 で導入され、<a href="/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill">ポリフィルを利用することができます</a>。古いブラウザーへの対応が必要な場合は、 <code><a href="https://api.jquery.com/jQuery.extend/">jQuery.extend()</a></code> または <code><a href="https://lodash.com/docs/#assign">_.assign()</a></code> を利用することができます。</p> - -<h3 id="Using_propertiesObject_argument_with_Object.create" name="Using_propertiesObject_argument_with_Object.create">Object.create() と propertiesObject 引数の併用</h3> - -<pre class="brush: js notranslate">var o; - -// プロトタイプを null にしてオブジェクトを生成 -o = Object.create(null); - - -o = {}; -// is equivalent to: -o = Object.create(Object.prototype); - - -// Example where we create an object with a couple of -// sample properties. (Note that the second parameter -// maps keys to *property descriptors*.) -o = Object.create(Object.prototype, { - // foo is a regular 'value property' - foo: { - writable: true, - configurable: true, - value: 'hello' - }, - // bar is a getter-and-setter (accessor) property - bar: { - configurable: false, - get: function() { return 10; }, - set: function(value) { - console.log('Setting `o.bar` to', value); - } -/* with ES2015 Accessors our code can look like this - get() { return 10; }, - set(value) { - console.log('Setting `o.bar` to', value); - } */ - } -}); - - -function Constructor() {} -o = new Constructor(); -// is equivalent to: -o = Object.create(Constructor.prototype); -// Of course, if there is actual initialization code -// in the Constructor function, -// the Object.create() cannot reflect it - - -// Create a new object whose prototype is a new, empty -// object and add a single property 'p', with value 42. -o = Object.create({}, { p: { value: 42 } }); - -// by default properties ARE NOT writable, -// enumerable or configurable: -o.p = 24; -o.p; -// 42 - -o.q = 12; -for (var prop in o) { - console.log(prop); -} -// 'q' - -delete o.p; -// false - -// to specify an ES3 property -o2 = Object.create({}, { - p: { - value: 42, - writable: true, - enumerable: true, - configurable: true - } -}); -/* is not equivalent to: -This will create an object with prototype : {p: 42 } -o2 = Object.create({p: 42}) */ -</pre> - -<h2 id="Specifications" name="Specifications">仕様書</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">仕様書</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('ESDraft', '#sec-object.create', 'Object.create')}}</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザーの互換性</h2> - -<div> -<p>{{Compat("javascript.builtins.Object.create")}}</p> -</div> - -<h2 id="See_also" name="See_also">関連情報</h2> - -<ul> - <li>{{jsxref("Object.defineProperty()")}}</li> - <li>{{jsxref("Object.defineProperties()")}}</li> - <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> - <li>{{jsxref("Reflect.construct()")}}</li> - <li><a href="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf()</a> に関する John Resig 氏の投稿</li> -</ul> diff --git a/files/ja/web/javascript/reference/global_objects/object/create/index.md b/files/ja/web/javascript/reference/global_objects/object/create/index.md new file mode 100644 index 0000000000..6353f24d76 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/object/create/index.md @@ -0,0 +1,398 @@ +--- +title: Object.create() +slug: Web/JavaScript/Reference/Global_Objects/Object/create +tags: + - ECMAScript 5 + - JavaScript + - Method + - 'Null' + - Object + - Reference + - Polyfill +browser-compat: javascript.builtins.Object.create +translation_of: Web/JavaScript/Reference/Global_Objects/Object/create +--- +{{JSRef}} + +**`Object.create()`** メソッドは、既存のオブジェクトを新しく生成されるオブジェクトのプロトタイプとして使用して、新しいオブジェクトを生成します。 + +{{EmbedInteractiveExample("pages/js/object-create.html", "taller")}} + +## 構文 + +```js +Object.create(proto) +Object.create(proto, propertiesObject) +``` + +### 引数 + +- `proto` + - : 新たに生成されるオブジェクトのプロトタイプになるべきオブジェクトです。 +- `propertiesObject` {{Optional_inline}} + - : 指定されていて、 {{jsxref("undefined")}} でない場合、それ自身の列挙可能なプロパティ (つまり、それ自身に定義されているものであり、プロトタイプチェーンの中での列挙可能なプロパティでは*ない*もの) が、それらのプロパティ名を伴う一連のプロパティ記述子を指定し、新たに生成されるオブジェクトに追加されることになります。これらのプロパティは、 {{jsxref("Object.defineProperties()")}} の 2 番目の引数に対応するものです。 + +### 返値 + +指定したプロトタイプオブジェクトとプロパティを持つ新しいオブジェクトです。 + +### 例外 + +`proto` 引数は次のいずれかになります。 + +- {{jsxref("null")}} または +- {{jsxref("Object")}} ただし[プリミティブラッパーオブジェクト](/ja/docs/Glossary/Primitive#primitive_wrapper_objects_in_javascript)を除く + +`proto` がどちらでもない場合、 {{jsxref("TypeError")}} が発生します。 + +## カスタムオブジェクトと Null オブジェクト + +完全なカスタムオブジェクト (特に `null` オブジェクトから作成されたもの、基本的にはメンバーを持たないカスタムオブジェクト) から生成された新しいオブジェクトは、予想外の振る舞いをすることがあります。これは特にデバッグ時に当てはまります。一般的なオブジェクト-プロパティ変換/検出ユーティリティ関数はエラーを生成したり、単に情報を失ったりする可能性があるからです (特にエラーを無視するサイレントエラートラップを使用している場合)。例えば、ここに 2 つのオブジェクトがあります。 + +```js +oco = Object.create( {} ); // 通常のオブジェクトを生成 +ocn = Object.create( null ); // "null" オブジェクトを生成 + +> console.log(oco) // {} -- 普通に見えます +> console.log(ocn) // {} -- これまでのところ、普通に見えます + +oco.p = 1; // 通常オブジェクトに単純なプロパティを生成 +ocn.p = 0; // "null" オブジェクトに単純なプロパティを生成 + +> console.log(oco) // {p: 1} -- まだ普通に見えます +> console.log(ocn) // {p: 0} -- まだ普通に見えますが、待ってください... +``` + +上記のように、今のところすべてが正常なように見えます。しかし、実際に使ってみると、その違いはすぐに明らかになります。 + +```js +> "oco is: " + oco // "oco is: [object Object]" と表示 + +> "ocn is: " + ocn // エラーが発生: Cannot convert object to primitive value +``` + +多くの最も基本的な組み込み機能のほんの一部をテストするだけで、問題の大きさがより明確にわかります。 + +```js +> alert(oco) // [object Object] と表示 +> alert(ocn) // エラーが発生: Cannot convert object to primitive value + +> oco.toString() // [object Object] と表示 +> ocn.toString() // エラーが発生: ocn.toString is not a function + +> oco.valueOf() // {} と表示 +> ocn.valueOf() // エラーが発生: ocn.valueOf is not a function + +> oco.hasOwnProperty("p") // "true" と表示 +> ocn.hasOwnProperty("p") // エラーが発生: ocn.hasOwnProperty is not a function + +> oco.constructor // "Object() { [native code] }" と表示 +> ocn.constructor // "undefined" と表示 +``` + +このように、これらの違いにより、一見単純そうに見える問題であっても、デバッグがすぐに迷走してしまうことがあります。例えば、以下のようなものです。 + +_シンプルな共通デバッグ関数です。_ + +```js +// 与えられたオブジェクトの最上位のプロパティ名と値の組を表示 +function ShowProperties(obj){ + for(var prop in obj){ + console.log(prop + ": " + obj[prop] + "\n" ); + } +} +``` + +_このような単純な結果ではありません。 (特にサイレントエラートラップがエラーメッセージを隠していた場合)_ + +```js +ob={}; ob.po=oco; ob.pn=ocn; // 上記のテストオブジェクトをプロパティ値として使用して、複合オブジェクトを生成します。 + +> ShowProperties( ob ) // 最上位のプロパティを表示 +- po: [object Object] +- Error: Cannot convert object to primitive value + +最初のプロパティのみが表示されることに注意してください。 +``` + +_(しかし、同じオブジェクトが単に順番が違うだけで作成されている場合 -- 少なくともいくつかの実装では...)_ + +```js +ob={}; ob.pn=ocn; ob.po=oco; // 同じ複合オブジェクトを再度作成しますが、同じプロパティを異なる順序で作成します。 + +> ShowProperties( ob ) // 最上位のプロパティを表示 +- Error: Cannot convert object to primitive value + +どちらのプロパティも表示されないことに注意してください。 +``` + +なお、このような順序の変化は、静的にはここにあるような異なる固定されたコードによって生じることがありますが、動的には、このようなプロパティを追加するコードの分岐が、入力やランダム変数によって実行される順序が変わることで生じることもあります。ただし、どのような順序でメンバーを追加しても、実際の反復順序は保証されません。 + +また、 Object.create() で生成されたオブジェクトに Object.entries() を使用すると、空の配列が返されることにも注意してください。 + +```js +var obj = Object.create({ a: 1, b: 2 }); + +> console.log(Object.entries(obj)); // "[]" と表示 +``` + +#### いくつかの解決しない方法 + +オブジェクトメソッドが不足していることについての良い解決策は、すぐには見つかりません。 + +不足しているオブジェクトメソッドを標準オブジェクトから直接追加してもうまくいきません。 + +```js +ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ) + +ocn.toString = Object.toString; // 新しいオブジェクトにはメソッドがないので、標準オブジェクトから直接代入してみる + +> ocn.toString // "toString() { [native code] }" と表示 -- 存在しないメソッドが来たように見えます +> ocn.toString == Object.toString // "true" と表示 -- 標準オブジェクトのメソッドと同じように見えるメソッド + +> ocn.toString() // エラー: Function.prototype.toString requires that 'this' be a Function +``` + +不足しているオブジェクトメソッドを新しいオブジェクトの「プロトタイプ」に直接追加してもうまくいきません。なぜなら、新しいオブジェクトは本当のプロトタイプを持っておらず (これがすべての問題における真の原因です)、プロトタイプを**直接**追加することはできないからです。 + +```js +ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ) + +ocn.prototype.toString = Object.toString; // エラー: Cannot set property 'toString' of undefined + +ocn.prototype = {}; // プロトタイプを生成してみる +ocn.prototype.toString = Object.toString; // 新しいオブジェクトにはメソッドがないので、標準オブジェクトから代入してみる + +> ocn.toString() // エラー: ocn.toString is not a function +``` + +[`Object.setPrototypeOf()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf) の第 2 引数に標準オブジェクト自身の名前を指定して、不足しているオブジェクトメソッドを追加しようとしても、うまくいきません。 + +```js +ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ) +Object.setPrototypeOf(ocn, Object); // 間違い。新しいオブジェクトのプロトタイプを Object() 関数に設定している + +> ocn.toString() // エラー: Function.prototype.toString requires that 'this' be a Function +``` + +#### いくつかの解決方法 + +繰り返しになりますが、欠落しているオブジェクトメソッドを**標準オブジェクト**から直接追加しても動作しません。しかし、**ジェネリック**メソッドを直接追加すると、動作します。 + +```js +ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ) + +ocn.toString = toString; // 新しいオブジェクトにはメソッドがないので、ジェネリック版から直接代入する + +> ocn.toString() // "[object Object]" と表示 +> "ocn is: " + ocn // "ocn is: [object Object]" と表示 + +ob={}; ob.pn=ocn; ob.po=oco; // 複合オブジェクトを生成 (既出と同じ) + +> ShowProperties(ob) // 最上位のプロパティを表示 +- po: [object Object] +- pn: [object Object] +``` + +しかし、ジェネリック**プロトタイプ**を新しいオブジェクトのプロトタイプとして設定すると、さらに効果的です。 + +```js +ocn = Object.create( null ); // "null" オブジェクトを生成 (既出と同じ) +Object.setPrototypeOf(ocn, Object.prototype); // 新しいオブジェクトのプロトタイプを (標準オブジェクトではなく) 「ジェネリック」オブジェクトに設定 +``` + +_(上記の文字列関連の関数に加えて、以下の関数も追加されています)_ + +```js +> ocn.valueOf() // {} と表示 +> ocn.hasOwnProperty("x") // "false" と表示 +> ocn.constructor // "Object() { [native code] }" と表示 + +// ...そして、それ以外の Object.prototype のすべてのプロパティとメソッドも +``` + +このように、この方法で変更されたオブジェクトは、普通のオブジェクトと同じように見えます。 + +## ポリフィル + +このポリフィルは、プロトタイプは選択されたが第二引数を考慮しない状況向けに、新規オブジェクトを生成する主要な利用法に対応します。 + +`null` を `[[Prototype]]` として設定することが、実際の ES5 の `Object.create` では対応していますが、このポリフィルは ECMAScript 5 以前のバージョンに対応する制約上、これに対応できないことに注意してください。 + +```js + if (typeof Object.create !== "function") { + Object.create = function (proto, propertiesObject) { + if (typeof proto !== 'object' && typeof proto !== 'function') { + throw new TypeError('Object prototype may only be an Object: ' + proto); + } else if (proto === null) { + throw new Error("This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument."); + } + + if (typeof propertiesObject != 'undefined') { + throw new Error("This browser's implementation of Object.create is a shim and doesn't support a second argument."); + } + + function F() {} + F.prototype = proto; + + return new F(); + }; +} +``` + +## 例 + +### `Object.create()` を用いた古典的な継承 + +以下の例は、古典的な継承をするための `Object.create()` の使用方法です。これは、すべての JavaScript が対応している単一継承です。 + +```js +// Shape - スーパークラス +function Shape() { + this.x = 0; + this.y = 0; +} + +// スーパークラスのメソッド +Shape.prototype.move = function(x, y) { + this.x += x; + this.y += y; + console.info('Shape moved.'); +}; + +// Rectangle - サブクラス +function Rectangle() { + Shape.call(this); // call super constructor. +} + +// サブクラスはスーパークラスを拡張する +Rectangle.prototype = Object.create(Shape.prototype); + +// Rectangle.prototype.constructor を Rectangle に設定しないと、 +// Shape (親) の prototype.constructor を取ることになります。 +// これを防ぐために、 prototype.constructor を Rectangle (子) に設定します。 +Rectangle.prototype.constructor = Rectangle; + +var rect = new Rectangle(); + +console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true +console.log('Is rect an instance of Shape?', rect instanceof Shape); // true +rect.move(1, 1); // Outputs, 'Shape moved.' +``` + +複数のオブジェクトから継承したい場合は、ミックスインが利用可能です。 + +```js +function MyClass() { + SuperClass.call(this); + OtherSuperClass.call(this); +} + +// inherit one class +MyClass.prototype = Object.create(SuperClass.prototype); +// mixin another +Object.assign(Object.getPrototypeOf(MyClass.prototype), OtherSuperClass.prototype); +// re-assign constructor +MyClass.prototype.constructor = MyClass; + +MyClass.prototype.myMethod = function() { + // do something +}; +``` + +{{jsxref("Object.assign()")}} は OtherSuperClass プロトタイプから MyClass プロトタイプへプロパティをコピーし、 MyClass のすべてのインスタンスで利用できるようにします。 `Object.assign()` は ES2015 で導入され、[ポリフィルを利用することができます](/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#polyfill)。古いブラウザーへの対応が必要な場合は、 [`jQuery.extend()`](https://api.jquery.com/jQuery.extend/) または +[`_.assign()`](https://lodash.com/docs/#assign) を利用することができます。 + +### Object.create() と propertiesObject 引数の併用 + +```js +var o; + +// プロトタイプを null にしてオブジェクトを生成 +o = Object.create(null); + +o = {}; +// これは次のものと同等です。 +o = Object.create(Object.prototype); + +// いくつかのサンプルプロパティを持つオブジェクトを作成 +// する例です。(2 番目の引数は、キーを*プロパティ記述子*に +// マッピングしていることに注意してください。) +o = Object.create(Object.prototype, { + // foo は普通の「値プロパティ」です + foo: { + writable: true, + configurable: true, + value: 'hello' + }, + // bar はゲッターとセッター (アクセサー) によるプロパティです + bar: { + configurable: false, + get: function() { return 10; }, + set: function(value) { + console.log('Setting `o.bar` to', value); + } +/* ES2015 のアクセサーでは、このようになります。 + get() { return 10; }, + set(value) { + console.log('Setting `o.bar` to', value); + } */ + } +}); + +function Constructor() {} +o = new Constructor(); +// これは次のものと同等です。 +o = Object.create(Constructor.prototype); +// もちろん、コンストラクター関数に実際の初期化 +// コードがある場合は、 Object.create() には反映 +// されません + +// プロトタイプが新規の空オブジェクトである新しいオブジェクトを +// 生成し、単一のプロパティ 'p' を値を 42 にして追加します。 +o = Object.create({}, { p: { value: 42 } }); + +// 既定では、プロパティは書き込み可能、列挙可能、構成可能ではありません +o.p = 24; +o.p; +// 42 + +o.q = 12; +for (var prop in o) { + console.log(prop); +} +// 'q' + +delete o.p; +// false + +// ES3 プロパティを指定 +o2 = Object.create({}, { + p: { + value: 42, + writable: true, + enumerable: true, + configurable: true + } +}); +/* 次のものと同じではありません。 +これはプロトタイプが {p: 42 } であるオブジェクトを生成します。 +o2 = Object.create({p: 42}) */ +``` + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- `Object.create` のポリフィルは [`core-js`](https://github.com/zloirock/core-js#ecmascript-object) で利用できます +- {{jsxref("Object.defineProperty()")}} +- {{jsxref("Object.defineProperties()")}} +- {{jsxref("Object.prototype.isPrototypeOf()")}} +- {{jsxref("Reflect.construct()")}} +- John Resig の [getPrototypeOf()](http://ejohn.org/blog/objectgetprototypeof/) の投稿 |