質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

5612閲覧

オブジェクト、コンストラクタの考え方

SugiuraY

総合スコア317

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

5グッド

7クリップ

投稿2016/12/07 14:57

お世話になっております。

Javascriptの基礎的な部分を本気で理解しようとしているのですが、どうもどの参考書やサイトを見ても一足飛びのところがあり、腹落ちしない部分があります。

まず、私が文字通りで理解していることは

①オブジェクトとインスタンス
名前をキーにしてアクセスできる配列で、プロパティやメソッドにより構成されている。
例えば以下のような波括弧{...}を「オブジェクト」と呼ぶと理解しております。
var obj =
{animal:"dog"//プロパティ,
cry:function(){document.write("ワン");}//メソッド}

オブジェクトを使用するためにオブジェクトを複製したコピーをインスタンスと呼び、new演算子によりインスタンスを作ることができる。この一連の行為をインスタンス化と呼ぶ。
例えば、上記を踏まえて以下のような、オブジェクト変数 copyをobjの「インスタンス」と理解しております。
var copy = new obj();

②コンストラクタ
参考サイトのコンストラクタの説明を読むと以下のように解説されています。

コンストラクタはオブジェクトを作成し、初期化する関数オブジェクトである。

参考サイト:http://javascript.keicode.com/lang/constructors.php

また、とある書籍では以下のように説明しています。

引用テキスト

オブジェクトには、オブジェクトを初期化するために、オブジェクトと同名のメソッドが用意されおり、この初期化メソッドのことをコンストラクタと呼ぶ。オブジェクト名は正確にはコンストラクタ名である。

実際掲載されている参考コードは下記の通りです。

javascript

1function Person(n) { // Constructor 2 this.name = n; 3 return this; // opt. 4} 5 6var p1 = new Person('Hanako'); 7document.write(p1.name);

質問(A)
ここで質問なのですが、コンストラクタとは結局メソッドなのですか?オブジェクトなのでしょうか?例えば、上記の参考コードでも具体的にどこの部分が定義上のコンストラクタであり、それがどのような役割を果たしているのかが全く理解できません。。そもそもこのコードの中で登場するオブジェクトは{this.name....return this;}だけと理解しており、中には何もメソッドはないように私のような素人には見えるのですが。。このオブジェクトではthis.name=n;がプロパティなのかもしれませんが、何もメソッドはないようなに思ってしまします。メソッドではないとしたら、ここのコンストラクタとは一体何なのでしょうか?
単にPersonオブジェクトをnew演算子でインスタンス化してp1という変数にインスタンスが代入されただけではないのでしょうか?

質問(B)
また、何を初期化しており、何のために初期化をしているのでしょうか?このコードから、初期化の過程と目的がうかがい知ることができません。

質問(C)
最後に最も根本的なことで申し訳ないのですが、
function Person(n){...}
obj={animal:"dog"...}
これらの波括弧の中身はどちらも「オブジェジクト」なのでしょうか?そもそもfunctionは自分で定義する関数として先に学んだのですが、これもオブジェクトの一つという整理なのでしょうか。また、関数を呼び出す場合、new演算子を使用することはないと思うのですが、なぜ上記の参考コードでは使用しているのでしょうか?

すみません、あまりにもわからず、的を絞れずにとりとめもなく質問を記載させていただいてしましましたが、端的には1.コンストラクが何を指し、具体的にどのような役割なのかがわからない、2.オブジェクトでも関数のオブジェクトと通常のオブジェクトが何が違うのかがわからないということになりますでしょうか。

上記の参考コードをもとにできるだけ平易な内容でご回答を賜ることができれば大変嬉しいです。わがままを承知で申し上げているため、あらかじめ深いくお詫びを申し上げます。

よろしくお願い申し上げます。

TheSakuMa, kay5, kaputaros, sassoon👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

#前提:関数・メソッドはオブジェクトの一種である
オブジェクトにはいくつか種類があります。配列(Array)や日付・時間(Date)を使ったことがあるかもしれませんが、これらもオブジェクトです。

それと同じように、関数やメソッドもオブジェクトの一種です。{ hoge: 1, fuga: 2 }こういうのだけがオブジェクトというわけではありません。オブジェクトの世界はもっと広いです。

#前提:Functionオブジェクト
ここでは、関数とメソッドをひっくるめてFunctionオブジェクトと呼びます。function xxx() { ... }と書く(名前は無い場合も)ことで新しく誕生するオブジェクトのことです。

繰り返しますが、関数やメソッドはオブジェクトの一種です。ですからFunctionオブジェクトを「オブジェクト」と呼んで全く問題ありません。

#前提:「関数」と「メソッド」
ここでは、以下のように区別します。

  • 関数

JavaScript

1//名前を付けて宣言したFunctionオブジェクト 2function hoge() { ... } 3 4//変数に入れたFunctionオブジェクト 5//(名前は有っても無くても可) 6var a = function() { ... }; 7var b = function fuga() { ... };
  • メソッド

JavaScript

1//obj.func()のようにドットで繋いで呼び出せるFunctionオブジェクト 2var obj = new Object; 3obj.func = function() { ... }; 4 5//以下のようにしても可(書き方が違うだけで同じ) 6var obj = { 7 func: function() { ... } 8};

つまり、オブジェクトのプロパティであるかそうでないか、だけの違いです。本来はもうちょっと突っ込んで考えるべきことですが、今回はざっくり簡略化しています。


#回答A

コンストラクタとは結局メソッドなのですか?

そうかもしれないし、そうではないかもしれません。Functionオブジェクトでさえあればいいので、関数である場合もメソッドである場合も両方あり得ます。

オブジェクトなのでしょうか?

Functionオブジェクトは必ずオブジェクトなので、Yesです。

どこの部分が定義上のコンストラクタ

JavaScript

1function Person(n) { // Constructor 2 this.name = n; 3 return this; // opt. 4}

このFunctionオブジェクトがコンストラクタです。

このコードの中で登場するオブジェクトは{this.name....return this;}だけ

誤りです。Functionオブジェクト全体でとらえてください。波括弧はいくつかの行をひとまとめにして、その範囲を示しているだけです。

また、documentもオブジェクトです。writeもFunctionオブジェクトです。p1の中身もPersonのインスタンス、つまりPersonを元に作られた、Personとは別なオブジェクトです。JavaScriptの世界はオブジェクトだらけです。

中には何もメソッドはない

そのとおりです。ちなみに、参考コードの中で登場する唯一のメソッドがdocument.writeです。

メソッドではないとしたら、ここのコンストラクタとは一体何なのでしょうか?

関数であるFunctionオブジェクトです。

Personオブジェクトをnew演算子でインスタンス化してp1という変数にインスタンスが代入されただけ

そのとおりです。

#回答B

何を初期化しており

p1に代入されたインスタンスです。

何のために初期化をしている

1つより複数生成したほうがわかりやすいと思いますが、

JavaScript

1function Person(n) { 2 this.name = n; 3} 4 5var p1 = new Person('Hanako'); 6var p2 = new Person('Taro'); 7 8document.write(p1.name); //Hanakoが表示される 9document.write(p2.name); //Taroが表示される

コンストラクタはnewで呼ばれる際、受け取った値('Hanako'や'Taro')を、生成されるインスタンスのnameプロパティに設定します。この作業が初期化です。

その結果、生成された2つのインスタンスはそれぞれ、nameというプロパティを持っており、その中身にアクセスすることができます。表示される文字列が異なるのは、初期化の際にインスタンスごとに異なる値が設定されたからです。

#回答C

これらの波括弧の中身はどちらも「オブジェクト」なのでしょうか?

先に述べたように、FunctionオブジェクトはFunctionオブジェクト全体でとらえてください。結果としてオブジェクトなのはそのとおりですが、波括弧があるからではありません。

ifやforの波括弧も同じで、いくつかの行をひとまとめにするためのものです。これはオブジェクトとは関係ありません。波括弧を見たら必ずオブジェクトというとらえ方はできません。

そもそもfunctionは自分で定義する関数として先に学んだのですが、これもオブジェクトの一つ

そのとおりです。何度も述べているように、関数もオブジェクトの1つです。

関数を呼び出す場合、new演算子を使用することはない

それはコンストラクタではない、またはコンストラクタとして使用していないだけで、少なくても参考コードはそうしています。

もちろん、newで呼んだ関数がコンストラクタとして適切に働いてくれるかどうかはまた別な話ですので、何でもかんでも呼べるというわけではありません。

投稿2016/12/07 18:07

sii_side

総合スコア849

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/12/08 02:55

詳細に又平易な内容でご説明を頂戴いたしましたことを心より感謝を申し上げます。しかも質問A,B,Cのなかにも質問をちりばめてしまったのに細かく分解までして回答を頂けたことに涙です。5割程度を理解できたのですが、正直申し上げて、少し認識が曖昧な箇所について確認をさせていただきたく存じます。 1) 回答A 「参考コードの中で登場する唯一のメソッドがdocument.writeです。」について 私の理解、定義の中ではオブジェクトの中にあるファンクションがメソッドであると理解していたのですが、参照コードではdocument.write(p1.name);はどのオブジェクトにも包含されていないようにお見受けいたしますが、いかがでしょうか? 2) 回答A 「メソッドではないとしたら、ここのコンストラクタとは一体何なのでしょうか? 関数であるFunctionオブジェクトです。」 この定義が推察するにfunction xxx (){...}(関数オブジェクト)はコンストラクタとなり得るものである。これがnew演算子でインスタンスが生成されるときに特定のプロパティを初期化してくれるの機能をもっているので、これはコンストラクタと呼ぶことができる。その初期化する機能はthis.name=n;によって実現されるものである。 従って、 甲) function meet (n){document.write(n+"hello!");}はなにも初期化する機能は備わっていないのでコンストラクタとは呼べない(なりえない)。 乙) var obj = {animal:"dog", cry:function(){document.write("ワン");}}におけるvar objは関数オブジェクトではない(functionがついていないので)ため、コンストラクタとは呼べない(なりえない)。 このように解釈して差し支えないでしょうか? 3) 回答C 「関数を呼び出す場合、new演算子を使用することはない-それはコンストラクタではない、またはコンストラクタとして使用していないだけで、少なくても参考コードはそうしています。」 この点で、純粋に関数を呼び出すことと、関数オブジェクトをコンストラクタとして利用し、インスタンスを初期化することの目的や相違点を明確にさせてください。 丙) function meet (n){document.write(n+"hello!");} これを呼び出すときは meet ("Smith");とし、var greet = new meet();とはしないと思います。これは”Smithhello”を出力する際に、なにも初期化するべきプロパティがないため、newを使わずに関数を呼び出しているだけということなのでしょうか?また、これはそもそもnewをしていないのでインスタンスを生成しているわけではなく、引数の"Smith"を関数meetに代入してその結果をmeet("Smith");返しているだけという意味合いであっていますでしょうか? 丁)function Person(n) { this.name = n; } var p1 = new Person('Hanako'); var p2 = new Person('Taro') このケースではインスタンスでPersonオブジェクトをコピーしてそのコピーしたオブジェクトの用途に応じてプロパティを変えてあげる(p1->name="Hanako",p2->"Taro")ことが目的なのでしょうか? このように整理すると、関数の呼び出しは飽くまでfunctionの実体に引数を代入して返しているだけで、new演算子でオブジェクトを利用する場合、そのコピー(インスタンス)をまずつくりだしている。 そこで、それぞれつり出すインスタンス(上記のp1p2)によってプロパティが変化する必要がある(上記ではTaro Hanako)ので初期化が必要ということなのでしょうか?初期化をしなくてもインスタンスの時点でなにも値が入ってので、初期化する必要性があまりぴんときませんが、、そもそもオブジェクトのプロパティを自由に変えてしまったら汎用性が聞かなくなるのでインスタンスを使用するという理解です。 最後になりますが、この初期化のために、オリジナルのオブジェクトに必ずthis.name = n;のようにnをこのオブジェクトのnameプロパティに代入せよという記述が必要になるという理解でしょうか。 重ねて申し訳ございませんが宜しくお願い申しあげます。
sii_side

2016/12/08 03:53

> 参照コードではdocument.write(p1.name);はどのオブジェクトにも包含されていない コードの中ではそうかもしれませんが、documentが元々オブジェクトであり、そのプロパティであるwriteがFunctionオブジェクトなのですから、writeはメソッドです。 「オブジェクトに包含する」の意味がよくわかりませんが、恐らく(どんな意味であったとしても)それは必要条件ではありません。 > 甲) function meet (n){document.write(n+"hello!");}はなにも初期化する機能は備わっていないのでコンストラクタとは呼べない(なりえない)。 いいえ、違います。 インスタンスの生成それ自体も「初期化」の一部です。インスタンスが必ず独自のプロパティを持たなければならないわけではありません。 ですから、インスタンスは生成した、だがインスタンスのプロパティは特に設定しない、という初期化もあり得ます。 例えば```function hoge() { }```こんな中身が空のFunctionオブジェクトでも、コンストラクタになることはできます。 > 乙) var obj = {animal:"dog", cry:function(){document.write("ワン");}}におけるvar objは関数オブジェクトではない(functionがついていないので)ため、コンストラクタとは呼べない そのとおりです。objはFunctionオブジェクトではないので、コンストラクタにはなりません。 > ”Smithhello”を出力する際に、なにも初期化するべきプロパティがないため、newを使わずに関数を呼び出しているだけということなのでしょうか? インスタンスを生成する必要が無いからです。インスタンスが不要なのに、newする理由はありません。 > そもそもnewをしていないのでインスタンスを生成しているわけではなく、引数の"Smith"を関数meetに代入してその結果をmeet("Smith");返しているだけ ということです。 > このケースではインスタンスでPersonオブジェクトをコピーしてそのコピーしたオブジェクトの用途に応じてプロパティを変えてあげる(p1->name="Hanako",p2->"Taro")ことが目的 です。
sii_side

2016/12/08 04:09

> それぞれつり出すインスタンス(上記のp1p2)によってプロパティが変化する必要がある(上記ではTaro Hanako)ので初期化が必要 ということです。 > そもそもオブジェクトのプロパティを自由に変えてしまったら汎用性が聞かなくなるのでインスタンスを使用する それも理由の1つだとは思います。 そもそも、なぜクラス-インスタンスという仕組みがありそれを使うのか、その利点は何かということについては、いくらでも情報は転がっていますので、色々眺めてみてください。 それと、ここまでprototypeの話が出てきていないので、そこまで進むとまた違った感想が生まれるのではないかと思います。 > 初期化のために、オリジナルのオブジェクトに必ずthis.name = n;のようにnをこのオブジェクトのnameプロパティに代入せよという記述が必要 先述のようにインスタンスにプロパティが要らないならプロパティの定義それ自体が不要です。 また、プロパティの定義の仕方は1つではありませんので、書き方としての```this.propertyName = value;```も必須ではありません。 例えばプロパティの性質(for...inなどで列挙されるかどうか、編集可能か…など)を細く設定したい場合は、Object.definePropertyを使います。
SugiuraY

2016/12/08 09:46

ご回答を賜り、深謝を申し上げます。 おかげさまで視界不良であった世界が、かなりクリアになりました。 最後に一点だけ私の中で肝の部分を質問させてください。 >インスタンスの生成それ自体も「初期化」の一部です。インスタンスが必ず独自のプロパティを持たなければならないわけではありません。ですから、インスタンスは生成した、だがインスタンスのプロパティは特に設定しない、という初期化もあり得ます。 ともすればnew演算子によってインスタンスが生成される関数オブジェクトはすべてコンストラクタと呼べる(反対にインスタンスが生成されていない関数オブジェクトは何らも初期化されているものはないため、コンストラクタとは呼ばない、無論コンストラクタとなりうる関数オブジェクトとなりますが)と整理することは可能でしょうか? 重ねてで申し訳ございませんが、何卒、よろしくお願い申し上げます。
sii_side

2016/12/08 10:54

> new演算子によってインスタンスが生成される関数オブジェクトはすべてコンストラクタと呼べる(反対にインスタンスが生成されていない関数オブジェクトは何らも初期化されているものはないため、コンストラクタとは呼ばない、無論コンストラクタとなりうる関数オブジェクトとなりますが) はい、そのとおりです。
SugiuraY

2016/12/08 12:37

最後までお付き合い有難うございました。自分の頭では、いくら本やサイトを読んでも解決がしなかったので、sii_side様とteratailに深く感謝致します。本当にありがとうございました!
kay5

2019/11/21 08:53 編集

こちら認識としてはこれで合ってますでしょうか? ちなみに変数でnewを使わなかった場合、他に何が使うことは可能でしょうか?またその場合それはコンストラクタなのか、もしくは別の何かでしょうか? function Person(n) { this.name = n; } ↑ コンストラクタ var p1 = new Person('Hanako'); var p2 = new Person('Taro'); ↑ 変数 document.write(p1.name); document.write(p2.name); ↑ メソッド
sii_side

2019/11/21 11:30

> こちら認識としてはこれで合ってますでしょうか? 問題無いと思います。 ・Person関数はコンストラクタである ・p1とp2は変数である ・document.writeはメソッドである > ちなみに変数でnewを使わなかった場合、他に何が使うことは可能でしょうか? この意味がわかりませんでした。もう少し具体的に尋ねていただけると助かります。
kay5

2019/11/22 04:31

要はnewでなければならない理由がいまいちよく分からないということです。 コンストラクタを使う場合は変数はnewを使用するのが絶対なのでしょうか?
sii_side

2019/11/22 10:06

ざっくりですが、new演算子が具体的に行っている処理は、次の2つです。 ・新しいオブジェクトを作る ・そのオブジェクトのプロトタイプを設定する JavaScriptでは新しいオブジェクトの生成も、プロトタイプの設定も簡単に行うことができますので、new演算子を使わずに同様の処理を行うことも、仕様上は可能となっています。 (さらに詳細について知りたい場合は、Lhankor_Mhyさんの回答にあるリンクを参照ください) ですので、あらゆる例外無く100%絶対にということではありませんが、せっかく仕様として用意されていているし、短く書けるnewを使うのが普通、ということです。
kay5

2019/11/28 02:54

疑問が解けました。ありがとうございます。
guest

0

Object 型

JavaScript における「オブジェクト」は「Object 型」に分類されるものを指します。
「型」を識別するものとして「typeof 演算子」がありますが、JavaScript の typeof 演算子は特殊で分かりづらいので Object() を利用して判別する事をお勧めします。

JavaScript

1'use strict'; 2function isObject (arg) { 3 return Object(arg) === arg; 4} 5 6console.log(isObject(function () {})); // true (Object 型 -> 関数) 7console.log(isObject({}); // true 8console.log(isObject([]); // true 9console.log(isObject(document.body); // true 10console.log(isObject(1); // false 11console.log(isObject(null); // false 12console.log(isObject(undefined); // false 13console.log(isObject(true); // false 14console.log(isObject('a'); // false 15console.log(isObject(Symbol(1)); // false

コンストラクタ

new 演算子で呼び出し可能な関数」をコンストラクタと呼びます。
関数は Object 型なので、必然的にコンストラクタも Object 型です。

JavaScript

1function Person (n) { // Constructor 2 this.name = n; 3 return this; // opt. 4} 5 6console.log(Object(Person) === Person); // true (Object 型 -> 関数)

インスタンス

コンストラクタを new 演算子で呼び出した返り値をインスタンスと呼びます。
インスタンスは必ず、Object 型です。

JavaScript

1function Person (n) { // Constructor 2 this.name = n; 3 return this; // opt. 4} 5 6var p1 = new Person('Hanako'); 7console.log(Object(p1) === p1); // true (Object 型)

オブジェクトを使用するためにオブジェクトを複製したコピーをインスタンスと呼び、new演算子によりインスタンスを作ることができる。

インスタンスとはコンストラクタのコピーではありません。
オブジェクトのプロパティ参照時にはプロトタイプチェーンによってプロトタイプ上のプロパティが参照されます(プロパティをコピーしているわけではありません)。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain

JavaScript

1function Person (n) { // Constructor 2 this.name = n; 3 return this; // opt. 4} 5 6Person.prototype = { 7 honorific: 'さん', 8 getName: function getName () { 9 return this.name + this.honorific; 10 } 11}; 12 13var p1 = new Person('Hanako'); 14console.log(p1.getName 15 === Person,prototype.getName); // true

Re: SugiuraY さん

投稿2016/12/07 23:06

編集2016/12/08 09:35
think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/12/08 12:42

ご回答頂き、有難うございます。 「new 演算子で呼び出し可能な関数」をコンストラクタと呼びます。という定義は非常にわかりやすいですね。初めの印象では、インスタンスはコンストラクタを複製したものとばかり思っていました。プロトタイプについては、これからじっくり学ばせて頂きます。今後この投稿が私みたいなお馬鹿な駆け出しプログラマにとって、コンストラクタの理解の一助になるものになれば嬉しいです。
guest

0

他の回答者の補足をしますと、new演算子はつまるところコンストラクタのthisを新しく作成したオブジェクトに束縛し、そのprototype __proto__ constructorといったプロパティを整えるものです。なので、やろうと思えばnew演算子なしでもプロトタイプチェーンは実装できるはずです。

JavaScript の new 演算子の意味: Days on the Moon
や...やっと理解できた!JavaScriptのプロトタイプチェーン - maeharin log
newを封印して、JavaScriptでオブジェクト指向する(1): Architect Note

投稿2016/12/08 04:36

Lhankor_Mhy

総合スコア35815

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

SugiuraY

2016/12/08 10:06

ご回答ありがとうございます。console.logでインスタンスを見ると__proto__やconstructorと言った色々なプロトタイプが出てきました!ブレッドポイントであまりにも多くの要素が出てくるので、一個ずつ調べてみます。またsii_sideさまもプロトタイプについて触れられていましたので、次にこれを本腰て勉強してみようと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問