はじめに
6月は素のJS学習月間ということで学んだことをまとめます。
※後半で知っておくと便利だなと思ったことも残しておきます。
基本
✅宣言と式
参考:文と式、関数宣言と関数式の違いとは?[JavaScript]、関数宣言 vs 関数式 | ES2015+
関数宣言はそれより手前でも呼び出せるが、関数式では文法エラーになる
関数宣言:宣言を含むスコープが実行されるまでにFunctionオブジェクトが生成。
function func(){}
関数式:式が実行されるときにFunctionオブジェクトが生成。
let a = function(){}
🙄文は式になれて、式は文になれない。
✅関数型プログラミング
オブジェクト指向はモノ単位で考える。
スーパークラスを作って継承でサブクラスを作っていく拡張を考えた設計。
関数型はデータに何らかの処理を加えていく連続。
メリット⇒副作用が少ないプログラミングができる。
参考:JavaScript関数型プログラミング入門、JavaScriptで関数型プログラミングの入門
関数型プログラミングとは、関数だけでコードを組み立てるスタイルのこと。
特徴
・すべての関数が値を返す。
・外部の変数を決して参照しない(const参照可)=副作用がない
・関数の目的は、引数から値を計算することのみ
✅クラス
クラスはモノ(オブジェクト)そのもの。オブジェクトの設計書。
JS固有の特徴
・クラス変数はコンストラクタの中でのみ記載できる
・クラス直下にはfunction(メソッド、関数)のみしか配置できない
定義方法
式
const fooclass = class { // ...クラスの内容をここで定義する }
✅テンプレートリテラル
参考:JavaScript の テンプレートリテラル を極める!
バッククォート
で囲めばOK
・メリット
改行をそのまま書ける
テンプレートリテラル&innerHTML&エスケープ処理でHTMLを生成して描画する。
✅スコープに関して
関数内で変数を定義する場合は関数内のみでしか使えない。
基本はグローバルに定義する。
※関数内で定義した変数はほかの関数で同名の変数を定義しても問題ない。
✅組み込みオブジェクトのメソッドを短縮する
document.getElementByIdを短縮する方法
これ感動しました。
function $(e) { return document.getElementById(e); } let startBtn = $('startBtn');
👇アロー関数でさらに短縮。よく使うメソッドは登録しておくと楽ですね。
let l = e => console.log(e); let $ = e => document.getElementById(e); let elem = e => document.createElement(e);
✅諸々のショートハンドに関して
あなたが知らないJavaScriptの便利すぎるショートハンド19選
アロー関数で処理が1文の際はreturn不要
テンプレート文字列はバッククォートを使う。改行もできるのには驚き。
配列
✅fillメソッドを使う
配列の特定の要素を変更したい場合。
let pieArray = [ ["test", 1], ["test2", 10] ] let newArray = ["test", 3]; pieArray.fill(newArray,0,1); l(pieArray); // [ [ 'test', 3 ], [ 'test2', 10 ] ]
✅forEachメソッドで配列のキーごとで分けて計算
🙄第2引数でindex番号取得できるのが結構ポイントな気がします。第3引数で対象にしている配列の値全て出力。
let l = e => console.log(e); let hour = 0 ,Min = 0; timeDB = [ [ '3', '4' ], [ '2', '30' ], [ '4', '25' ], [ '3', '46' ], [ '2', '20' ], [ '1', '0' ] ] // timeDB = Number(timeDB[0].shift()); // 3 timeDB.forEach((value,index)=> { hour += Number(timeDB[index].shift()); // 先頭の要素を取得し削除 }); timeDB.forEach((value,index)=> { Min += Number(timeDB[index].shift()); // 先頭の要素を取得し削除 }); l(hour); // 15 l(Min); // 125
✅mapメソッドとfilterメソッドを使う(※forEachを使わない)
filterメソッドは与えられた関数によって実装されたテストに合格したすべての配列からなる新しい配列を生成.
※コールバック関数がtrueを返した場合に、その時の要素を追加する
mapメソッドは与えられた関数を配列のすべての要素に対して呼び出し、その結果からなる新しい配列を生成。
参考:JavaScript で forEach を使うのは最終手段
以下をfilterメソッドとmapメソッド使って実装してみる。
let n = 0; Object.keys(allDB).forEach((key) => { if (allDB[key].time !== ""){ ttlTimeDB[n] = allDB[key].time; n++; } }) l(ttlTimeDB);
期待値は以下の感じで””となっているデータなどを排除したい。
[ '3時間4分', '2時間30分', '0時間0分', '0時間0分', '0時間0分', '0時間0分' ]
以下がmapメソッドとfilterメソッドを組み合わせた場合。
let ttlTime = allDB.map(key => key.time); ttlTime = ttlTime.filter(value => value !== ""); l(ttlTime);
🙄衝撃!!
✅findメソッドとfilterメソッドの違い
filterメソッドは該当する配列を全て配列に追加していく。
findメソッドは該当する配列の1つ目を取り出す。※変数に代入すると最後の1つのみになってしまう。
個人的に実験してみました。
let l = (e) => console.log(e); array = [ ["javascript ", 60], ["test", 30], ["vue", 20] ]
let filter_result = array.filter((value) => { return value[0] === "test"; }) l(filter_result); // [ [ 'test', 30 ] ] let filter_none_result = array.filter((value) => { return value[0] === "none"; }) l(filter_none_result); // [] let find_result = array.find((value) => { return value[0] === "test"; }) l(find_result); // [ 'test', 30 ] let find_none_result = array.find((value) => { return value[0] === "none"; }) l(find_none_result); // undefined
filterメソッドは新しく配列を作成。
findメソッドは与えられた配列からピックアップしてくるイメージですね。
また、findメソッドはundefinedを返すのがポイント!!
オブジェクト
✅オブジェクトをforEach
Objectオブジェクトのkeys()メソッドを利用。
let obj = { x:"X",y:"Y",z:"Z"} // keys()でプロパティを取得できる Object.keys(obj).forEach(key => { l(key + obj[key]); });
出力
xX yY zZ
👇オブジェクトのオブジェクトをforEach
let obj2 = { 1:{ x:"X" }, 2:{ x:"X" }, 3:{ x:"X" }, } Object.keys(obj2).forEach(key => { l(key + obj2[key].x); });
出力
1X 2X 3X
✅オブジェクトへの要素追加と出力
オブジェクトのキーを指定してあげて追加すればOK。
let obj = { x: {x: "X"}, 1: {x: "X"}, 2: {x: "X"}, }; console.log(obj.x.x); // X obj[3] = {x: "X"}; l(obj.x.x) // X // l(obj.1.x) // error l(obj[3].x) // X // l(obj[x].x) // error l(obj["x"].x) // X
プロパティは名前(キー)と値の関連付け。
出力の部分がだいぶこんがらがる。
””付けないと変数と扱われる。数型は変数の頭文字に持ってこれないので自然とプロパティとして扱われない。
正規表現
✅文字列の分割
参考:【JavaScript入門】文字列の分割と切り出し(substr/substring/slice)
splitメソッドを使う
let time = "3時間4分"; var result = time.split('時間');// [ '3', '4分' ] result2 = result[1].split('分'); console.log(result[0]); // 3 console.log(result2[0]); // 4
🙄この方法やっと理解できた。
splitメソッドに正規表現を組み合わせると。。。
let time = "3時間4分"; let result = time.split( /時間|分/ ); console.log(result); // [ '3', '4', '' ]
🙄とても簡単に欲しい文字を取得することができました◎
更に配列も正規表現で処理。
let times = [ '3時間4分', '2時間30分', '4時間25分', '3時間46分', '2時間20分', '1時間0分' ]; let timesReg = times.map(value => value.split( /時間|分/ )); console.log(timesReg);
出力
[ [ '3', '4', '' ], [ '2', '30', '' ], [ '4', '25', '' ], [ '3', '46', '' ], [ '2', '20', '' ], [ '1', '0', '' ] ]
超便利!!!
上記たど配列の3つ目が不要なので以下の形に修正して処理
timeDB = timeDB.map(value => { let array = value.split( /時間|分/ ); array.pop(); // [ '2', '30', '' ]になっているので最後の要素を取得して削除 return array; });
以下出力結果
[ [ '3', '4' ], [ '2', '30' ], [ '4', '25' ], [ '3', '46' ], [ '2', '20' ], [ '1', '0' ] ]
計算処理
✅値の合計を出す
参考:JavaScriptで配列内の値を加算する方法を現役エンジニアが解説【初心者向け】
let array = [1,2,3] function reducer(first,second){ l(first); // 1,3 ※累積される値 l(second); // 2,3 ※今処理されている値 return first + second; } array = array.reduce(reducer) // 合計値 l(array); let array2 = [1,5,10] function reducer(first,second){ l(first); // 1,6 ※累積される値 l(second); // 5,10 ※今処理されている値 return first + second; } array2 = array2.reduce(reducer, 5) // 合計値 l(array2); // 21 ※最後に5が加算される
🙄for文で加算していく方法しか知らなかったので便利ですね!!
VScode編
命名規則(省略)
おわりに
随時追記していきます。
コメントを残す