#JavaScript 始めの一歩
HTMLとCSSしか経験していない者にとって、JavaScriptのハードルは低くありませんでした。
一年前の自分にとってJavaScriptの最初の一歩の理解はすごく難しかったです。
JavaScriptを理解しなくてもjQueryを使えば簡単に動的な変化はつけられるし、
付けたい動きをググってqiitaなんかにあるコードをコピペして解決!!(したふり)はできるのですが、それではその先がありません。
そうは思えど入門書を読み進めれば読み進めるほどわからなくなったりして。
「他言語経験者からすればサクサクなんだろうなー(イライラ)」
そんな一年前の自分のような人のためによく聞く例えを更にわかりやすく例えたいという思いで記事を書くことにしました。
##初学者が躓くところ(個人的回想)
自分の場合、webや入門書で学習。変数の理解くらいまではスムーズでした。
if文であれfor文であれ、ふむふむなるほど!!という感じで進みます。
オブジェクトもひとまずわかった気にはなれるので、そのまま進みます。
ところが徐々に話が変わります。
関数、new演算子、this、コンストラクタ、インスタンス、プロトタイプ
待って待って、分かんなくなってきました。
わかった気になったはずのオブジェクトもわかってない気がしてました(いや、分かっていない)。
「よし、もう一回はじめから復習しよう。」
##対象読者
・javascript書けないし、読めもしないよって人
・他言語の学習/経験も経ていない人
・真の理解にすぐには到達できなくてもとりあえず分かった気にはなれないと進めない人
##実践
###変数
基本的に変数、オブジェクト、配列、は全てデータの”入れ物”。
入れ物をイメージする。
箱です。ただし箱の中はドラえもんのポケットみたいにいろんなものが入れられます。
なので箱の大きさのイメージを持たないことがポイントです。
早速箱を用意しましょう。
var hoge;
hogeという名前のついた箱が用意できました。
箱に何か入れましょう。
var hoge;
hoge = '飛行機';
console.log(hoge);
//飛行機
はい。箱の中に飛行機(文字列)が格納できました。
これが変数です。
箱の中にいろんなものを入れてそれをいじったりできます。
ここまでは誰しもが馬鹿にすんな!!ですね。すみません。
###オブジェクト
次はオブジェクトです。
「Javascriptでは何もかもがオブジェクトオブジェクトをプロトタイプとして持つオブジェクトです。」
っていう言葉遊びみたいな事実は一旦知らんがな!!しておいて説明します。
そういうことはもう少し先で理解しましょう。
オブジェクトはタンスをイメージしましょう。
さきほど変数の説明のとき箱(変数)はドラえもんのポケットみたいと書きましたが、
このタンスも不思議なタンスで引き出しの数は2つかもしれないし1000個あるかもしれません。(例えの限界)
しかしながら、説明するときに引き出しが何個あるのかとか何もデータがなければイメージできないので、
今回は引き出し5つのタンス(オブジェクト)で進めます。
引き出しそれぞれに適当な名前をつけて用意します。
var hoge = {
hoge : '',
piyo : '',
fuga : '',
hogera : '',
hogehoge : '',
};
console.log(hoge);
//{hoge: "", piyo: "", fuga: "", hogera: "", hogehoge: ""}
console.log(hoge.hoge);
//
console.log(hoge.hoge2);
//undefined
引き出しに名前のついたタンスが用意できました。
引き出しには名前がついているけどタンスには名前がついていません。
わかりやすく進めたいのでこのタンスを先ほど作った箱に入れてます。
hogeという名前の箱の中にタンスを格納した状態です。
タンスの引き出しにはそれぞれ名前がついています(hoge被り許してください)。
ここでの理解は
- オブジェクトは{}で表す
- オブジェクトの引き出しの名前(キー)と引き出しの中身(値)はセミコロンでつなぐ
- この引き出しの名前(キー)と中身(値)のセットをプロパティと呼ぶ
というところでしょうか。
コンソールの結果はhogeという名前のついた箱の中身は、
hoge,piyo,fuga,hogera,hogehogeという名前の引き出しがあるタンス(オブジェクト)ですよ。
ということです。
引き出しの中身はどうでしょう。
hogeの引き出しを表示すると空っぽです。
この場合引き出しの中身がちゃんと''で空っぽであることが示してあるので、
何も表示されません。
試しにhoge2という用意してない引き出しを表示すると"undefined"。
つまり定義されてないよ!と言われます。
引き出しに色々しまってみましょう。
var hoge = {
hoge : '下着',
piyo : '靴下',
fuga : '上着',
hogera : 'Tシャツ',
hogehoge : 'ズボン',
};
console.log(hoge);
//{hoge: "下着", piyo: "靴下", fuga: "上着", hogera: "Tシャツ", hogehoge: "ズボン"}
console.log(hoge.hoge);
//下着
服を綺麗にしまえました。
引き出しの中身はどうでしょう。
現状、hogeという箱(変数)は=タンス(オブジェクト)で、
タンスのhogeという引き出しには下着がしまわれている。ということです。
オブジェクトについてはもう少し説明しますが、
先に配列の説明をしましょう。
###配列
配列です。
配列のイメージもタンスでいいです。
ただし配列のタンスには引き出しに既に名前がついてます。
番号です。
この画像ではわかりにくいですが一番最初の段から0段目、1段目〜とイメージします。
それではこの新しい配列のタンスにモノをしまいます。
先ほどのタンスとは違うタンスなのでhoge2という名前を変数に格納します。
var hoge2 = ['マフラー','パーカー','帽子','手袋','モモヒキ'];
console.log(hoge2);
//(5) ["マフラー", "パーカー", "帽子", "手袋", "モモヒキ"]
console.log(hoge2[0]);
//マフラー
console.log(hoge2.length);
//5
冬用の衣類を綺麗にしまえました。
一見オブジェクトでいう引き出し名(キー)がないので不安になりますが、
番号という引き出し名があるので順番にしっかりしまえています。
引き代の中身はどうでしょう。
0という名前の引き出しにはマフラーがしまわれていることがわかります。
コンソールの表示先頭の(5)というのは引き出しの数のことです。(lengthと言います。)
なのでhoge2.lengthは引き出しの数で5と表示されます。
いやいやlengthなんて引き出しどこにあるんだよって感覚がある人はその勢いです。
オブジェクトもいきなり引き出しを増やすことは可能ですが(後述)このlengthは特殊です。
配列というタンスにはデフォルトでlengthという引き出しがあって、
その引き出しの中には引き出しの数が常にしまわれていて、増減するたび更新されます。
不思議ですね(例えの限界2)。
むしろlengthであったり引き出しに0から番号が振られてあったりする特殊なオブジェクトが配列なんだ。
という理解ができる人はその方が良いと思います。
こういう不思議が最終的に、
「Javascriptでは何もかもがオブジェクトオブジェクトをプロトタイプとして持つオブジェクトです。」
とか
「Javascriptはプロトタイプベースのオブジェクト指向言語です。」
とか
入門書の最初に書かれているけど訳分かんないフレーズの理解に繋がります。
ここでの理解は
- 配列は[]で表す
- 配列は引き出し名が番号で、しまったものから順に0から始まる引き出しに格納される
- 配列にはlengthという引き出しが最初からある
という感じで良いでしょう。
###オブジェクト、配列 + α
さあ一通り押さえたところで色々やってみましょう。
タンス(オブジェクト)の引き出しの中にタンス(配列)をぶち込みます。
var hoge = {
hoge : '下着',
piyo : '靴下',
fuga : '上着',
hogera : 'Tシャツ',
hogehoge : 'ズボン',
};
var hoge2 = ['マフラー','パーカー','帽子','手袋','モモヒキ'];
hoge.piyo2 = hoge2;
console.log(hoge);
//{hoge: "下着", piyo: "靴下", fuga: "上着", hogera: "Tシャツ", hogehoge: "ズボン", …}
console.log(hoge.piyo2[2]);
//帽子
先ほどまで説明していた、タンスたち(オブジェクトと配列)をそのまま利用しました。
いかがでしょうか。
まず配列をオブジェクトの今まで登場してこなかった"piyo2"という引き出しに格納してます。
このようにそれまでなかった引き出しも突然使用することができます。
突然出てきた引き出しですがしっかりと引き出しの名前(キー)と中身(値)があります。
hogeという箱には現在タンス(オブジェクト)が格納されていて、
そのタンスのpiyo2という名前の引き出しには、
タンス(配列)が格納されているということです。
"hoge.piyo2[2]"というのは
"hogeに格納されているタンスのpiyo2って引き出しに格納されているタンスの2という名前(順番)の引き出しに格納されているモノ!!"
ということになり、結果帽子となります。
このように一度変数に格納された状態のタンスはどんどん引き出しにしまうことができます。
その結果、タンスの引き出しの構造が深くなりすぎることは書く側にとっても読む側にとっても、
順を追うのが難しくなるので喜ばしいことではない、ということはイメージしやすいかもしれません。
さて、ここまでは引き出しに衣類を文字列としてしまってきましたが、
文字列でないものも入れてみましょう。
var hoge = {
hoge : '下着',
piyo : '靴下',
fuga : '上着',
hogera : 'Tシャツ',
hogehoge : 'ズボン',
};
var order01 = function(yabukumono){
return '破れた' + yabukumono;
};
// function order01(yabukumono){
// return '破れた' + yabukumono;
// };
var fuga2 = order01('紙');
console.log(fuga2);
//破れた紙
hoge.fuga = order01(hoge.fuga);
console.log(hoge);
//{hoge: "下着", piyo: "靴下", fuga: "破れた上着", hogera: "Tシャツ", hogehoge: "ズボン"}
関数です。
ですが、いきなり関数を入れてみる前に、まず関数の働きを超絶簡単に復習しましょう。
関数はあらかじめ決められた処理なんて言われたりしますが、
ここでは命令という意味のorderにしてます。
関数は名前がつけることもできますが(↑コメントアウト部分参照)、
ここまで変数に入れてきたのでorder01という変数に入れておきます。
この関数は、
"破くもの"を引数に渡すと"破れたもの"返してくれるという、
ものすごく単純で嫌な処理をしてくれます。
試しに"紙"を渡して適当に作った箱に格納すると、"破れた紙"を返してくれていることがわかります。
次に引き出しの中のものも破きましょう。
fugaの引き出しに入っているものをorder01に引数として渡して、再びfugaの引き出しにしまってます。
するとタンスの中の上着は破れてしまってます。悲しい。
悲しいけど関数を引き出しに入れる準備は整いました。
var hoge = {
hoge : '下着',
piyo : '靴下',
fuga : '上着',
hogera : 'Tシャツ',
hogera2 : function(nurerumono) {
return '濡れた' + nurerumono;
},
hogehoge : 'ズボン',
};
var hoge2 = ['マフラー', 'パーカー', '帽子', '手袋','モモヒキ'];
hoge.piyo2 = hoge2;
console.log(hoge);
//{hoge: "下着", piyo: "靴下", fuga: "上着", hogera: "Tシャツ", hogehoge: "ズボン", …}
//fuga: "上着"
//hoge: "下着"
//hogehoge: "ズボン"
//hogera: "Tシャツ"
//hogera2: ƒ (nurerumono)
//piyo: "靴下"
//piyo2: (5) ["マフラー", "パーカー", "帽子", "手袋", "モモヒキ"]
console.log(hoge.hogera2(hoge.piyo2[2]));
//濡れた帽子
console.log(hoge.piyo2[2]);
//帽子
最後に今日の総決算です。
大分読み辛くなってきました。
関数をhogera2という引き出しにしまいました。
hogeという箱の中にはタンス(オブジェクト)が格納され、
その引き出しの中には衣類(文字列)やらさらに衣類が入ったタンス(配列)やら関数やらがしまわれてる状態です。
コンソールでhogeを表示してみるとその全容がしっかりわかります。
しまった関数の処理内容は先ほどとほぼ同じで、引数を濡れた状態で返す最低なやつです。
console.log(hoge.hogera2(hoge.piyo2[2]));
はどういうことかというと、
hogeという箱に格納されているタンス(オブジェクト)のhogera2という引き出しにしまってある関数の引数として、
hogeという箱に格納されているタンス(オブジェクト)のpiyo2という引き出しにしまってあるタンス(配列)の
"2"という番号の引き出しにしまっているものを渡しますよ。
ということです。
今、
hogeという箱に格納されているタンス(オブジェクト)のpiyo2という引き出しにしまってあるタンス(配列)の
"2"という番号の引き出しにしまっているものは、
"帽子"
ですので当然"濡れた帽子"が返されるわけです。悲しい。
でも関数から返された"濡れた帽子"は、
再びhoge.piyo2[2]にしまわれた訳ではないので、
console.log(hoge.piyo2[2]);
で引き出しの中をのぞくとそこには何も処理の加わっていない帽子がしまわれています。
よかった(完)
###総括
もっとわかりやすく例えれられる気がしたてたけど、
やはりたとえの限界がいくつもあって無理が出ました。
この世の誰か1人でもいいので、理解の手助けになれば幸いです。
もっと例えの実力が上がったら、
new演算子、this、コンストラクタ、インスタンス、プロトタイプとかも
例えていきたいと思います。
今年も残りわずかですがみなさん体調には気をつけて、良いお年を過ごしてください。