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

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

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

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

Q&A

解決済

4回答

1829閲覧

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

sassoon

総合スコア13

JavaScript

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

0グッド

3クリップ

投稿2017/09/04 22:07

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

javascript

1var person = function(){ 2 this.name = "no name"; 3} 4 5var me = new person(); 6

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

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

よろしくお願いします。

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

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

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

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

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

guest

回答4

0

ベストアンサー

Object 型

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

JavaScript

1var Person = function(){ 2 this.name = "no name"; 3} 4 5var me = new Person();

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

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

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

JavaScript

1var Person = function(){ 2 this.name = "no name"; 3} 4 5var me = new Person(); 6 7console.log(Person instanceof Function); // true (Function型) 8console.log(Person instanceof Object); // true (Object型) 9console.log(me instanceof Person); // true (Person型) 10console.log(me instanceof Object); // true (Object型)

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

プロトタイプ

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

プロトタイプチェーン

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

JavaScript

1'use strict'; 2function Person (name) { 3 this.name = arguments.length ? name : 'no name'; 4} 5 6Person.prototype.output = function output () { 7 console.log(this.name); 8}; 9 10var taro = new Person('taro'); 11 12taro.output(); // "taro" (new Person は Person.prototype に存在するプロパティを使用できる) 13 14console.log(taro.output === Person.prototype.output); // true (taroのプロパティを参照する時、暗黙の内に Person.prototype に存在するプロパティを検索する) 15console.log(Object.getPrototypeOf(taro) === Person.prototype); // true (new Person の [[Prototype]] は Person.prototype である) 16console.log(taro.__proto__ === Person.prototype); // true (同上)

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

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

Re: dada_moreo さん

投稿2017/09/05 01:03

編集2017/09/05 10:20
think49

総合スコア18162

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

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

Lhankor_Mhy

2017/09/05 02:30

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

2017/09/05 03:07

ありがとうございます。 Person , me どちらもオブジェクト型ということが分かりました。 また新たな疑問が湧いてしまったのですが、1行目の var Person = function() は、 var Person = new function(){ と、new を暗黙的に省略しているのでしょうか?
think49

2017/09/05 07:58

To: Lhankor_Mhy さん ご指摘の件、ごもっともだと思いますので、修正しました。ありがとうございます。 To: dada_moreo さん > new を暗黙的に省略しているのでしょうか? いいえ。省略しているのではありません。 > var Person = function() このコードは変数 Person に関数オブジェクトを代入するだけで実行はしません。 下記2つのコードはほぼ等価です。 var Person = function() {}; function Person () {}
sassoon

2017/09/05 08:19

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

2017/09/05 08:23

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

2017/09/05 09:33

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

2017/09/05 10:24

To: dada_moreo さん new Person で生成されるのは「Person.prototype を雛形とするオブジェクト」ですね。 クラスベース的に表現するなら、Person のインスタンスを返します。 親記事に「プロトタイプチェーン」の節を追記しました。 To: Lhankor_Mhy さん 何度もフォローいただき、ありがとうございます。 個人的には横入り歓迎なので、気になる事があったら積極的に指摘頂けると嬉しいです。
sassoon

2017/09/05 12:47

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

2017/09/05 13:18

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

2017/09/06 11:47

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

0

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

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

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

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

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

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

Bash

1var person = function() { 2 this.name = "hogehoge"; 3} 4 5var me = new person(); 6 7console.log(me); 8// person {name: "hogehoge"}

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

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

JavaScript

1var person = function() { 2 this.name = "hogehoge"; 3} 4// これがメソッド定義 5person.prototype.hello = function() { 6 return "hello. my name is " + this.name; 7} 8 9var me = new person(); 10 11console.log(me); 12// person {name: "hogehoge"} 13 14console.log(me.hello()); 15// "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 01:21

編集2017/09/05 01:57
miyabi-sun

総合スコア21158

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

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

sassoon

2017/09/05 03:57

Javascriptの世界では、継承という概念はないのでしょうか? meオブジェクトは、Personオブジェクトのnameインスタンスを「me.name」という書き方で使うことができますが、それは継承とは呼ばないのでしょうか? meにとってPersonは、どういう関係と呼ぶのが適切なのでしょうか? もともとの質問と方向が変わってしまい申し訳ありません。
miyabi-sun

2017/09/05 07:57

そもそもの「継承」がクラスベースのオブジェクト指向言語の話なんで、 JavaScriptでは継承なんてしなくても、その雛形関数をコピーして別の雛形関数を生成すりゃいいじゃんという設計です。 もちろんコードに起こすとめっちゃ汚くなりがちです(回答欄のMDNの記事参照) > meオブジェクトは、Personオブジェクトのnameインスタンスを「me.name」という書き方で使うことができますが、それは継承とは呼ばないのでしょうか? クラスベースの言語では親クラス→子クラスに継承しますよね。 つまり、継承とはクラスからクラスによって行われるもので、クラスとインスタンスでは継承は行われません。 JavaScriptではPersonはクラスに該当する関数、meはPerson関数を元に生成されたインスタンス、どこにも継承はありません。 「me.name」を書き換えた場合、meインスタンスのnameプロパティを変更したという扱いであり、継承という呼び方はしません。 ES2015という新しいバージョンを取り込んだJavaScriptではクラスの書き方が追加されていますので、 多くのオブジェクト指向言語と同じように「Class xxx extends yyy」という書き方が使えます。
sassoon

2017/09/05 08:21

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

0

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

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

質問2

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

投稿2017/09/04 22:26

maisumakun

総合スコア145183

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

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

0

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

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


コメントを受けて追記

  • personfunction という型のインスタンスです。
  • meperson という型のインスタンスです。

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

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

という感じです。

例を示しながら。

js

1var person = function() { 2 this.name = "no name"; 3} 4 5var me = new person(); 6var he = new person(); 7var it = new person(); 8 9person.prototype.setName = function(name) { 10 this.name = name; 11 return this; 12}; 13 14person.prototype.isHuman = true; 15 16person.prototype.greet = function() { 17 console.log("my name is " + this.name + " (" + (this.isHuman ? "human" : "?")\ 18 + ")."); 19}; 20 21me.bark = function() { 22 console.log(this.name + "!!!"); 23}; 24 25it.isHuman = false; 26 27me.setName("Taro").greet(); //-> my name is Taro (human). 28he.setName("Jiro").greet(); //-> my name is Jiro (human). 29it.greet(); //-> my name is no name (?). 30me.bark(); //-> Taro!!! 31he.bark(); //-> エラー発生 (he.bark is not a function)

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

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

投稿2017/09/04 22:25

編集2017/09/04 23:53
unau

総合スコア2468

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

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

sassoon

2017/09/04 22:57

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

2017/09/04 23:54

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

2017/09/05 01:13

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

2017/09/05 01:16

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

2017/09/05 03:52

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

2017/09/05 08:00

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問