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

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

ただいまの
回答率

90.60%

  • JavaScript

    15939questions

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

Javascriptのオブジェクトの概念について

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 519

dada_moreo

score 3

Javascriptを勉強し始めた者です。
オブジェクトと変数の関係の概念がいまいち理解できなかったので、以下のコードをもとに質問させてください。

var person = function(){
 this.name = "no name";
}

var me = new person();

■質問1
1行目で宣言した変数personの型はオブジェクトですか?

■質問2
1行目で宣言したpersonがオブジェクトだとすると、下部で new person(); とオブジェクトを生成する意味は何でしょうか?
オブジェクトではない場合、person の型は何でしょうか?

よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+6

 Object 型

コンストラクタ(new 演算子で呼べる関数)の関数名は先頭を大文字にする慣習がある為、名前を変えます。

var Person = function(){
 this.name = "no name";
}

var me = new Person();

変数 Personme はどちらも「Object 型」です。
一部には new Function を「Function型」、new Person を「Person型」と呼ぶ場合もありますが、それらと「JavaScriptとしての型」は別物なので、厳密な意味では間違った表現(便宜上の説明)です。

性質 Person me 
Object型 Object型
[[Call]]を持っているか 持っている(関数である) 持っていない(関数ではない)
インスタンス生成元 Function Person
[[Prototype]] (__proto__) Function.prototype Person.prototype

インスタンス生成元としての「型」を「Person型」と呼ぶ場合があるわけですが、プロトタイプチェーンを辿れば、多くの型を持っている扱いとなります。

var Person = function(){
 this.name = "no name";
}

var me = new Person();

console.log(Person instanceof Function);  // true (Function型)
console.log(Person instanceof Object);    // true (Object型)
console.log(me instanceof Person);        // true (Person型)
console.log(me instanceof Object);        // true (Object型)

この表現方法は厳密な意味では「JavaScriptの型」とは違いますし、多くの型を併せ持つ性質は理解されづらいなので、個人的には混乱を招く可能性の高い表現だと思っています。
結論としては、両方ともObject型です。

 プロトタイプ

JavaScriptはプロトタイプベースの言語です。
Person.prototype はオブジェクトの雛形(プロトタイプ)であり、new Person という命令によって、Person.prototype を雛形(プロトタイプ)とするオブジェクトを生成します。
そうすることによって、Person の性質を持つオブジェクトを複数生成できます。

 プロトタイプチェーン

JavaScriptではプロパティ参照の際には必ず、プロトタイプチェーンを辿る事でプロパティを検索します。
(new 演算子とセットで説明されることが多いですが、これは new 演算子を使った場合限定の規則ではありません)

'use strict';
function Person (name) {
  this.name = arguments.length ? name : 'no name';
}

Person.prototype.output = function output () {
  console.log(this.name);
};

var taro = new Person('taro');

taro.output(); // "taro" (new Person は Person.prototype に存在するプロパティを使用できる)

console.log(taro.output === Person.prototype.output);          // true (taroのプロパティを参照する時、暗黙の内に Person.prototype に存在するプロパティを検索する)
console.log(Object.getPrototypeOf(taro) === Person.prototype); // true (new Person の [[Prototype]] は Person.prototype である)
console.log(taro.__proto__ === Person.prototype);              // true (同上)

注目してほしいのは、taro.output === Person.prototype.output が true となる部分です。
taro.output が参照された場合、taro は直属のプロパティとして output を持っていない為、prototypeである Person.prototype から output プロパティを探し、見つかった為、それを参照しているわけです。

ここでもし、Person.prototype.output が存在しなかったのなら、更に上の prototype を探し、prototype が存在しなくなるまでこの過程を繰り返します。
この仕組みをプロトタイプチェーンといいます。

Re: dada_moreo さん

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/05 11:30

    横からすみません。


    瑣末な話ですが、回答中の表が気になりました。
    ご存知のとおり、Person.__proto__ は Function ではなくて、Function.prototype ですから、「インスタンス生成元([[Prototype]] or __proto__)」という記述は、プロトタイプチェーンでインスタンスがコンストラクタのプロパティを直接参照しているような誤解を先々に生みそうな気がします。
    カッコ内はいらないのでは。

    キャンセル

  • 2017/09/05 12:07

    ありがとうございます。
    Person , me どちらもオブジェクト型ということが分かりました。

    また新たな疑問が湧いてしまったのですが、1行目の
    var Person = function()
    は、
    var Person = new function(){
    と、new を暗黙的に省略しているのでしょうか?

    キャンセル

  • 2017/09/05 16:58

    To: Lhankor_Mhy さん
    ご指摘の件、ごもっともだと思いますので、修正しました。ありがとうございます。

    To: dada_moreo さん
    > new を暗黙的に省略しているのでしょうか?
    いいえ。省略しているのではありません。

    > var Person = function()
    このコードは変数 Person に関数オブジェクトを代入するだけで実行はしません。
    下記2つのコードはほぼ等価です。
    var Person = function() {};
    function Person () {}

    キャンセル

  • 2017/09/05 17:19

    > 関数オブジェクトを代入するだけで実行はしません。
    このお答えで理解しました。
    new を付けて初めて実行され、Personオブジェクトができるということですね。

    キャンセル

  • 2017/09/05 17:23

    > think49さん
    ご変更ありがとうございました。

    キャンセル

  • 2017/09/05 18:33

    たびたび横からすみません。


    > dada_moreoさん
    > new を付けて初めて実行され、Personオブジェクトができるということですね。
    new演算子でできるのは、meオブジェクトです。Personオブジェクト自体は代入した時点で存在します。new演算子はPersonオブジェクトをコンストラクタとして実行する働きをしています。その具体的なふるまいはmiyabi-sunさんのご回答のとおりです。

    キャンセル

  • 2017/09/05 19:24

    To: dada_moreo さん
    new Person で生成されるのは「Person.prototype を雛形とするオブジェクト」ですね。
    クラスベース的に表現するなら、Person のインスタンスを返します。
    親記事に「プロトタイプチェーン」の節を追記しました。

    To: Lhankor_Mhy さん
    何度もフォローいただき、ありがとうございます。
    個人的には横入り歓迎なので、気になる事があったら積極的に指摘頂けると嬉しいです。

    キャンセル

  • 2017/09/05 21:47

    皆さん有り難うございます。
    いままで、varで宣言した変数はただの変数(数字や文字などの値を入れる箱)としてしか認識していなかったのですが、変数にはオブジェクトも代入でき、その変数はオブジェクトの機能を持つ。という理解でよろしいでしょうか。
    質問ばっかりして申し訳ないです。

    キャンセル

  • 2017/09/05 22:18

    「変数はオブジェクトの機能を持つ」は語弊がありますが、「変数にはオブジェクトも代入でき」はその通りです。
    質問が基本的な部分まで波及しているようなので、一度、入門書/入門サイト等をご覧になってから分からない部分を質問してみてはいかがでしょうか。
    https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide
    質問が後から継ぎ足し的に増えていくと、このスレッドを後から参照する方も困ってしまうと思います。

    キャンセル

  • 2017/09/06 20:47

    大変失礼いたしました。もう少し基本的な学習から進めようと思います。
    おかげさまで少し理解が深まりました。ありがとうございました。

    キャンセル

+4

1行目で宣言した変数personの型はオブジェクトですか?

いいえ、これは関数です※
ただし、newを使ってインスタンスを作ることを想定した関数です。

newが何やってんねんってのいうのがわかれば自ずと理解出来ます。

newを使って関数を叩くと、まず空のオブジェクトを作ります。
関数内部でthis.hoge = 123;という風にthisに向かってプロパティを詰めていくと、
newで作られた空のオブジェクトのプロパティに値が詰め込まれていきます。

そして、ここが重要!
newを使って関数が実行されると、最初に作ったオブジェクトだったものが戻り値として帰ってきます。
関数内のreturnじゃないよ!
要するに変数menew person()と指定するから、必ずオブジェクトが代入されるってわけ。

なので、thisのプロパティに値を突っ込む事が目的の変な関数が出てきたら、
それは他の言語で言うクラスに相当する雛形的な関数と解釈してください。
ちょっとだけ変な書き方になりますが、クラスベースのオブジェクト指向言語と同じ事は可能です。
(ES2015ではClass構文がサポートされ、他の言語のようなクラス宣言が出来るようになりました)

var person = function() {
  this.name = "hogehoge";
}

var me = new person();

console.log(me);
// person {name: "hogehoge"}

newを使って作られたオブジェクトはただのオブジェクトではなく、
関数であるpersonのインスタンスとして動作するオブジェクトになります。

console.logで中身を表示するとちゃんとpersonのインスタンスって表示されることが確認出来ます。
ついでに定義しておいたpersonのメソッド(プロトタイプのプロパティ)にアクセスできます。

var person = function() {
  this.name = "hogehoge";
}
// これがメソッド定義
person.prototype.hello = function() {
  return "hello. my name is " + this.name;
}

var me = new person();

console.log(me);
// person {name: "hogehoge"}

console.log(me.hello());
// "hello. my name is hogehoge"

1行目で宣言したpersonがオブジェクトだとすると、下部で new person(); とオブジェクトを生成する意味は何でしょうか?
オブジェクトではない場合、person の型は何でしょうか?

JavaScriptはプロトタイプベースのオブジェクト指向言語という話を聞いたことありませんか?
(その気になれば)全ての関数をnewして新しいインスタンスを生成することが可能です。

現実的にはthisに値を突っ込むコンストラクタメソッド的な関数しかプロトタイプの元には成りえないので、
雛形に相当する関数を予め作っておく(プロトタイプ)、それを元に新しいインスタンスを生成する(new)
正にコピーを作りながら量産するという考え方になります。

継承の代わりになるのがプロトタイプのコピー及び改良。
ちょっとしたコードを買いて見せたかったけど、ちゃんとした書き方は大変なので参考サイト張っておきます。

参考サイト:継承とプロトタイプチェーン - MDN


※Rubyは完全なオブジェクト指向言語なので数値や文字列も全てオブジェクトですが、
JavaScriptも不完全ながら似たようなアプローチで、Number, String, Boolean等のプリミティブなもの以外はオブジェクトから派生して作られたものです。
JavaScriptの関数はFunctionというオブジェクトを使って生成されたものです。

「変数personの型はオブジェクトですか?」という問いに関しては、
その通りと回答するのが正解なのですが、
今回の質問に限ってはそういう分類に対する質問とは異なると考え、否定しています。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/05 12:57

    Javascriptの世界では、継承という概念はないのでしょうか?
    meオブジェクトは、Personオブジェクトのnameインスタンスを「me.name」という書き方で使うことができますが、それは継承とは呼ばないのでしょうか?
    meにとってPersonは、どういう関係と呼ぶのが適切なのでしょうか?

    もともとの質問と方向が変わってしまい申し訳ありません。

    キャンセル

  • 2017/09/05 16:57

    そもそもの「継承」がクラスベースのオブジェクト指向言語の話なんで、
    JavaScriptでは継承なんてしなくても、その雛形関数をコピーして別の雛形関数を生成すりゃいいじゃんという設計です。
    もちろんコードに起こすとめっちゃ汚くなりがちです(回答欄のMDNの記事参照)

    > meオブジェクトは、Personオブジェクトのnameインスタンスを「me.name」という書き方で使うことができますが、それは継承とは呼ばないのでしょうか?
    クラスベースの言語では親クラス→子クラスに継承しますよね。
    つまり、継承とはクラスからクラスによって行われるもので、クラスとインスタンスでは継承は行われません。
    JavaScriptではPersonはクラスに該当する関数、meはPerson関数を元に生成されたインスタンス、どこにも継承はありません。
    「me.name」を書き換えた場合、meインスタンスのnameプロパティを変更したという扱いであり、継承という呼び方はしません。

    ES2015という新しいバージョンを取り込んだJavaScriptではクラスの書き方が追加されていますので、
    多くのオブジェクト指向言語と同じように「Class xxx extends yyy」という書き方が使えます。

    キャンセル

  • 2017/09/05 17:21

    ちょっと難しくなってきました。。
    オブジェクトとインスタンスの関係をもう少し理解しようと思います。

    キャンセル

+3

person はオブジェクトであり、その型は「関数オブジェクト」です。
me はオブジェクトであり、型は無名ですが、person で示される型です。
変数 (や定数) には、オブジェクトとプリミティブがあります。プリミティブはそれ以上の構造を持たない数 (12 とか 1.5 とか) や文字列 ("test" とか) などがあります。それ以外はオブジェクトと考えてさしつかえないと思います。

new person() でオブジェクトを生成するメリットは、person 型の prototype にメソッド (たとえば、walk()) を追加すると、そのメソッドの実体が一つでも、生成したオブジェクト、たとえば me から me.walk() のように me 自体のメソッドのように呼べること、などです。


コメントを受けて追記

  • person は function という型のインスタンスです。
  • me は person という型のインスタンスです。

もうちょっと詳しく書くと、

  • person は function という型のインスタンスです。関数オブジェクトとも言います。関数オブジェクトは型となれます。
  • me は person という変数に格納された関数オブジェクトを型としたときのインスタンスです。

という感じです。

例を示しながら。

var person = function() {
   this.name = "no name";
}

var me = new person();
var he = new person();
var it = new person();

person.prototype.setName = function(name) {
  this.name = name;
  return this;
};

person.prototype.isHuman = true;

person.prototype.greet = function() {
  console.log("my name is " + this.name + " (" + (this.isHuman ? "human" : "?")\
 + ").");
};

me.bark = function() {
  console.log(this.name + "!!!");
};

it.isHuman = false;

me.setName("Taro").greet(); //-> my name is Taro (human).                       
he.setName("Jiro").greet(); //-> my name is Jiro (human).                       
it.greet();                 //-> my name is no name (?).                        
me.bark();                  //-> Taro!!!                                        
he.bark();                  //-> エラー発生 (he.bark is not a function)         

person 型のオブジェクト meheit を生成しました。me にはオブジェクト固有のメソッド bark() が定義してあります。it には固有のプロパティ isHuman が定義してあります。これらは、オブジェクトごとに記憶領域を持っているわけです。

一方で、setName() メソッドや greet() メソッド、そして isHuman プロパティについては、person という型のほうに定義してあります。これらは person 型の記憶領域に保存されているので、person 型のインスタンスをいくら生成しても、これらの分の記憶領域は消費されません。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/09/05 07:57

    回答ありがとうございます。少し分かってきました。
    つまり、新たに作るmeオブジェクトで、personオブジェクトのインスタンスを使いたい場合は、new と書くのが決まりという理解でよろしいでしょうか。
    すでにpersonを宣言してるのにnewと書くのが違和感がありますが、そう言うものならそのまま覚えます。

    キャンセル

  • 2017/09/05 08:54

    追記しました。person と me は別物です。型が違います。

    キャンセル

  • 2017/09/05 10:13

    > person は function という型のインスタンスです。
    typoだと思いますが、「"Function" という型のインスタンス」が正解でしょうか。

    To: dada_moreo さん
    誤解が生まれそうなので補足しますが、
    - person は「Object型」です。
    - person は「Function型」です。
    両者は全く別の概念の「型」を表しています。
    maisumakunさんが説明されているのが前者で「JavaScript(ECMAScript)言語仕様としての型」です。
    後者は「インスタンス生成元(プロトタイプ)」の性質としての型を表しています。これは便宜上の表現であって、しばしば前者の概念と混同を招きます。ECMAScript 言語仕様にも存在しない表現ですね。
    詳しくは、別で回答しました。

    キャンセル

  • 2017/09/05 10:16

    はい、ご指摘ありがとうございます。think49 さんのおかげで、より正しい認識が広がってくれそうで嬉しいです。

    キャンセル

  • 2017/09/05 12:52

    すいません。お二人が何を話しているのかが理解できませんでした。

    キャンセル

  • 2017/09/05 17:00

    To: dada_moreo さん
    型の話は、私の回答で触れましたので、そちらを参考にしてみて下さい。

    キャンセル

+3

質問1 1行目で宣言した変数personの型はオブジェクトですか?

functionオブジェクト」です。JavaScriptでは、関数もオブジェクトなのです。

質問2

personという関数を使って、新たなオブジェクトを作る操作、です。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

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

  • JavaScript

    15939questions

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