From bba1788dd593e5f64bfb6814cb550259638619a0 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Mon, 9 Aug 2021 13:01:42 +0900 Subject: Web/JavaScript/Reference/Global_Objects/Object 以下の一部を Markdown に変換 (#1691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 以下のページを Markdown に変換。必要に応じて 2021/07/25 時点の英語版に同期。 - Web/JavaScript/Reference/Global_Objects/Object - Web/JavaScript/Reference/Global_Objects/Object/__defineGetter__ - Web/JavaScript/Reference/Global_Objects/Object/__defineSetter__ - Web/JavaScript/Reference/Global_Objects/Object/__lookupGetter__ - Web/JavaScript/Reference/Global_Objects/Object/__lookupSetter__ - Web/JavaScript/Reference/Global_Objects/Object/assign - Web/JavaScript/Reference/Global_Objects/Object/constructor - Web/JavaScript/Reference/Global_Objects/Object/Object - Web/JavaScript/Reference/Global_Objects/Object/proto --- .../global_objects/object/constructor/index.html | 255 --------------------- .../global_objects/object/constructor/index.md | 224 ++++++++++++++++++ 2 files changed, 224 insertions(+), 255 deletions(-) delete mode 100644 files/ja/web/javascript/reference/global_objects/object/constructor/index.html create mode 100644 files/ja/web/javascript/reference/global_objects/object/constructor/index.md (limited to 'files/ja/web/javascript/reference/global_objects/object/constructor') diff --git a/files/ja/web/javascript/reference/global_objects/object/constructor/index.html b/files/ja/web/javascript/reference/global_objects/object/constructor/index.html deleted file mode 100644 index 617c5cdfea..0000000000 --- a/files/ja/web/javascript/reference/global_objects/object/constructor/index.html +++ /dev/null @@ -1,255 +0,0 @@ ---- -title: Object.prototype.constructor -slug: Web/JavaScript/Reference/Global_Objects/Object/constructor -tags: - - JavaScript - - Object - - Property - - Prototype -translation_of: Web/JavaScript/Reference/Global_Objects/Object/constructor ---- -
{{JSRef}}
- -

constructor プロパティは、インスタンスオブジェクトを生成した {{jsxref("Object")}} のコンストラクター関数への参照を返します。なお、このプロパティの値は関数そのものへの参照であり、関数名を含んだ文字列ではありません。

- -

値が 1, true, "test" のようなプリミティブ値の場合は読み取り専用です。

- -

解説

- -

(Object.create(null) で生成されたオブジェクトを除いて) すべてのオブジェクトが constructor プロパティを持ちます。明示的にコンストラクター関数を用いることなく生成されたオブジェクト (オブジェクトリテラルや配列リテラルなど) は、 constructor プロパティがそのオブジェクトの基礎オブジェクトのコンストラクター型を指します。

- -
let o = {}
-o.constructor === Object // true
-
-let o = new Object
-o.constructor === Object // true
-
-let a = []
-a.constructor === Array // true
-
-let a = new Array
-a.constructor === Array // true
-
-let n = new Number(3)
-n.constructor === Number // true
-
- -

- -

オブジェクトのコンストラクターの表示

- -

以下の例では、コンストラクターである Tree と、その方のオブジェクトである theTree を生成します。そして、 theTree オブジェクトの constructor プロパティを表示します。

- -
function Tree(name) {
-  this.name = name
-}
-
-let theTree = new Tree('Redwood')
-console.log('theTree.constructor is ' + theTree.constructor)
-
- -

この例の出力は次のとおりです。

- -
theTree.constructor is function Tree(name) {
-  this.name = name
-}
-
- -

オブジェクトのコンストラクターの変更

- -

次の例は、一般的なオブジェクトのコンストラクターの値を変更する方法を示しています。 true, 1, "test" については、 (コンストラクターが読み取り専用のネイティブのものであるため) 影響を受けません。

- -

この例は、オブジェクトの constructor プロパティに頼ることが常に安全とは限らないことを示しています。

- -
function Type () {}
-
-let types = [
-  new Array(),
-  [],
-  new Boolean(),
-  true,             // 変わらない
-  new Date(),
-  new Error(),
-  new Function(),
-  function () {},
-  Math,
-  new Number(),
-  1,                // 変わらない
-  new Object(),
-  {},
-  new RegExp(),
-  /(?:)/,
-  new String(),
-  'test'            // 変わらない
-];
-
-for (let i = 0; i < types.length; i++) {
-  types[i].constructor = Type
-  types[i] = [types[i].constructor, types[i] instanceof Type, types[i].toString()]
-}
-
-console.log(types.join('\n'))
-
- -

この例の出力は次の通りです (参考にコメントを追加しています)。

- -
function Type() {},false,                                     // new Array()
-function Type() {},false,                                     // []
-function Type() {},false,false                                // new Boolean()
-function Boolean() {
-    [native code]
-},false,true                                                  // true
-function Type() {},false,Mon Sep 01 2014 16:03:49 GMT+0600    // new Date()
-function Type() {},false,Error                                // new Error()
-function Type() {},false,function anonymous() {
-
-}                                                             // new Function()
-function Type() {},false,function () {}                       // function () {}
-function Type() {},false,[object Math]                        // Math
-function Type() {},false,0                                    // new Number()
-function Number() {
-    [native code]
-},false,1                                                     // 1
-function Type() {},false,[object Object]                      // new Object()
-function Type() {},false,[object Object]                      // {}
-function Type() {},false,/(?:)/                               // new Regexp()
-function Type() {},false,/(?:)/                               // /(?:)/
-function Type() {},false,                                     // new String()
-function String() {
-    [native code]
-},false,test                                                  // 'test'
-
- -

関数のコンストラクターの変更

- -

多くの場合、このプロパティは new およびプロトタイプ継承チェーンで将来の呼び出しに使われる関数コンストラクターとしての関数の定義に使用されます。

- -
function Parent() { /* ... */ }
-Parent.prototype.parentMethod = function parentMethod() {}
-
-function Child() {
-   Parent.call(this) // Make sure everything is initialized properly
-}
-Child.prototype = Object.create(Parent.prototype) // Child のプロトタイプを Parent のプロトタイプで再定義
-
-Child.prototype.constructor = Child // Child の元のコンストラクターを復帰
- -

しかし、いつこの最後の行を実行する必要があるのでしょうか。残念ながら、正しい答えは、場合によるということです。

- -

元のコンストラクターを再割り当てすることが重要である場合と、これがコードの未使用の一行になる場合を定義してみましょう。

- -

以下の場合を見てみてください。オブジェクトが自分自身を生成するために create() メソッドを持っています。

- -
function Parent() { /* ... */ }
-function CreatedConstructor() {
-   Parent.call(this)
-}
-
-CreatedConstructor.prototype = Object.create(Parent.prototype)
-
-CreatedConstructor.prototype.create = function create() {
-  return new this.constructor()
-}
-
-new CreatedConstructor().create().create() // TypeError undefined is not a function since constructor === Parent
- -

上記の例では、コンストラクターが Parent にリンクしているため、例外が発生します。

- -

これを防ぐには、利用したいことに必要なコンストラクターを割り当てるだけです。

- -
function Parent() { /* ... */ }
-function CreatedConstructor() { /* ... */ }
-
-CreatedConstructor.prototype = Object.create(Parent.prototype)
-CreatedConstructor.prototype.constructor = CreatedConstructor // sets the correct constructor for future use
-
-CreatedConstructor.prototype.create = function create() {
-  return new this.constructor()
-}
-
-new CreatedConstructor().create().create() // it's pretty fine
- -

これで、コンストラクターの変更が有用である理由が明確になりました。

- -

もう一つの例を考えてみましょう。

- -
function ParentWithStatic() {}
-
-ParentWithStatic.startPosition = { x: 0, y:0 } // Static member property
-ParentWithStatic.getStartPosition = function getStartPosition() {
-  return this.startPosition
-}
-
-function Child(x, y) {
-  this.position = {
-    x: x,
-    y: y
-  }
-}
-
-Child = Object.assign(ParentWithStatic)
-Child.prototype = Object.create(ParentWithStatic.prototype)
-Child.prototype.constructor = Child
-
-Child.prototype.getOffsetByInitialPosition = function getOffsetByInitialPosition() {
-  let position = this.position
-  let startPosition = this.constructor.getStartPosition() // error undefined is not a function, since the constructor is Child
-
-  return {
-    offsetX: startPosition.x - position.x,
-    offsetY: startPosition.y - position.y
-  }
-};
- -

この例では、正常に動作するように親のコンストラクターを維持するか、静的プロパティを子のコンストラクタに再割り当てする必要があります。

- -
...
-Child = Object.assign(ParentWithStatic) // Notice that we assign it before we create(...) a prototype below
-Child.prototype = Object.create(ParentWithStatic.prototype)
-...
-
- -

または、親コンストラクターの識別子を子コンストラクター関数の別のプロパティに代入し、そのプロパティを介してアクセスします。

- -
...
-Child.parentConstructor = ParentWithStatic
-Child.prototype = Object.create(ParentWithStatic.prototype)
-...
-   let startPosition = this.constructor.parentConstructor.getStartPosition()
-...
-
- -
-

まとめ: コンストラクターを手動で更新したり設定したりすると、異なる結果や混乱する結果を導くことがあります。これを防ぐためには、それぞれの場合に応じてコンストラクターの役割を定義することが必要です。多くの場合、コンストラクター使用されず、再割り当ての必要はありません。

-
- -

仕様書

- - - - - - - - - - - - -
仕様書
{{SpecName('ESDraft', '#sec-object.prototype.constructor', 'Object.prototype.constructor')}}
- -

ブラウザーの互換性

- -

{{Compat("javascript.builtins.Object.constructor")}}

- -

関連情報

- - - - diff --git a/files/ja/web/javascript/reference/global_objects/object/constructor/index.md b/files/ja/web/javascript/reference/global_objects/object/constructor/index.md new file mode 100644 index 0000000000..35ea5680f9 --- /dev/null +++ b/files/ja/web/javascript/reference/global_objects/object/constructor/index.md @@ -0,0 +1,224 @@ +--- +title: Object.prototype.constructor +slug: Web/JavaScript/Reference/Global_Objects/Object/constructor +tags: + - JavaScript + - Object + - Property + - Prototype +browser-compat: javascript.builtins.Object.constructor +translation_of: Web/JavaScript/Reference/Global_Objects/Object/constructor +--- +{{JSRef}} + +**`constructor`** プロパティは、インスタンスオブジェクトを生成した {{jsxref("Object")}} のコンストラクター関数への参照を返します。なお、このプロパティの値は*関数そのものへの参照*であり、関数名を含んだ文字列ではありません。 + +値が `1`, `true`, `"test"` のようなプリミティブ値の場合は読み取り専用です。 + +## 解説 + +(`Object.create(null)` で生成されたオブジェクトを除いて) すべてのオブジェクトが `constructor` プロパティを持っています。明示的にコンストラクター関数を用いることなく生成されたオブジェクト (オブジェクトリテラルや配列リテラルなど) は、 `constructor` プロパティがそのオブジェクトの基礎オブジェクトのコンストラクター型を指します。 + +```js +let o = {} +o.constructor === Object // true + +let o = new Object +o.constructor === Object // true + +let a = [] +a.constructor === Array // true + +let a = new Array +a.constructor === Array // true + +let n = new Number(3) +n.constructor === Number // true +``` + +## 例 + +### オブジェクトのコンストラクターの表示 + +以下の例では、コンストラクター (`Tree`) と、その型のオブジェクト (`theTree`) を生成します。そして、 `theTree` オブジェクトの `constructor` プロパティを表示します。 + +```js +function Tree(name) { + this.name = name +} + +let theTree = new Tree('Redwood') +console.log('theTree.constructor is ' + theTree.constructor) +``` + +この例の出力は次のとおりです。 + +```js +theTree.constructor is function Tree(name) { + this.name = name +} +``` + +### オブジェクトのコンストラクターの変更 + +`constructor` プロパティに代入することができるのは、対応するコンストラクター関数を持たない `null` および `undefined` 以外の値 (`String`、`Number`、`Boolean` など) ですが、プリミティブ値には変更が適用されません (例外は発生しません)。これは、プリミティブ値 (`null` と `undefined` を除く) にどのようなプロパティを設定しても効果がないのと同じ仕組みによるものです。つまり、このようなプリミティブをオブジェクトとして使用すると、対応するコンストラクターのインスタンスが生成され、文の実行後すぐに破棄されることになります。 + +```js +let val = null; +val.constructor = 1; //TypeError: var is null + +val = 'abc'; +val.constructor = Number; //val.constructor === String + +val.foo = 'bar'; //暗黙的に String('abc') のインスタンスが生成され、 foo プロパティに代入する +val.foo === undefined; //true になる。 String('abc') の新しいインスタンスがこの比較のために生成され、 foo プロパティがないため +``` + +つまり、上記のプリミティブ値を除いて、基本的に `constructor` プロパティの値を変更することができます。**なお、 `constructor` プロパティを変更しても、 instanceof 演算子には影響しません**。 + +```js +let a = []; +a.constructor = String +a.constructor === String // true +a instanceof String //false +a instanceof Array //true + +a = new Foo(); +a.constructor = 'bar' +a.constructor === 'bar' // true + +//etc. +``` + +オブジェクトが封印または凍結されていた場合は、変更の効果がなくなり、例外は発生しません。 + +```js +let a = Object.seal({}); +a.constructor = Number; +a.constructor === Object; //true +``` + +### 関数のコンストラクターの変更 + +多くの場合、このプロパティは**関数コンストラクター**としての関数の定義に使用され、将来の **new** およびプロトタイプ継承チェーンでの呼び出しに使われます。 + +```js +function Parent() { /* ... */ } +Parent.prototype.parentMethod = function parentMethod() {} + +function Child() { + Parent.call(this) // すべてが正しく初期化されていることを確認 +} +Child.prototype = Object.create(Parent.prototype) // 子のプロトタイプを親のプロトタイプで再定義 + +Child.prototype.constructor = Child // 元のコンストラクターとして Child を返す +``` + +しかし、いつこの最後の行を実行する必要があるのでしょうか。残念ながら、正しい答えは、*場合による*ということです。 + +元のコンストラクターを再割り当てすることが重要である場合と、これがコードの未使用の一行になる場合を定義してみましょう。 + +以下の場合を見てみてください。オブジェクトが自分自身を生成するために `create()` メソッドを持っています。 + +```js +function Parent() { /* ... */ } +function CreatedConstructor() { + Parent.call(this) +} + +CreatedConstructor.prototype = Object.create(Parent.prototype) + +CreatedConstructor.prototype.create = function create() { + return new this.constructor() +} + +new CreatedConstructor().create().create() // TypeError undefined is not a function since constructor === Parent +``` + +上記の例では、コンストラクターが Parent にリンクしているため、例外が発生します。 + +これを防ぐには、利用しようとしている必要なコンストラクターを代入するだけです。 + +```js +function Parent() { /* ... */ } +function CreatedConstructor() { /* ... */ } + +CreatedConstructor.prototype = Object.create(Parent.prototype) +CreatedConstructor.prototype.constructor = CreatedConstructor // 将来使用するために正しいコンストラクターを設定 + +CreatedConstructor.prototype.create = function create() { + return new this.constructor() +} + +new CreatedConstructor().create().create() // とてもよくなった +``` + +これで、コンストラクターの変更が有用である理由が明確になりました。 + +もう一つの例を考えてみましょう。 + +```js +function ParentWithStatic() {} + +ParentWithStatic.startPosition = { x: 0, y:0 } // Static member property +ParentWithStatic.getStartPosition = function getStartPosition() { + return this.startPosition +} + +function Child(x, y) { + this.position = { + x: x, + y: y + } +} + +Child = Object.assign(Child, ParentWithStatic) // 静的メンバーを ParentWithStatic から Child へコピー +Child.prototype = Object.create(ParentWithStatic.prototype) +Child.prototype.constructor = Child + +Child.prototype.getOffsetByInitialPosition = function getOffsetByInitialPosition() { + let position = this.position + let startPosition = this.constructor.getStartPosition() // error undefined is not a function, since the constructor is Child + + return { + offsetX: startPosition.x - position.x, + offsetY: startPosition.y - position.y + } +}; +``` + +この例では、正常に動作するように親のコンストラクターを維持するか、静的プロパティを子のコンストラクタに再代入する必要があります。 + +```js +... +Child = Object.assign(Child, ParentWithStatic) // Notice that we assign it before we create(...) a prototype below +Child.prototype = Object.create(ParentWithStatic.prototype) +... +``` + +または、親コンストラクターの識別子を子コンストラクター関数の別のプロパティに代入し、そのプロパティを介してアクセスします。 + +```js +... +Child.parentConstructor = ParentWithStatic +Child.prototype = Object.create(ParentWithStatic.prototype) +... + let startPosition = this.constructor.parentConstructor.getStartPosition() +... +``` + +> **Note:** コンストラクターを手動で更新したり設定したりすると、異なる結果や混乱する結果を導くことがあります。これを防ぐためには、それぞれの場合に応じて `constructor` の役割を定義することが必要です。多くの場合、 `constructor` 使用されず、再割り当ての必要はありません。 + +## 仕様書 + +{{Specifications}} + +## ブラウザーの互換性 + +{{Compat}} + +## 関連情報 + +- {{jsxref("statements/class","クラス宣言","",1)}} +- {{jsxref("Classes/constructor","クラスのコンストラクター","",1)}} +- 用語集: {{Glossary("constructor", "コンストラクター", 1)}} -- cgit v1.2.3-54-g00ecf