こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

回答受付中の質問

JSのクラスについての質問

JSのクラスについての質問

ソース
class Cat {
constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

//インスタンス作成
var clsObj = new Cat("my cat");
//インスタンス(オブジェクト)の中身を出力
console.log(clsObj);

初心者なのでこの中のどの記述が必須で、
またnameはどれと対になっているかがわかりません。

インスタンスはnew クラス名 となっている所で作成されて変数に作られたインスタンスが代入されるというのは何となく分かったのですが、

console.log(clsObj);
VM793:9
Cat {name: "my cat"}

となるのがいまいちわかりません。

new Cat("my cat");は

class Cat {
constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

を実行するという事で、
引数は

constructor(name)
new Cat("my cat");

が対になっているのでnameがmycatに代わるという事でしょうか?

new Cat("my cat");が実行された結果がインスタンスという事ですが、
mycatがインスタンスなのですか?

大変恐縮ですが、簡単に一連の流れを教えていただければ幸いです。

class Cat {
constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

にどう渡されてどのように処理され何がインスタンスとして吐き出されるのでしょうか?

投稿日時 - 2017-04-21 14:04:53

QNo.9320085

困ってます

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.7

>同じnameなのに違うとはどう区別したのですか?

constructor(name) {this.name = name}

↑この行で2つ記述されている「name」が「constructor」の仮引数で、「this.name」がクラス内部のローカル変数(その実態は内部的に「name」なのですが、コンストラクターの「name」仮引数とは別物です)
つまり(class内の定義の場合)「this.」が付いてるか付いてないかで区別できます。
class内の定義でない場合、「Cat」クラス内部の「name」ローカル変数にアクセスする場合は(インスタンスが「clsObj」の場合)「clsObj.name」ど言うシンタックスでアクセスできます。

>this.name以外のname引数はconstractorの引数という事ですね。

そうです。

>区別できるように「this.name」となってますというのがいまいちよくわからないのですが、
>thisはクラスcatのことですよね。

そうです。

>するとCat.nameとなりCatクラスという箱の中に入っているnameプロパティ?いや引数という事なのでしょうか?

引数ではなくプロパティです、ここではクラス内部のローカル変数と説明しているモノです(初心者に分かりやすいか どうかは別としてプロパティと言った方が正確ですね)。
関数内部(関数が持っている)のローカル変数は ご存知ですか?、それに類似しています、この場合はクラス内部(クラスが持っている)のローカル変数と言うイメージです。

>ふつう違うなら別名にしますよね?

そうですね。

>なぜこの例えはこんなわかりにくいことをしたんですかね?

恐らく同じ名前でも「this.」が付いてるか付いてないかで区別できるので、同じ名前でもコンフリクト(衝突、競合)せずに使えると言う例を示したかったのかもしれません。

>変数と似ている箱で

変数と違う箱と考えて下さい。

>特殊な箱でなんでも好きに入れ替えできず、
>入れられるものと入っていなくても良いものが固定されている箱という事でしょうか?
>つまり変数と違ってコンストラクタが絶対に入っている箱なのですね。

初期設定が必要ないなら、コンストラクタは必要ないようです。

>メソッドなども必須なのですか?

メソッドも必要ないなら、メソッドを記述する必要はありません。

>入れられないものもあるのですか?

クラス内クラスは無理なようです。

>>>クラス内の関数定義はfunctionは省略できる、省略しなければいけないのですね。
>>>恐らくこれはクラス内の関数だよと区別するためですかね?

>>この場合、分かりきっているのでワザワザ書く必要もないと言う事で、省力化しているのだと思われます。

>書いてはいけないのではなく省略可能なので省略しているのですね。
>ただ一般的な関数も省略可能でしたっけ?

省略可能と言う意味ではありません、分かりきっているのでワザワザ書く必要もないので「書いてはいけない」と言う仕様にして省力化している、と言う事です。

>var コンストラクターの「name」= my cat;という事ですかね?

その説明は変な感じです、実際のプロセスを考えて下さい(「my cat」ではなく"my cat"文字列です)。

new Cat("my cat") ←ここでコンストラクターの「name」仮引数に"my cat"文字列が代入され、「constructor(name) {this.name = name}」が呼ばれます。

>new Cat("my cat")の部分がインスタンスの作成ですが
>関数で例えるならこちらは定義した関数の呼び出しに当たるのですかね。

コンストラクターが無い場合も有り得るので「関数の呼び出しに当たる」とも言えませんし、コンストラクターが在る場合もコンストラクターは初期設定だけです。
クラス"設計図"からインスタンス"実態"を作成すると言う事で、例えるなら十徳ナイフの"設計図"から十徳ナイフの"実態"を作成すると言うイメージして下さい。
(十徳ナイフの"実態"を作成しても)十徳ナイフが置いてあるだけでは何も役に立ちません、十徳ナイフは使ってこそ役に立つ訳です、例えば十徳ナイフの「栓抜き」(機能)を使うと言うのが「栓抜き」メソッド、「缶切」(機能)を使うと言うのが「缶切」メソッドに対応すると言うイメージです。

>インスタンスの引数が実引数なら関数も呼び出しが実引数ですよね。
>ローカル変数に代入される値がインスタンスの引数になり、関数と同じですね。

「インスタンスの引数」と言うのは違います。
new Cat("my cat"):Catクラスに実引数"my cat"文字列を設定しnewすると、コンストラクターの「name」仮引数に"my cat"文字列が代入され、「constructor(name) {this.name = name}」が呼ばれ、インスタンスが生成されます。

>そして定義の引数が仮引数つまりローカル変数の変数名に当たるという事も関数と同じですね。

仮引数とローカル変数(プロパティー)とは違います。
ローカル変数(プロパティー)はクラスの箱の中に定義されるモノです(添付画像参照)。

投稿日時 - 2017-04-23 21:27:51

ANo.6

>classも変数と同じ箱で中に関数や変数を入れられるのですね。
>其れってオブジェクトと同じ箱という事ですか?

変数とは違います、変数のように自由に値を代入できる訳ではありません。
classとは"設計図"の"定義"であり、そして構造をもってます(添付画像参照)。
今回は
コンストラクター1個。
変数1個:「this.name」(その実態は内部的に「name」なのですが、コンストラクターの「name」パラメータとは別物です)。
メソッド1個:「meow()」メソッド。
となります。

>>class Cat { ←「Cat」クラス定義。

>Catという名前のクラスを定義する

そうです。

>オブジェクトの定義と同じですね。

オブジェクトと言う言葉は実は曖昧で、通常インスタンス(実態)を表します(オブジェクト指向と言った場合は また別ですが)。
そう言う意味で言うとインスタンス(実態)ではありません。

>クラス内の関数定義はfunctionは省略できる、省略しなければいけないのですね。
>恐らくこれはクラス内の関数だよと区別するためですかね?

この場合、分かりきっているのでワザワザ書く必要もないと言う事で、省力化しているのだと思われます。

>関数の定義で例えるならfunction Cat(){}と全く同じですね。

まあ確かに("定義"と言う)見た目は似ていますが…。

>コンストラクタとは設計図のクラスをインスタンス化するための関数をコンストラクタと特別に言っているだけの関数そのものなので、
>functionがconstracutorになっただけで他は関数と全く同じなのですね

そうですね。

>>「this.name = name」はコンストラクターの「name」パラメータをクラス内部のローカル変数「this.name」(その実態は内部的に「name」なのですが、
>>コンストラクターの「name」パラメータとは別物です)に
>>meow() {alert( this.name + 'はミャオと鳴きました' )} ←「meow()」メソッド定義。
>}

>ここがよくわかりませんでした。
>this.name = nameとは変数の定義の事なのでしょうか?

分かりにくいですが
「name」が仮引数。
「this.name」が「Cat」クラス内部のローカル変数(その実態は内部的に「name」なのですが、コンストラクターの「name」パラメータとは別物です、区別できるように「this.name」となってます)。

>コンストラクターの「name」パラメータは仮引数と思うのですが実引数はどこにあるのでしょうか?

実引数はインスタンス作成時にセットされてます、下記「"my cat"」文字列が実引数で、コンストラクターの「name」仮引数に代入されます。

//インスタンス作成
var clsObj = new Cat("my cat"); // 「new Cat(~)」で(コンストラクターが呼ばれ)インスタンスが作成される、そのインスタンスを「clsObj」変数に代入。

投稿日時 - 2017-04-22 22:36:09

お礼

>>>
変数とは違います、変数のように自由に値を代入できる訳ではありません。
classとは"設計図"の"定義"であり、そして構造をもってます(添付画像参照)。
今回は
コンストラクター1個。
変数1個:「this.name」(その実態は内部的に「name」なのですが、コンストラクターの「name」パラメータとは別物です)。
メソッド1個:「meow()」メソッド。
となります。


nameは同じnameなのに、別物なのですね。非常にややこしい例えを採用してしまったのですかね?
同じnameなのに違うとはどう区別したのですか?
なぜこの例えはこんなわかりにくいことをしたんですかね?
ふつう違うなら別名にしますよね?

変数と似ている箱ですが、
特殊な箱でなんでも好きに入れ替えできず、
入れられるものと入っていなくても良いものが固定されている箱という事でしょうか?
つまり変数と違ってコンストラクタが絶対に入っている箱なのですね。
メソッドなども必須なのですか?
入れられないものもあるのですか?



>>>
>オブジェクトの定義と同じですね。
オブジェクトと言う言葉は実は曖昧で、通常インスタンス(実態)を表します(オブジェクト指向と言った場合は また別ですが)。
そう言う意味で言うとインスタンス(実態)ではありません。


プリミティブ以外はすべてオブジェクトと聞いているのですが、インスタンスはオブジェクトではないのですか?



>>>
>クラス内の関数定義はfunctionは省略できる、省略しなければいけないのですね。
>恐らくこれはクラス内の関数だよと区別するためですかね?

この場合、分かりきっているのでワザワザ書く必要もないと言う事で、省力化しているのだと思われます。


書いてはいけないのではなく省略可能なので省略しているのですね。
ただ一般的な関数も省略可能でしたっけ?



>>>
>ここがよくわかりませんでした。
>this.name = nameとは変数の定義の事なのでしょうか?
分かりにくいですが
「name」が仮引数。
「this.name」が「Cat」クラス内部のローカル変数(その実態は内部的に「name」なのですが、コンストラクターの「name」パラメータとは別物です、
区別できるように「this.name」となってます)。


区別できるように「this.name」となってますというのがいまいちよくわからないのですが、
thisはクラスcatのことですよね。
するとCat.nameとなりCatクラスという箱の中に入っているnameプロパティ?いや引数という事なのでしょうか?

this.name以外のname引数はconstractorの引数という事ですね。




>>>
>コンストラクターの「name」パラメータは仮引数と思うのですが実引数はどこにあるのでしょうか?
実引数はインスタンス作成時にセットされてます、下記「"my cat"」文字列が実引数で、コンストラクターの「name」仮引数に代入されます。
//インスタンス作成
var clsObj = new Cat("my cat"); // 「new Cat(~)」で(コンストラクターが呼ばれ)インスタンスが作成される、そのインスタンスを「clsObj」変数に代入。


つまり
var コンストラクターの「name」= my cat;という事ですかね?
上記の質問で考えると間違っているかもしれませんが、

すると実質
class Cat {

var name = my cat;

constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}
となるという事でよいでしょうか?

本当に関数そっくりですね。


new Cat("my cat")の部分がインスタンスの作成ですが
関数で例えるならこちらは定義した関数の呼び出しに当たるのですかね。

インスタンスの引数が実引数なら関数も呼び出しが実引数ですよね。
ローカル変数に代入される値がインスタンスの引数になり、関数と同じですね。

そして定義の引数が仮引数つまりローカル変数の変数名に当たるという事も関数と同じですね。

投稿日時 - 2017-04-23 15:32:37

ANo.5

>class Cat { ←「Cat」クラス定義。
>関数の定義で例えるならfunction Cat()のようなものですね。

違います、class と言う箱の中に、関数(コンストラクター、(0個以上の複数の)メソッド)、(0個以上の複数の)変数を詰め込むと言うイメージです(カプセル化と言われたりします)。

>Catという名前のクラスを定義するよという事ですね。

class 内に関数(コンストラクター、(0個以上の複数の)メソッド)、(0個以上の複数の)変数を定義できます。

>meow()は関数の呼び出しという事ですが、定義が見つかりません。
>どこで定義しているのでしょうか?
>それともfunctionの省略した定義がここなのでしょうか?
>ソースには見つかりませんでしたが、どこかにあるのですかね?

どうも class 内の関数の定義には「function」は記述する必要はない用です。
もう1度 下記のコメントを良く見て下さい。
『「Cat」クラス定義』内に『コンストラクター定義(new 時に実行される)』、『「meow()」メソッド定義』とコメントで明記しています。

class Cat { // 「Cat」クラス定義。
constructor(name) {this.name = name} // コンストラクター定義(new 時に実行される)。
meow() {alert( this.name + 'はミャオと鳴きました' )} // 「meow()」メソッド定義。
}

投稿日時 - 2017-04-22 13:36:43

お礼

>>>>
>class Cat { ←「Cat」クラス定義。
>関数の定義で例えるならfunction Cat()のようなものですね。
違います、class と言う箱の中に、関数(コンストラクター、(0個以上の複数の)メソッド)、(0個以上の複数の)変数を詰め込むと言うイメージです(カプセル化と言われたりします)


classも変数と同じ箱で中に関数や変数を入れられるのですね。
其れってオブジェクトと同じ箱という事ですか?



>>>
Catという名前のクラスを定義する


オブジェクトの定義と同じですね。



>>>
どうも class 内の関数の定義には「function」は記述する必要はない用です。
もう1度 下記のコメントを良く見て下さい。
『「Cat」クラス定義』内に『コンストラクター定義(new 時に実行される)』、『「meow()」メソッド定義』とコメントで明記しています。


クラス内の関数定義はfunctionは省略できる、省略しなければいけないのですね。
恐らくこれはクラス内の関数だよと区別するためですかね?



下記二つはどうでしょうか?このnameの対が一番わかりませんのでお願いします。

>>>
「this.name = name」はコンストラクターの「name」パラメータをクラス内部のローカル変数「this.name」(その実態は内部的に「name」なのですが、
コンストラクターの「name」パラメータとは別物です)に
meow() {alert( this.name + 'はミャオと鳴きました' )} ←「meow()」メソッド定義。
}

ここがよくわかりませんでした。
this.name = nameとは変数の定義の事なのでしょうか?

コンストラクターの「name」パラメータは仮引数と思うのですが実引数はどこにあるのでしょうか?




>>>
「new Cat("my cat")」は「constructor(name) {this.name = name}」コンストラクターだけが実行されます。
「clsObj.meow();」とすれば「meow()」メソッドが実行されると思われます。

new Cat("my cat")が実行されたときにクラス内の
constructor(name) {this.name = name}の部分だけが実行されるという事ですか?

つまりnew クラス名(引数)とは初めに定義したクラスを実行しろ、呼び出ししろという意味で。
その際にconstructor(name) {this.name = name}
のみが実行されるのですかね?

よって関数と同じで、new Cat("my cat")のmycatが実引数で、constructor(name)のnameが仮引数となるのですか?


>>>
constructor(name) {this.name = name} ←コンストラクター定義(new 時に実行される)

関数の定義で例えるならfunction Cat(){}と全く同じですね。
コンストラクタとは設計図のクラスをインスタンス化するための関数をコンストラクタと特別に言っているだけの関数そのものなので、
functionがconstracutorになっただけで他は関数と全く同じなのですね。



>>>
「this.name = name」はコンストラクターの「name」パラメータをクラス内部のローカル変数「this.name」(その実態は内部的に「name」なのですが、
コンストラクターの「name」パラメータとは別物です)に
meow() {alert( this.name + 'はミャオと鳴きました' )} ←「meow()」メソッド定義。
}

ここがよくわかりませんでした。
this.name = nameとは変数の定義の事なのでしょうか?

コンストラクターの「name」パラメータは仮引数と思うのですが実引数はどこにあるのでしょうか?

投稿日時 - 2017-04-22 15:33:11

ANo.4

回答No.3 amanojaku1

>この中のどの記述が必須

とりあえず下記が基本です、「meow()」メソッドの実行はプログラマーが呼びたい時に呼べば良いので、本当の意味での必須と言う訳ではありません(つまり必要がなければ「meow()」メソッドは呼ばなくても良い)。


class Cat { // 「Cat」クラス定義。
constructor(name) {this.name = name} // コンストラクター定義(new 時に実行される)
meow() {alert( this.name + 'はミャオと鳴きました' )} // 「meow()」メソッド定義。
}


//インスタンス作成
var clsObj = new Cat("my cat"); // 「new Cat(~)」で(コンストラクターが呼ばれ)インスタンスが作成される、そのインスタンスを「clsObj」変数に代入。


clsObj.meow(); // 「meow()」メソッドを実行

投稿日時 - 2017-04-21 20:18:18

お礼

class Cat {
constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

//インスタンス作成
var clsObj = new Cat("my cat");
//インスタンス(オブジェクト)の中身を出力
console.log(clsObj);


class Cat { ←「Cat」クラス定義。
関数の定義で例えるならfunction Cat()のようなものですね。
Catという名前のクラスを定義するよという事ですね。




meow()は関数の呼び出しという事ですが、定義が見つかりません。
どこで定義しているのでしょうか?
それともfunctionの省略した定義がここなのでしょうか?

ソースには見つかりませんでしたが、どこかにあるのですかね?

投稿日時 - 2017-04-22 08:56:06

ANo.3

以前のJSのオブジェクト指向プログレミングは非常に分かりにくい、と言うか理解しようと言う気持ちが沸いてこないモノでしたが、今回のような新しい?オブジェクト指向の記述はJavaに類似していて分かりやすいです(あくまで当方の個人的な主観ですが)。

class Cat { ←「Cat」クラス定義。
constructor(name) {this.name = name} ←コンストラクター定義(new 時に実行される)、「this.name = name」はコンストラクターの「name」パラメータをクラス内部のローカル変数「this.name」(その実態は内部的に「name」なのですが、コンストラクターの「name」パラメータとは別物です)に
meow() {alert( this.name + 'はミャオと鳴きました' )} ←「meow()」メソッド定義。
}

//インスタンス作成
var clsObj = new Cat("my cat"); ←「new Cat("my cat")」でインスタンスを作成し、そのインスタンスをclsObj変数に代入。

//インスタンス(オブジェクト)の中身を出力
console.log(clsObj); ←インスタンス(オブジェクト)の中身をConsole(コンソール)に出力。


console.log(clsObj);
VM793:9 ←これは良く分かりませんが その数字はスクリプトIDらしいです。
Cat {name: "my cat"} ←インスタンス(オブジェクト)の中身です、この「name」とはコンストラクター中にあった「this.name」であり、コンストラクターの「name」パラメータではありません。


>new Cat("my cat");は
>class Cat {
>constructor(name) {this.name = name}
>meow() {alert( this.name + 'はミャオと鳴きました' )}
>}
>を実行するという事で、

違います
「new Cat("my cat")」は「constructor(name) {this.name = name}」コンストラクターだけが実行されます。
「clsObj.meow();」とすれば「meow()」メソッドが実行されると思われます。

>引数は
>constructor(name)
>new Cat("my cat");
>が対になっているのでnameがmycatに代わるという事でしょうか?

この「name」はコンストラクターのパラメータです、コンストラクターのパラメータ「name」変数に"my cat"文字列が代入されます。

投稿日時 - 2017-04-21 20:04:20

お礼

class Cat {
constructor(name) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

//インスタンス作成
var clsObj = new Cat("my cat");
//インスタンス(オブジェクト)の中身を出力
console.log(clsObj);


class Cat { ←「Cat」クラス定義。
関数の定義で例えるならfunction Cat()のようなものですね。
Catという名前のクラスを定義するよという事ですね。


>>>
constructor(name) {this.name = name} ←コンストラクター定義(new 時に実行される)

関数の定義で例えるならfunction Cat(){}と全く同じですね。
コンストラクタとは設計図のクラスをインスタンス化するための関数をコンストラクタと特別に言っているだけの関数そのものなので、
functionがconstracutorになっただけで他は関数と全く同じなのですね。



>>>
「this.name = name」はコンストラクターの「name」パラメータをクラス内部のローカル変数「this.name」(その実態は内部的に「name」なのですが、
コンストラクターの「name」パラメータとは別物です)に
meow() {alert( this.name + 'はミャオと鳴きました' )} ←「meow()」メソッド定義。
}

ここがよくわかりませんでした。
this.name = nameとは変数の定義の事なのでしょうか?

コンストラクターの「name」パラメータは仮引数と思うのですが実引数はどこにあるのでしょうか?



>>>
meow() {alert( this.name + 'はミャオと鳴きました' )}


これはただの一般的なmeowという名前の関数を定義しただけという事ですね。
functionがないのは省略可能なのですか?


>>>
/インスタンス作成
var clsObj = new Cat("my cat"); ←「new Cat("my cat")」でインスタンスを作成し、そのインスタンスをclsObj変数に代入。

catクラスに文字列を渡してインスタンス化をするといったいどうなるのでしょうか?
全く想像がつきません?
my catはnameと対になっているのですか?
var cat = mycat
と同じことになるのですか?

newで出来上がったインスタンスをclsobj変数に代入しているんですよね?
するとconsoleは出来上がったインスタンスを表記しているのではないのですか?




class Cat {
constructor(仮引数) {this.name = name}
meow() {alert( this.name + 'はミャオと鳴きました' )}
}

//インスタンス作成
var clsObj = new Cat(実引数)

という事ですか?;



>>>
「new Cat("my cat")」は「constructor(name) {this.name = name}」コンストラクターだけが実行されます。
「clsObj.meow();」とすれば「meow()」メソッドが実行されると思われます。

new Cat("my cat")が実行されたときにクラス内の
constructor(name) {this.name = name}の部分だけが実行されるという事ですか?

つまりnew クラス名(引数)とは初めに定義したクラスを実行しろ、呼び出ししろという意味で。
その際にconstructor(name) {this.name = name}
のみが実行されるのですかね?

よって関数と同じで、new Cat("my cat")のmycatが実引数で、constructor(name)のnameが仮引数となるのですか?

投稿日時 - 2017-04-22 08:05:26

ANo.2

間違えました
Cat = 『constructor』
『constructor』.prototype = {constructor:function constructor(name) {this.name = name},meow:function meow() {alert( this.name + 'はミャオと鳴きました' )}}
です。

投稿日時 - 2017-04-21 17:53:21

ANo.1

『Cat {name: "my cat"}』
はそれがCatクラスのインスタンスであり、nameプロパティに"my cat"を持つオブジェクトということを表しています。
クラス名を呼ぶとconstructorが呼ばれることになり、nameがmycatに代わるというのはあっています。
そしてmycatがインスタンスです。
「インスタンス」と言うのは「実体」という意味です。
つまり、「抽象」的に見れる型を用いて作られた「実体」のオブジェクトなのです。

一連の流れをざっくり簡略化して書くと、

まずClass構文でCatという名前でクラスが定義されるとき、
構文内のconstructor関数がCatになります。
つまり、Cat == constructorです
このとき、constructorのprototypeプロパティに、構文内の関数達、constructorやmeowメソッドが入ります。
つまり
Cat = 『constructor』 = {constructor:function constructor(name) {this.name = name},meow:function meow() {alert( this.name + 'はミャオと鳴きました' )}}
です。

次にCatクラスがnew演算子で呼ばれると、new演算子の効果で、
Cat.prototypeを「「プロトタイプ」」としたオブジェクトが生成され、Catにthisとして渡され呼ばれます。
そしてCatを実行し終わったあと、処理された、ここではnameプロパティを追加されたオブジェクトを
new演算子は結果として返すのです。

投稿日時 - 2017-04-21 17:51:44