はじめに
Nuxt.js+Typescriptでの開発現場に入ってはや4ヶ月。前はマークアップエンジニアだったのでせいぜいjQueryでDOM操作することしか実務ではしていませんでした。
当たり前ですが今の現場ではゴリゴリとES2015+で書くので自分の出したPRや先輩のPRを眺めながら「このメソッドとか処理よく使ったなあ」というのを振り返ります。
また、あくまでも一現場のR&D的なプロダクトの中で書いている内容なので、そのまま皆さんのプロダクトに当てはまらないということは事前にお断りさせていただきます。
では早速いってみましょう!
アロー関数
わざわざ紹介するほどのことではないのですが、必ず使っているという意味で書きます!
もう一切functionって書かなくなりましたって話です。
function (arg1, arg2){
return arg1 + arg2
}
(arg1, arg2) => {
return arg1 + arg2
}
はい、functionはもう書かなくてOKです。厳密にいうと色々他にもあるのですが(thisの扱いとか)、簡単にかけるようになるのはいいですね。
これから下の処理ももちろんアロー関数で書いていきます。
map
渡ってくる配列の各要素に対して処理をします。返り値は新しい配列になります。
array1.map(処理)
// 処理をした後のarray2が返ってくる
簡単なサンプルはこちら
const array1 = [1, 2, 3, 4];
const array2 = array1.map(x => x * 2);
console.log(array2); // [2 ,4, 6, 8]
map(x => x * 2)
はfunctionを使って書くと
map(function(x) {
return x * 2
})
と一緒です。
実際どんな感じで使ったりするかというと
arrayData.map(data => {
return new Date(data.date).toLocaleDateString()
}
arrayDataが渡ってきて、その中身がObjectの配列だった時に、それぞれのdata(オブジェクト)のdate(日付)を抜き出してきて新しく配列を作り出す
という感じで使ったりしました。
reduce
配列の各要素に対して処理をします。返り値は単一の値です。(配列とは限らない)
array.reduce(処理)
// 何かの値が返ってくる(例えば計算結果など)
簡単な処理はこちら
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1から4までを足す
console.log(array1.reduce((arg1, arg2) => {
return arg1 + arg2
}));
// 合計値の10が返ってきます
実際のプロダクトでは
array.reduce((a,b) => {
return a + b / WEEKDAYS_COUNT // WEEKDAYS_COUNTは1週間 = 7日という意味で7としていた
})
みたいな感じで処理をしたりしていました。
filter
配列に対してフィルタリングを行い、フィルタリングした後の値を新しい配列にして変更します
const words = ['deepleaning', 'python', ' javascript', 'php', 'html', 'css'];
const result = words.filter(word => word.length >= 6);
console.log(result);
// ["deepleaning", "python", "javascript"]という配列が返ってくる
実際のプロダクトでは
array.filter(array_data => {
return array_data.program.weekday === targetWeekday
});
// array_data.weekday === targetWeekdayがtrueになるようなものだけを抽出して新しい配列を返す
のように使っていました。
Object.entries
Object.entries()は、引数に与えたオブジェクトが所有する、列挙可能なプロパティの組 [key, value] からなる配列を返します。オブジェクトに対して使い、配列を返す処理をしてくれるということです。
Objectで返ってくる内容を配列で取り出したい、加工したい、という時にたまに使っていました。
const object1 = {
a: 'hogehoge',
b: 10
};
console.log(Object.entries(object1));
// [["a", "hogehoge"],["b", 10]]
実際のプロダクトではmapと組み合わせて
Object.entries(obj).map(([key, value]) => ({[key]: value}))
/* こんな感じのオブジェクトを
obj = {
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
*/
// こんな感じの返り値を出したい時に使います
/*
[
{
"key1": "value1"
},
{
"key2": "value2"
},
{
"key3": "value3"
}
]
*/
という感じで配列を作っていました。
Object.fromEntries
Object.fromEntries()は、key valueの組み合わせの配列をオブジェクトに変換します。
簡単なサンプルはこんな感じ
const array = [
['sample', 'data'],
['sample2', 100 ]
];
const obj = Object.fromEntries(array);
console.log(obj);
// { sample: "data", sample2: 100 }
配列からオブジェクトを生み出したい時に使っていました。
実際のプロダクトでは
Object.entriesの中でObject.fromEntriesをやっているところとかもあって、読み解くのに一苦労しました。笑
スプレッド構文
配列のようなオブジェクト(正確には for of で展開できるもの)を個々の値に展開するのがスプレッド演算子です。
記法としては...
とピリオド3つを使って表現します。
配列の個々の値に展開する
const data = [1, 2, 3, 8, 11];
console.log(Math.max(...data)); // 11
実際のプロダクトでは
Math.max(
...this.dailyData.map(data => {
return data.increaseCount;
})
)
のようにして使っていました。
おまけ(Typescript)
enum
通常のJavascriptにはないもので、数値の定数に名前を付けて、その集合に対して定義ができるようにしたものです。
例えば
enum userStatus {
ready,
active,
finished
}
のようにセットすると。Javascript側では
"use strict";
var userStatus;
(function (userStatus) {
userStatus[userStatus["ready"] = 0] = "ready";
userStatus[userStatus["active"] = 1] = "active";
userStatus[userStatus["finished"] = 2] = "finished";
})(userStatus || (userStatus = {}));
のようにコンパイルされます。ちょっとややこしいですね。
実際に使う時にはこんな感じで使えるようになります。
(下記の場合だとVue.jsで使っています)
<template v-if="status === userStatus.ready">
<!--userのstatusがreadyの時の内容-->
</template>
generics
genericsは「抽象化されたデータ型」を表現する機能です。
似た感じの関数だけど型が違うケースにおいて、引数である型を抽象的に使う時に便利です。
どういうことかといいますと
- string型のデータを引数にしてstring型のvalueを持った配列を返す関数
- number型のデータを引数にしてnumber型のvalueを持った配列を返す関数
これらの2つがあった時に
let stringArray = (valueOfString: string): string[] => {
return [valueOfString, valueOfString, valueOfString];
};
let numberArray = (valueOfNumber: number): number[] => {
return [valueOfNumber, valueOfNumber, valueOfNumber];
};
上記のように型をつけてもいいのですが、同じような形の関数を2つも書くのはめんどくさいし冗長ですよね。
なのでこれを
let genericsArray = <T>(genericsValue: T): T[] => {
return [genericsValue, genericsValue, genericsValue]
}
とTとして抽象化することで
genericsArray<number>(10)
// [10,10,10]
genericsArrayの引数はnumber型で、かつ返り値もnumber型となってくれます。
<number>
の箇所を
<string>
にすれば
genericsArray<string>(10)
// ["10","10","10"]
のようにできます。
うーん、これは味がありますね。
最後に
実際の開発の中では他にも色々なメソッドに触れましたが、全部は書けないので、この辺で。
来年は業務で使っているJavascript、Typescript、Nuxt.js以外にもPythonを触っていく予定です。もっとたくさんコードを書いて周りのすごいエンジニアの人とちゃんと対等に仕事ができるように頑張ろう。