以前働いていた会社で、「JavaScriptを覚えておけば何でもできるぞ!」と言われたことがあります。
その時は「?」だったのですが、たしかにフロント側はもちろん、サーバサイドもNode.jsなどで制御できてしまうので、マルチプレイヤー言語です。
初心者が覚えておきたいJavaScriptの基礎を要点を絞って書いていきます。
歴史
JavaScriptは、最初期のWebブラウザであるNetscape Navigator付属のスクリプト実行環境として誕生し、最初はLiveScriptという名前でした。
フロントエンドの動きを制御できる言語で、例えばアラート表示、画像のスライダーなど枚挙に暇がありません。Webの広告もJavaScript使っていますよね。
プログラムは、文字や数値を変数に入れて、他のプログラムと組み合わせたり処理をした結果を表示させたりする一連の命令の集まりといえます。
そのためには、抽象化することが重要です。汎用性が上がるとより多くの場所で利用することができるからです。
それが、変数や関数や引数になります。
変数
自由に文字や数値、複雑なオブジェクトを代入して扱えるものです。
イメージ
鍋に出汁をはっておいて、そこに何を入れるのかでできあがる鍋が変わる。この場合の「鍋」は抽象的で自由に応用できる。この「鍋」が変数。
コメントアウトとコードの終わり
// 一行コメント
/* 複数行コメント
コメントコメント
コメントコメントコメント
*/
この行に関しては実行から無視される。
そしてコードの最後はセミコロン「;」をつける。
Node.jsはたくさんのモジュールがある
サーバ側の言語として有名なNode.jsは、JavaScriptで記載していくのですが、なぜ使われているのかというと、様々なモジュールがあるため有益だからです。
JavaScriptはもともとスクリプト実行環境なので、サーバーサイドを操作できる仕組みがない。そこで、Nodeが利用できる便利機能が、モジュールであり、Nodeにはめちゃめちゃたくさんのモジュールがある。ということです。
例えば、
const fs = require(‘fs’);
のようにすると、fsというファイルを操作するモジュールを利用できます。
また、HTTPモジュールを使うとHTTPサーバーを起動させることができたりもします。(参考までに)
const http = require(‘http’);
// nodeにおけるHTTPモジュールのAPI。
/* サーバーには、リクエストを表すオブジェクトの引数reqと、
レスポンスを表すオブジェクトの引数resを受け取る無名関数を渡す。
※この無名関数は、サーバーにリクエストが合った際に呼び出される。
*/
const server = http.createServer((req, res) => {
// 無名関数の中では、レスポンスヘッダーをwriteしている。
res.writeHead(200, {
‘Content-Type’ : ‘text/plain; charset=utf-8’
});
// writeはHTTPレスポンスの内容を書き出す。
res.write(req.headers[‘user-agemt]);
// endメソッドでレスポンスの書き出しを終了。
res.end();
});
const port = 8000;
// HTTPサーバーを起動する関数は、listen関数。
server.listen(port, () => {
console.log(‘Listening on’ + port);
});
変数宣言
変数を使う前には、「〇〇を使います!」という変数宣言をしたほうがいいです。
(しなくてもJavaScriptは動きますが、わかりやすくするためにしたほうがいい。)
そんな宣言方法は以下の2種類です。
- let
- const
2つの違いは、letは同じ変数に何度も値を代入できる のですが、constはそれができない。(1回きり。変更するとエラーになる。) ということです。
使い分けが必要です。
関数
関数(ファンクション)
処理のまとまりのこと。よく使う処理はまとめて名前(関数名)をつけておけばどこでもそれを呼び出すことで使えるようになるので便利です。
例
function 関数名(引数…) {
// 処理内容
}
関数には予め用意した値を渡すことができ、これを引数といいます。(引き渡す)
引数はあってもなくてもいいのですが、引数がない場合であっても()だけは記載しないといけません。
例:引数がない場合
function 関数名() {
// 処理内容
}
ただし現在は、functionという表記をしないことが多いです。
アロー関数という => こういうやつを使って書きます。なぜかと言うと、こっちのほうが書く量が少なくて済むので良いからです。
例:アロー関数を使った関数宣言
const 関数名 = (引数) => {
console.log(引数);
};
引数
引数は、関数に渡すことで処理をする処理の元となるデータです。複数指定する場合は、カンマで区切り、第1引数、第2引数 ・・・と呼びます。
例:引数(wordsとpage)を関数(search)に渡している
const search = (words, page) => {
console.log
}
配列
配列は、同じ特徴を持つ要素を並べてひとまとまりにしたものです。同じ特徴の色んなものが入っている箱みたいなイメージ。
身近だと、本が色々入っている本棚などのイメージですね。
例:配列
let 配列名 = [要素1, 要素2, 要素3];
要素1~3までが入った箱の名前が 配列名 という意味。
例のように記述します今度は[ ]ですね。箱っぽいのでわかりやすい。
そして例の状態だと実は勝手に番号が振られており、要素1が0番め、要素2が1番め、要素3が2番めということになります。(※間違いやすい※)
要素を追加する場合は、push
配列に要素を追加する場合は、pushを使います。
例:pushで麦わらの一味にウソップを追加する
配列名.push(追加する要素);
let mugiwara = ['ルフィ', 'ゾロ', 'ナミ'];
mugiwara.push('ウソップ');
追加された!
要素を削除する場合は、splice
配列の要素を削除する場合は、spliceを使います。
例:麦わらの一味からゾロを削除
配列名.splice(要素番号, 削除する個数);
要素番号1のゾロだけ消えましたね。。。
ループと条件分岐
「もし〇〇だったら●●する。」というやつです。
ループとは繰り返し(コンピュータが得意)、条件分岐はifです。
for文
指定した条件がfalseになるまで繰り返す書き方です。
for ([初期化式]; [条件式]; [加算式])
if文
指定した条件がtrueかどうかを判断し、それに応じて処理を行う書き方です。
もし、次の対戦相手がフリーザだったら、
ベジータをつかう。(true/false)
次の対戦相手が、セルだったら、
悟飯をつかう。(true/false)
どちらでもなかったら、
悟空を使う。
ドラゴンボールで例えてみました。
書き方でいうと、こうなります。
if ( 条件 ) {
// 条件がtrueのときに実行する処理
}
if ( 条件 ) {
// 条件がtrueのときに実行する処理
} else {
// 条件がfalseのときに実行する処理
}
例:麦わらの一味の中で武器を持っているキャラと持っていないキャラを出力
出力結果は、0番目(ルフィ)武器なし、その後3つ(ゾロ、ナミ、ウソップ)武器あり、最後(サンジ)武器なしとなりました。
条件分岐と繰り返しを使っています。
同期処理、非同期処理
JavaScriptには、同期処理と非同期処理があります。同期はsync(シンク)、非同期はasync(アシンク)とよんだりしています。
同期処理
1つの処理と完全に連動して別の処理をすることをいいます。
非同期処理
一つの処理と別の処理が別々に動くことです。同期せずに別行動です。
処理というのはクリックなどのイベント(事象の発生)のことです。
わかりやすいのは同期処理で、処理Aが終わってから処理Bが始まるということですが、非同期処理は処理Aの終了を待たずに処理Bを行うことをいうのでなんだか非同期処理のほうが便利そうです。
だって1つずつ処理が終わるのを待っていたら直列処理になってしまって、待ち時間が増えてしまいますし、並列処理ができるならしたほうがいいじゃんか!ということです。
そこでJavaScriptでは非同期処理において以下の3つの方法があります。
- コールバック関数
- Promise
- asinc/await
コールバック関数
コールバック関数とは、呼び出し先であらかじめ呼び出し元が指定する処理のことです。
関数の引数に別の関数を指定する処理、他の関数に引数として渡される関数 ともいわれています。
特にネットワークを挟む処理はそこでの時間がかなりかかるものなのです。
そこで、呼び出し先は主な処理を行い、その後に呼び出し先で予め指定した処理を呼ぶことで呼び出し先に処理が戻るという動きをします。
var func1 = function() { // 関数の定義 }
func2(func1);
Promise
Promiseは、非同期に実行される未来の結果を表すオブジェクトのことです。
未来の約束というイメージでしょうか。
Promiseから値を取得するときは、then関数を読んでそこに実行完了時に呼び出されてほしい関数を与えることで未来の結果を利用することができます。
また、catch関数で処理が失敗した際に行う処理を記載します。
testPromise(‘param’)
.then((data) => {
// 上手く行ったときの処理
}).catch((error) => {
// エラーのときの処理
});
今回参考にしている、Puppeteer入門 スクレイピング+Web操作自動処理プログラミング のサンプルコードを見てみます。
例
function myPromiseFunction(params) {
return new Promise(function (resolve, reject) {
// ファンクションの処理
if (params) {
// Promiseの中でresolveを呼び出すと処理成功。
// resolveにパラメーターを渡すと myPromiseFunction の戻り値として帰る。
resolve('OK');
} else {
// rejectは処理が失敗したことを表す。
// パラメーターはエラー内容として帰る。
}
});
}
今風にアロー関数を使って書き直すと、
const myPromiseFunction = (params) => new Promise((resolve, reject) => {
// ファンクションの処理
if (params) {
resolve('OK');
} else {
reject('NG');
}
});
こうなります。
具体的なことで例えると、APIからデータを読み込んでいる場合。読み込み中に非同期で整形や表示が進んでしまったらエラーが出てしまいます。これはNGですね。
PromiseでAPIの呼び出しが成功するまではAPIデータが整形、表示されないことを約束 Promise できるのでPromiseが使われます。
その他、Promise処理を続けて呼び出すプロミスチェーンもあります。
async / await
Promiseを利用した構文よりも、簡潔に非同期処理が書けるので使われるものです。
asyncはPromiseを返す変数であることを示す予約語で、わざわざPromiseのようにresolveメソッド呼び出す必要がないです。
そしてreturnする値をPromiseにラップして返します。
Promiseを返すメソッドを呼び出すときは、呼び出すメソッドの接頭語にawaitをつけます。
-> Promiseで返した値(Promise関数内でresolveの引数に渡した値)を返す。
awaitを使うためにasyncの無名関数でラップします。
つまり、asyncで予約してawaitで呼び出すという動きになります。
この非同期処理部分は奥が深いので別の記事として書くかもしれません。
最後に
今回は、少しコードも交えてJavaScriptの基礎部分をざっと紹介しました。JavaScriptを極めることはかなり汎用性が高いことで、エンジニアであればいずれにしろJavaScriptは使わないといけないので「こんな事できるんだ〜」を増やしていくことは大事なことです。
参考資料
エンジニアリングはスクールで学ぶのもアリ
独学でできるのであればそれば一番です。
ただ、やはりメンターをつけてガッツリ短期集中でやったほうが個人的には時間が有効に使えると思います。今の所のイチオシは TECH CAMP です。無料体験でも技術だけでなく、自分がプログラミングスクールを経てどういう道のりを描いているのかを一緒に合わせてくれるので、エンジニア転職の方でもテクノロジースクールの方も体験はしておくのがいいと思います。
(一人でやっていたりすると自分を見失ってしまったりしますので笑)