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

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

ただいまの
回答率

87.94%

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

解決済

回答 3

投稿

  • 評価
  • クリップ 7
  • VIEW 4,530

score 250

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

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

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

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

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

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

コンストラクタはオブジェクトを作成し、初期化する関数オブジェクトである。
参考サイト:http://javascript.keicode.com/lang/constructors.php

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

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

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

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

var p1 = new Person('Hanako');
document.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.オブジェクトでも関数のオブジェクトと通常のオブジェクトが何が違うのかがわからないということになりますでしょうか。

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+9

前提:関数・メソッドはオブジェクトの一種である

オブジェクトにはいくつか種類があります。配列(Array)や日付・時間(Date)を使ったことがあるかもしれませんが、これらもオブジェクトです。

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

前提:Functionオブジェクト

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

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

前提:「関数」と「メソッド」

ここでは、以下のように区別します。

  • 関数
//名前を付けて宣言したFunctionオブジェクト
function hoge() { ... }

//変数に入れたFunctionオブジェクト
//(名前は有っても無くても可)
var a = function() { ... };
var b = function fuga() { ... };
  • メソッド
//obj.func()のようにドットで繋いで呼び出せるFunctionオブジェクト
var obj = new Object;
obj.func = function() { ... };

//以下のようにしても可(書き方が違うだけで同じ)
var obj = {
  func: function() { ... }
};

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


回答A

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

そのとおりです。

回答B

何を初期化しており

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

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

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

function Person(n) {
  this.name = n;
}

var p1 = new Person('Hanako');
var p2 = new Person('Taro');

document.write(p1.name);  //Hanakoが表示される
document.write(p2.name);  //Taroが表示される

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

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

回答C

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

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

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

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

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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/11/22 19:06

    ざっくりですが、new演算子が具体的に行っている処理は、次の2つです。
    ・新しいオブジェクトを作る
    ・そのオブジェクトのプロトタイプを設定する

    JavaScriptでは新しいオブジェクトの生成も、プロトタイプの設定も簡単に行うことができますので、new演算子を使わずに同様の処理を行うことも、仕様上は可能となっています。
    (さらに詳細について知りたい場合は、Lhankor_Mhyさんの回答にあるリンクを参照ください)

    ですので、あらゆる例外無く100%絶対にということではありませんが、せっかく仕様として用意されていているし、短く書けるnewを使うのが普通、ということです。

    キャンセル

  • 2019/11/22 19:32

    参考までに、newの代替としては、後発のメソッドであるObject.createを使うことも可能です。

    十一章第七回 継承2 — JavaScript初級者から中級者になろう — uhyohyo.net
    https://uhyohyo.net/javascript/11_7.html

    .create() | JavaScript 日本語リファレンス | js STUDIO
    http://js.studio-kingdom.com/javascript/object/create

    キャンセル

  • 2019/11/28 11:54

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

    キャンセル

+6

 Object 型

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

'use strict';
function isObject (arg) {
  return Object(arg) === arg;
}

console.log(isObject(function () {})); // true (Object 型 -> 関数)
console.log(isObject({});              // true
console.log(isObject([]);              // true
console.log(isObject(document.body);   // true
console.log(isObject(1);               // false
console.log(isObject(null);            // false
console.log(isObject(undefined);       // false
console.log(isObject(true);            // false
console.log(isObject('a');             // false
console.log(isObject(Symbol(1));       // false

 コンストラクタ

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

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

console.log(Object(Person) === Person); // true (Object 型 -> 関数)

 インスタンス

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

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

var p1 = new Person('Hanako');
console.log(Object(p1) === p1); // true (Object 型)

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

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

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

Person.prototype = {
  honorific: 'さん',
  getName: function getName () {
    return this.name + this.honorific;
  }
};

var p1 = new Person('Hanako');
console.log(p1.getName
 === Person,prototype.getName); // true

Re: SugiuraY さん

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/08 21:42

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

    キャンセル

+2

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/12/08 19:06

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

    キャンセル

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

  • ただいまの回答率 87.94%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る