アップルップル社内勉強会の覚書 JavaScript入門編
2019年1月22日夕方、アップルップルで社内勉強会が開催されました。お題は「JavaScript入門&Vue.js入門」です。おそらく、「案件で Vue.js を取り入れていってほしい!」という目的で行われた勉強会だったと思います。高校生に10時間かけて教えている内容を凝縮&割愛しての3時間でした。今回の記事ではJavaScript入門編について残します。
JavaScript入門編
JavaScript入門編では、ES6以上の内容に絞っての解説で、あらかじめ作られた資料をみながら進みました。
テンプレートリテラル
バッククオート「`」で囲んだ範囲を文字列とするリテラル。バッククオートを使うことで文字列をより扱いやすくできる。
※ 「リテラル」とはプログラムのソースコードにおいて使用される、数値や文字列を直接に記述した定数のことである。変数の対義語であり変更されないことを前提とした値である。(引用元:weblio辞書)
テンプレートリテラルの活用方法①
改行を「n」なしでできる
// バックククオートあり const test = `改行できる 改行できる 改行できる`; // バックククオートなし const test2 = "改行できる\n改行できる\n改行できる"; console.log(test); console.log(test2); // ↓それぞれの表示結果↓ // 改行できる // 改行できる // 改行できる
テンプレートリテラルの活用方法②
変数を「+」で繋げなくても文字列の中に入れれる
// バックククオートあり const string = "繋げる"; const hoge = `文字列${string}文字列`; // バックククオートなしバージョン const hoge2 = "文字列" + string + "文字列"; console.log(hoge); // 文字列繋げる文字列 console.log(hoge2); // 文字列繋げる文字列
変数
ES6から変数に型を指定できるようになった。使える型は「var」「const」「let」で、基本的には const を使うことを推奨するが、処理に合わせて let も使う。varは使わない。ただし、let, const はIE10では使えないためビルドしないならvarを使う。
const, let の特徴
- スコープの中でしか使えないようになっている(簡単に説明すると { } の範囲が一つのスコープ)
- 同じスコープ内で、同じ名前&型の変数は再定義できない
letとconstの違いは、再代入できるかできないかの違い。再代入できるのが let 、再代入できないのが const。
※ varはletと同じく再代入が可能だが、再宣言も可能です。スコープ範囲はletやconstよりも緩い。スコープ以外にも挙動面で違いがあるようだが、constとletを使っておけば間違いない!(var との違いは気になったら調べる...)
アロー関数の特徴
アロー関数とは、「=>」を使って記述した関数のことを示します。
※ 基本的な処理については解説しません。
// アロー関数 let hogeNotArrow = (hogehoge) => { console.log(hogehoge); }; // 普通の関数 let hogeArrow = function(hogehoge) { console.log(hogehoge); }; hogeNotArrow("アロー関数!"); hogeArrow("アロー関数じゃない?!");
アロー関数の特徴①
省略して書くことができる。引数が1つの時は()を省略でき、処理が return 1行の場合は {} も省略できる。
// 省略なし const areaCircle = (radius) => { return radius * radius * 3.14; }; console.log(`円の面積は${areaCircle(5)}`); //円の面積は78.5 // 引数の()を省略 const areaCircle2 = radius => { return radius * radius * 3.14; }; console.log(`円の面積は${areaCircle2(5)}`); //円の面積は78.5 // 引数が一つなら () と関数全体の {} と return も省略できる const areaCircle3 = radius => radius * radius * 3.14; console.log(`円の面積は${areaCircle3(5)}`); //円の面積は78.5
アロー関数の特徴②
普通の関数であれば、JavaScriptのthisは独特な動きをするが、アロー関数の場合は他の言語と同じような動きをするため、thisを使用する際は関数の種類によって動きかたが変わることを意識すること。
注意点として、jQuery使うときはアロー関数を使わない! jQueryではthisをよく使用するが、アロー関数で書いてしまうと意味合いが変わってしまうので混乱しやすい。
詳しい使用方法はググりましょう。
配列・オブジェクト・JSON
ここは簡略的にメモを残します。
配列
配列は、変数名['aaa', 'bbb', 'ccc'] のように、[ ](ブラケット)を使用して値を入れていく。参照する時は添字をつけて呼び出す。添字は0から始まる。
const hoge = ['aaa', 'bbb', 'ccc']; console.log(hoge[0]); // 表示結果:aaa
配列は変数定義時、最後の要素の後に「, 」がついていても動作に影響はない(IE9以降であれば)。例えば、変数名['aaa', 'bbb', 'ccc',]と書いてもOK。
オブジェクト
オブジェクトはプロパティの集合で、キー(名前)と値から構成される。 キーには文字列が利用でき、値には任意のデータが利用できる。 オブジェクトを作成するには、オブジェクトリテラル({})を使用する。
const object = { "key": "value" }; console.log(object.key) // 表示結果:value
const object2 = { "7aaa": "例文です", }; console.log(object2['7aaa']) // 表示結果:例文です
オブジェクトは要素の最後に「, 」をつけてもOK
key の「" "」や「' '」(クウォート)は省略できるが、変数として不適切なものを指定した場合は "" で囲い定義する必要がある。例)7aaa //数値から始まるkey
オブジェクトは「. 」または「 [ ] 」でアクセスできる。
ただし、key に変数として不適切なものを指定した場合は [ ] で参照すること。
例)hoge[ '7aaa' ]
JSON
ほぼオブジェクトの形で使用できる。
オブジェクトとの違いは、
JSONの場合はkeyをダブルコートで必ず括る
JSONの場合は最後の要素にカンマつけてはダメ
ESモジュール
ESモジュールは、export文によって変数や関数などをエクスポートできます(ファイルの外でも使えるようにすること)。 また、import文を使って別のモジュールからエクスポートされたものをインポートできます(外部ファイルから読み込むこと)。
exportには「名前付きexport」と「デフォルトエクスポート」の2種類ある。エクスポートの仕方でインポート方法も変わってくる。
名前付きエクスポート
// export の方法 // hoge.jsファイル const hoge = 'hoo'; const hoge2 = () => { return 'hoo2'; } export {hoge,hoge2};
// importの方法 (exportしているファイルとは別ファイルです) import {hoge,hoge2} from 'path/to/hoge.js';
デフォルトエクスポート
デフォルトエクスポートは、名前付きと違い1ファイル1つしかエクスポートすることができない。
// export の方法 // hoge.jsファイル const hoge = 'hoo'; export default hoge;
1ファイル1つしかエクスポートできないが、インポート時に好きなモジュール名をつけることができる。
import 好きな名前 from 'path/to/hoge.js';
クラスの場合は色々なところで使われることを想定しているため、デフォルトエクスポートを使う場合が多い。デフォルトエクスポートであれば自分で好きな名前を付けれるため、わざわざエクスポートしているファイルの中身まで見に行かなくていい。
ESモジュールの実行
作成したESモジュールを実行するためには、起点となるJavaScriptファイルをESモジュールとしてWebブラウザに読み込ませる必要がある。 scriptタグにtype="module"属性を付与すると、Webブラウザは JavaScriptファイルをESモジュールとして読み込む。
<script type="module" src="./myModule.js"></script>
非同期処理① コールバック
JSは非同期IO(インプットアウトプット)の言語で知られている。よく見かける「setTimeout」も非同期処理の一種。そしてJavaScriptには非同期処理の歴史がある。まずは、昔よく使われていた手法としてコールバックというものがある。
「コールバック」は、簡単に言うと関数の引数に別の関数を指定する処理を指します。 これにより、Aという関数が実行されたあとに引数で指定していたBという関数を実行するということが可能になります。 よく使われるケースとして、例えばサーバーからデータを取得したあとに次の処理を実行したいという場合です。
引用元:侍エンジニア塾
コールバック例)
const fn = (num, callback) => { // callbackは関数 setTimeout(() => { callback(num * num); }, 1000); // 1秒後に処理 }; fn(2, (result1) => { // 関数fnが実行されて、result1は4になる fn(result1, (result2) => { // 関数fnが実行されて、result2は16になる fn(result2, (result3) => { // 関数fnが実行されて、result3は256になる console.log(result3); // 表示結果:256 }); }); });
コールバック例:アローファンクションではないバージョン)
勉強会の時に出てきた例題の理解にとても時間がかかったので、アローファンクションなしバージョンも載せておきます...。
const fn = (num, callback) => { // callbackは関数 setTimeout(() => { callback(num * num); }, 1000); // 1秒後に処理 }; fn(2, function(result1) { // 関数fnが実行されて、result1は4になる fn(result1, function(result2) { // 関数fnが実行されて、result2は16になる fn(result2, function(result3) { // 関数fnが実行されて、result3は256になる console.log(result3); // 表示結果:256 }); }); });
JavaScriptの歴史の中で始めに使われていたのが「コールバック」。しかし、非同期処理した結果をもらってさらに非同期処理をする場合どんどん入れ子になっていくというデメリットがある(コールバック地獄)。
ちなみに、jQueryの「$.get('url', function(data){});」にはコールバックが使われている。
非同期処理② プロミス
Promesはコールバックのネストが深くなるという問題を解消するために編み出された手法だそうです。↓のように、処理をthenなどでつなげていくことができます。thenで呼ばれた関数の引数には、呼び出し元でresolveの引数に入っている値が戻り値として入ってきます。
const fn = (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num * num); }, 1000); }); }; fn(2).then((result1) => { return fn(result1); }).then((result2) => { return fn(result2); }).then((result3) => { console.log(result3); }); // resolveが実行されるまでthenは待つ、そしてさらにthenで繋げれる // 表示結果:256
Promesを理解するには、JavaScriptの基本的な概念から押されておく必要があると感じたので調べたことを書いていきます。
まず、Promes自身は「new Promise()の形でインスタンスを作るコンストラクタ」というものみたいです(参考元:僕なりのPromise入門 | Qiita)。
コンストラクタとは
コンストラクタとは、newされたら実行される関数のこと(参考元:JavaScriptのnew(インスタンス生成)は何をしているのか?について調べてみた | Qiita)。らしいのですが「関数」ではなくて「クラスオブジェクト」と呼ぶ人もいれば(参考元:鷹沢三二ホームページ ChaichanPapa-World !)、「コンストラクタ関数」と呼んでいる人もいました(参考元:JavaScript (ES5) でクラスを実現するための基本 | Qiita)。正体がわからなかったので、わかったら別記事で書くかもしれません。
とりあえずは、「コンストラクタとは new したら実行されるもの」と覚えておきます。
インスタンスとは
次に、インスタンスとは、「new演算子でメモリ上に記憶場所を確保して作られたオブジェクト」のことです(引用元:鷹沢三二ホームページ ChaichanPapa-World !)。↓下記ソースコードだと test2 がインスタンスです。
function test(num){ // コンストラクタ this.num = num * num ; return this; } const test2 = new test(5); // test2がインスタンス console.log(test2.num); // 表示結果 25
会社の先輩の話では、「車の工場で例えると、コンストラクタが工場で、インスタンスが市場に出た車。同じ形の車を工場(コンストラクタ)で生産(newしてインスタンス化)して、それらの車(インスタンス)は別々に出荷される(処理は別々に動く)。」のように例えてくれました。
Promes について
そして、Promesについては 僕なりのPromise入門 | Qiita を読めばだいたい理解できました。もしわからない方がいましたら読んでおくといいです。
非同期処理③ async/await
async/await は 「非同期処理② プロミス」をさらに見やすくしたような書き方ですね。returnも書く必要がなく、then などで処理をつなげていく必要もないため、一つ一つの関数を1行で書くことができるようになりました。
const fn2 = (num) => { return new Promise((resolve) => { setTimeout(() => { resolve(num * num); }, 1000); }); }; const test2 = async () => { const aa = await fn2(2); //2を関数fnに渡し算出結果resolveの引数をaaに格納 const bb = await fn2(aa); //aaを関数fnに渡し算出結果resolveの引数をbbに格納 const cc = await fn2(bb); //bbを関数fnに渡し算出結果resolveの引数をccに格納 console.log(cc); //ccを表示 } test2();
async awaitは、IEでは動かないのでビルドできる環境の中でやること。