この講座は「最終的にこれを作ります」形式ではなく、ES6から導入された、または改良された文法を実例と共に紹介していく講座のため、このレビュー記事も「これが後で~」などの記述は少なくなるため「サラッと」にしました。それでもこの講座の良さを少しでもご紹介出来たら幸いです。実際に使用されるコードも紹介しますが、コンテンツを侵害する意図はありません。
大きな特徴として全てのセクションではありませんが“演習問題”が用意してあり、この難易度が結構高いです。基本的な文法の確認から応用として「~~関数を作ってみよう」という問題が出され「こういう時に○○してくれる~~関数を今回習った##を使って実装」といった具合です。すでに質問も多くありますのでその回答も参考にチャレンジしてみてください。この記事では演習については解説しません、長くなるので。ちなみに講座を収録しているのは2018年と少し古めです。
Sec1 はじめに
“1”この講座の紹介です。Stephen Grider氏の講座を福山健さんが日本語版で作成したものになります。const-letもES6からなんですね、これしか知らないので逆にvarに馴染みがない人もいるのでは?JavaScriptにclassがなかったというもの知らなかったし、ES6で多くの改良がされたんですね。レッスンの進め方として「書いたコードをすぐ実行」するためにStephen Grider氏が作成したエディタ・実行画面・エラー表示が1つの画面で同時に見れる「Rally Coding」というものを使います。VSCodeの自動予測変換などはないようですが、「コードを書いて、Chrome開いて~」の手間がなく左にコードを書くとすぐに右上のエリアに実行された結果、エラーも右下に表示されるため便利です。無料で公開されているので使いましょう。“2”ES6とは標準規格ECMAScriptの6番目のバージョンということですが、ES2015も同じ意味になります。
Sec2~7 便利メソッド
配列で使える便利メソッド、これが本講座のメインと言ってもいいかもしれません。「forEach map filter find every some reduce」の7つを使って「for文を書かずに記述を少なく、一目でわかりやすいコードを目指す」が大きな目標です。というわけでこういったスタートなので全くのJavaScript初心者には本講座は向いていません。「足し算は~」「===でイコール」「関数とは~」みたいな基本文法は出てこないので「JavaScriptって何?」という方は他の講座から始めることをオススメします、本講座はES6の焦点を当てたものになっています。
“4”から実際にコードを書いていきますが、まずfor文は長い・わかりにくい
var colors = [‘red’, ‘blue’, ‘green’];
for (var i < 0; i < colors.length; i++) {
console.log(colors[i]);
}
このようにまずfor文で元となるコードを書いてこれを便利メソッドforEachだと
colors.forEach(function(color)) {
console.log(color);
}
この方が記述も少ないし、「あ~forEachね、一つずつcolorで取り出してるのね」と読みやすい、ということです。コールバック関数という用語も当然のように使われますので、やはり初心者向けではありません。メソッドそれぞれで使いどころなど解説もありますが、そちらは省略しますので気になる方は講座へ。続いてmap
var number = [1,2,3];
var doubledNumbers = [];
for (var i < 0; i < numbers.length; i++) {
doubledNumbers.push(numbers[i] * 2)
}
doubledNumbers;
var doubled = numbers.map(function(numbers) {
return number * 2;
});
doubled;
の結果[2,4,6]が出力されます。こちらも省略しますが、文字だけでなく音声だけでなく図を使っての解説がとてもわかりやすいのもこの講座の特徴です。この後も繰り返し言われますがreturnを忘れずに!returnがないと[null, null, null]となります。ここまでは自分で使ったりもしていましたが、次は見慣れない?filterです。
var products = [
{name: ‘トマト’, type: ‘野菜’},
{name: ‘りんご’, type: ‘フルーツ’},
{name: ‘さんま’, type: ‘魚’},
{name: ‘メロン’, type: ‘フルーツ’},
];
var filteredProducts = [];
for (var i < 0; i < products.length; i++) {
if (products[i].type === ‘フルーツ’) {
filteredProducts.push(products[i]);
}
}
products.filter(function(product) {
return product.type === ‘フルーツ’;
});
これだけで{name: ‘りんご’, type: ‘フルーツ’},{name: ‘メロン’, type: ‘フルーツ’}が出力されます。この辺りで便利メソッドの利点を感じてきたのではないでしょうか?記述がすくなく”filter”という文字を見つけたら“抽出してる”がイメージしやすい、というわけです。今のは”11”のコードでしたが、基本の使い方を紹介しさらに別の使い方も「続」という形で照会されるのもわかりやすく、”12”のコード例では「&&」や「不等号」で条件を複数指定しますし、“13”では配列を2つ用意して「何番の投稿idに対してのコメントidか」を紐付けて取り出すSQLのリレーションのような操作もできます。“取り出す”作業で似ているのが次のfindです。
var users = [
{name: ‘steve’},
{name: ‘james’},
{name: ‘jeff’},
];
var user;
for (var i < 0; i < users.length; i++) {
if (users[i].name === ‘james’) {
user = users[i];
}
}
これでjamesが出力されます。しかし細かいことなんですが、この書き方では3人目のjeffまでループが回ってるのです。そこでuser = users[i];の下にbreak;を入れることで「見つかったら終了」にするのですが、やはり長いですよね。最初に見つかった時点で終了するのがfindです。
users.find(function(user) {
return user.name === ‘james’;
});
見つけたら終了なのでもっと大きなデータで100番目くらいに同じ名前のjamesがいてもそのid=100のjamesは取得されないので注意。
ここから“取り出す”とかの話とは少し異なるevery-someですが、for文は省略してもわかるはず。
var computers = [
{name: ‘Apple’, ram: 24},
{name: ‘Compaq’, ram: 4},
{name: ‘Acer’, ram: 32},
];
computers.every(function(computer) {
return computer.ram >= 16;
};)
これでFalseが返ってきます。「全部16以上?」「いいえFalse」と読めますね。someも理屈は同じです。
computers.some(function(computer) {
return computer.ram >= 16;
});
これで「どれか16以上のもの1つでもある?」「はいTrue」となります。“20”の使いどころはバリデーションで名前やパスワードがあるかをチェックし、その項目がメールアドレスなど増えても対応できるように「全て通ってますか?」を確認するために使う場面を紹介しています。
“21”から最後の便利メソッドはreduceです。「ガチ、フロントエンド」でも出てきたのでこれが最も難しいことはわかってました。reduce自体の意味は「減らす」ですが、1つずつ“積み重ねる”作業をイメージするとわかりやすいかも。
var numbers = [10, 20, 30];
var sum = 0;
for (var i < 0; i < numbers.length; i++) {
sum += numbers[i];
}
1つずつ足していって60になると思います。reduceは初期値を設定します。
numbers.reduce(function(sum, number) {
return sum + number;
}, 0);
第2引数に0という初期値を書くことで、1回目の処理で「0+10」でsumが10になり2回目の処理で「10+20」で30、3回目の処理で「30+30」、この結果60が出力されます。sumが更新されていき次のnumberと足されます。第2引数の初期値に0ではなく1を書けば最終的に61になるはずです。「ガチ、フロントエンド」の文字列ANIMATIONを分割しアニメーションを付けるに比べれば、簡単ですね。”23”のカッコの数’((()))’が均衡がとれているかはプログラミング脳の問題といいますか「ふ~ん」でいいです。
Sec8-12 新しく覚えるものは少ないセクション
“24”から後半でしょうか、constとletですが難しい話はありません。この記事もここまではレッスン動画に合わせてvarで宣言をしてきましたが、ES6からvarは使わないようにするように推奨されているんだとか。簡単に分けると「変わる予定があるものはlet、変更しないものはconst」を使えばいいし、深く考えなくてもまずconstで定義して「やっぱりこれ変わるやつだった」とわかった時点でletに書き直せばいいです。例えばアカウントの情報など名前や誕生日はconstで役職・居住地などはletを使います。なぜ使い分けるか?は便利メソッドと同じ「パッと一目で理解しやすい」が大きな理由です。他の人がコードを見た時など「あ~この配列は変わらないのね、なるほど」と全てvarで宣言されているコードに比べると読みやすくなりますよね。
Sec9は変数を文字列に埋め込むテンプレートリテラルです。
function getMessage() {
const year = new Date().getFullYear();
return “今年は” + year + “年です”
return `今年は${year}年です`;
}
これで両方ともに文章の中でyearが2021に変換され挿入されます。「`」は見慣れないですが「バックティック」といいます。${}の中なら${year + 4}で4年後を表示することも出来ます。
Sec10はアロー関数です。今JavaScriptを学び始めた人は当然聞いたことあるものですよね。関数の書き方で「こうも書けます」と教えている教材もありますが、アロー関数もES6からの追加なんですね。
const add = function(a, b) {
return a + b;
}
この普通の関数を
const add = (a, b) => {
return a + b;
}
こう書き換えるだけでアロー関数は出来上がりですが、ここからさらに省略を図ります。
const add = (a, b) => a + b;
実行が1つの場合は{}もreturnも省略できますが、個人的には読みにくいと思います。“29”ではさらに引数が1つの場合に()も省略
const double = (number) => {
return number * 2;
}
const double = number => number * 2;
double(8)とすると「16」が出力され、これは同じ意味になりますが、皆さんはどちらが読みやすいでしょうか?
さらにここからthisの取り扱いという別の話ですが、詳しくは「ガチ、フロントエンド」の作者CodeMafiaさんがYoutubeで解説もしているので見ていただきたいのですが、コールバック関数の中でthisを使うとオブジェクト内を参照せずundefinedになるので、bind(this)でthisを束縛したり、事前にvar self = thisなどでselfとしてコールバック関数の中でthisの代わりにselfを使ったりがES5までの方法だったそうで、ES6からはアロー関数にするだけでコールバック関数内でthisが使えるようになります。
Sec11は同じものを省略するオブジェクトリテラルです。全部は書きませんがオブジェクト内で
return {
inventory: inventory,
inventoryValue: function() {
~~
}
}
があった時に「同じのは省略したいよね」という考えから
return {
inventory,
inventoryValue() {
~~
}
}
に出来ます。キーとバリューが同じ、またfunctionを書かなくても()で関数をイメージできるので省略します。
Sec12は指定されなかった時の「これを入れてね」の関数のデフォルト引数です。!methodなど「methodがなかったら」のif文を書くと場所をとるので、あらかじめ引数の場所で指定しておきます。
function makeAjaxRequest(url, method = “GET”) {
~~
}
Sec13-15 すぐ使えなくても読めた方がいいセクション
Sec13から難しい…まずはrestとspreadです。
function addNumbers(…numbers) {
return numbers.reduce((sum, number) => {
return sum + number;
}, 0);
}
addNumbers(1,2,3,4,5,6);
これで「…」のrest演算子でいくつでも受け取てnumbersという配列で格納し1つずつ足していくreduceが作動します。spread演算子はその逆に「広げる」ことをします。
const redColors = [‘赤’, ‘オレンジ’],
const blueColors = [‘青’, ‘緑’],
[…redColors, …blueColors]
とすることで「‘赤’, ‘オレンジ’, ‘青’, ‘緑’」が出力されますし、そこに要素を加えることも
[…redColors, ‘黄’ …blueColors]で「‘赤’, ‘オレンジ’, ’黄’ ‘青’, ‘緑’」と好きな場所に簡単追加することが可能です。
Sec14は分割代入、これは使いどころでもなかなか使おう!とはならないかも…
let expense = {
type: ‘交際費’,
amount: ‘4500円’
};
let type = expense.type
let amount = expense.amount
と書くところを(これでもいいと思いますが)
const {type, amount} = expense;
amount;
これで4500円が出力できるのですが、わかりにくい…“40”では関数の引数のなかでも分割代入を使います。”41”でもさらに配列の分割代入、ただは書き方は同じで[]になるだけ
const companies = [
‘Google’,
‘FaceBook’,
‘Amazon’
];
const [name, name2, name3] = companies;
これをrestで残りを配列にする応用も紹介
const [name, …rest] = companies;
とすることでnameはGoogleでrestは[“FaceBook”, “Amazon”]になります。”42”でオブジェクトと配列で分割代入を併用、”43-44”は使いどころですが読みやすいです…気になる方は講座へ。このセクションの演習問題の3問目34が最も難しいです、解説するのも難しい…のでパス
Sec15はclassそこまで特殊なのは出ませんが、prototypeはES6以降は使わないってことでいいのかな?欲しいクラスをextends○○で継承してconstructor内でsuper()も必要、その他そのクラスで独自に設定したいプロパティはsuper()の下などにthis.title = title;など付け足します。
Sec16-17 見るだけいいセクション generatorとpromise-fetch
この2つは演習もないですし、「こんなのもあるんだ~」でいいと思います。generatorはオブジェクトを独自の関数で引数で受け取りyieldプロパティとして好きなように取り出せたりします。Promiseは処理が成功(resolve)したらthen()、失敗(reject)したらcatch()の中が実行されます。PHPでのcatchで例外処理もここと関係していると思われます。fetchはurlをリクエストしてそのレスポンスを見てますが、「それがどうした」としか思えないSec17でした。
generatorについては独自に調べてましたが、Youtubeの英語解説動画が多くこのレッスンで概要を掴めていれば眺めているだけでも何を言っているか大体流れでわかります。まずiteratorがnext()メソッドを持っていてvalueとdoneを返す、yieldの数だけnext()を実行できる、next()を実行するたびに関数は中断、こんなカンジでしょうか
まとめ
今回も1周目は普通に学んで2周目に復習を兼ねてのレビュー記事を書いてきましたが、この講座の重要なのは前半の便利メソッドかなと感じました。記述少なく、読みやすいコードを目指すことが大事であって、ES6からそこが改良されたのでしょう。後半の分割代入あたりから「それで?」と思うものが増えてきましたね、特にgeneratorとpromiseはたしかにES6で導入されたんでしょうけど、今すぐ必要性を感じるものではありません。
この記事では触れていませんが、各セクションの演習問題は難易度も高く非常に手ごたえがあるものですので、興味を持たれた方は受講を検討してみてください。
おまけ
演習問題で上手く実行できない箇所があったので記しておきます。classes.mapをclasseなら動くけどclassでエラーになった、ということです。
のをオブジェクトリテラルで省略。と思ってたけどおかしい…classes.mapを引数でclassにするとエラーで動かないが、classeにすると動くしclassesのままでも動く。classesだとそのまま配列を受け取ってる?ここは「s」を取ることしか認めてないの?どういう名前で受け取るかは自由だと思ってたけど
— Halu@エンジニア(未) (@halu_0366) June 1, 2021
記録として残す
— Halu@エンジニア(未) (@halu_0366) June 1, 2021
const classes = [
[ '化学', '1時限目', '鈴木先生' ],
~,
~
];
const classesAsObject = https://t.co/A0Eh03Z6cm( class => {
const [ subject, time, teacher ] = class;
return { subject, time, teacher };
});
classesAsObject;
これだとエラー、classeで動く
コメント