はのちゃ爆発

はのちゃが技術ネタとか日常のこととかを書いてます。

はのフロントエンド入門 #4 JS基礎 & ES6 編

久々の投稿です。フロントエンド入門その4、JS基礎とES6の話です。 React の話をするつもりでしたが、そもそもその前に JS そのものの話をしていなかったのでざっくりまとめます。

ES6のまとめ記事は色々あるので今更まとめ直すのもアレかと思いつつ、自分用の学習メモとして。

他のプログラミング言語をある程度知っている前提で書きます。

変数、制御構文、演算子や基本的なオブジェクトについては他の(オブジェクト指向)言語とあまり変わらないはずなので省略。 主に JS 特有の書き方などについてまとめたいと思っています。

昨今のJS事情(主に ES6 について)

昨今、Webフロントエンド開発では ES6 (正式名称 ES2015) の構文を使って開発を行うことがスタンダードになっている、はずです。

JS は前述の通り他のプログラミング言語と基本構文はそこまで変わらないのですが、そもそもあまり本格的なプログラミングをできるような言語にはなっていませんでした。 それを改善し、ある程度の規模のプログラミングにも耐えうるように様々な機能追加を行ったのが ES6 です。

(そもそもJSとは、 ES(ECMAScript) とは、などは書くと長くなるのでまた別途。)

今後JS開発を始めるなら、基本的に ES6 を使って書くのが正解だと思います。

ES6, ES6 って言ってますが、別にそんなに身構える程のものではないですし、 ES6 を使わない従来の JS の書き方も普通に使えるので、ちょっとずつ取り入れて慣れていくのが良いと思います。

とりあえず言いたいのは 「ES6 は身構えるほど怖いものではない」 です。気軽に行きましょう。

JavaScript 入門

ということで実際の書き方を見ていきます。

変数、定数

基本的には const 、でなければ let を使いましょう。

const は定数、あるいはイミュータブルな変数の定義をします。定数と言いつつ他の言語で言う定数とはやや扱われ方が違います。 「一度定義した後の変更」が出来ません。正確に言うと「再代入」が出来ません。

const foo = 1;
foo = 2; // NG!!

なお、あくまで再代入が出来ないだけで、オブジェクトを格納した場合、そのオブジェクトの中身の変更は出来たりします。

let は通常の変数定義になります。変数なので定義後に値の変更が出来ます。

let foo = 1;
console.log(foo); // => 1
foo = 2;
console.log(foo); // => 2

基本的には const を使うように心がけ、どうしても同じ変数で値を書き換える必要があるときだけ let を使う、という使い分けが良いと思います。 意外と変数を定義した後に変更しなきゃいけないケースは少ないです。 React 特有かもしれませんが…

JS の関数

ES6 の有無にかかわらず、 JS は関数の扱いにやや癖があるので、ざっくり基本的なところをまとめます。

JS における関数は、

といういくつかの扱われ方があります。最近コード書いててアロー関数以外書いた記憶が殆ど無いので、アロー関数だけ説明します。

…とはいえ関数の特性について触れないのはアレなのでざっくり。

JS において、関数はデータ型の一種、つまり数値や文字列、オブジェクトと同列に扱われます。つまり、

「関数を変数に代入したり、引数として他の関数に渡したり、あるいは関数の返り値として関数を返す」

ことが出来ます。変数に代入できるので、以下のように関数を扱うことができます。

const fooFunction = function(x) {
  console.log(x + 1);
}
fooFunction(1); // => 2

これは従来の関数リテラルの書き方( function 以下 )で、アロー関数を使うと以下のようになります。

const fooFunction = x => {
  console.log(x + 1);
}

更に省略して以下のようにも書けます。

const fooFunction = x => console.log(x + 1);

記法的には以下のようになります。

(引数) => {関数内の処理}

引数がなければ

() => {処理}

のように書けます。また、 fooFunction の例のように引数が1つだけなら () を省略しても大丈夫です。

テンプレートリテラル

文字列中に変数を埋め込みたい、展開したいことは結構あると思います。これまでは + を使って結合したりしてましたが、

const name = "hanocha"
console.log(`Hello, ${name}!`) // => Hello, hanocha!

のように書けます。文字列を囲う時にクオート、ダブルクオートの代わりにバッククオートで囲うとテンプレートリテラルになります。

分割代入

JSではオブジェクトをよく使う(気がする)のですが、あるオブジェクト中から特定のキーの値を取り出したい時に分割代入が使えます。

const obj = {
  x: 1,
  y: 2,
  str: "test",
  num: 3,
};

const { y, str, ...rest } = obj; // y, str という const を obj から取り出す

...rest のように書くと rest 内に取り出さなかった残りの値が格納されます。

Class

ES6 からクラスが使えるようになりました。他の言語のクラスとそこまで使い勝手に差はない…はず。

class hogeClass {
  constructor() {
    // 初期化処理
    this.hoge = ...
  }

  hogeMethod() {
  }

  ...
}

余談ですが、 React を使っていると、以下のようにクラスを使うことが多いです。

import React from "react";
...
class hogeComponent extends React.Component {
  constructor(props) {
    this.state = {...}; // state の初期化
    super(props);
  }

  componentDidMount() {
     // コンポーネントがマウントされた時に行いたい処理
  }

  render() {
    // コンポーネントのレンダリング
    return <...>
  }
}

import, export

上記の Class で一瞬 import を使ってしまっていますが、 importexport という構文が使えます。

なんとなく想像できそうですが、 import はライブラリや他のファイルの読み込み、 export は自分(ファイル)を他のファイルから参照できるようにするためのエクスポートをするためのものです。

以下に import の例を示します。

// `react` というモジュールから(デフォルトエクスポートされた) `React` をインポートする
import React from "react";

// `hogeModule` から `hoge` をインポートする
import { hoge } from "hogeModule";

// `../path/to` 以下の `myModule` から `myFunc` をインポートする 
import { myFunc } from "../path/to/myModule";

// `hogeModule` の `hoge` を `myHoge` という別名でインポートする
import { hoge as myHoge } from "hogeModule";

// `fugaModule` をインポートする(あまり使わない)
import from "fugaModule"

次に export の例です。

const hoge = ... // エクスポートしたい適当な何か

// hoge をエクスポートする
export hoge;

// hoge をデフォルトエクスポートする
export default hoge;

// fuga を定義しつつエクスポートする
export const fuga = ...

// 他のファイル `otherModule` がエクスポートしているものを other という名前空間を切ってエクスポートする
export * as other from "../path/to/otherModule";

だいたいこんな感じに使います。バリエーションが多く、いきなり全て覚えるのは難しいので、使いながら慣れていくのがいいと思います。

from だけ少し補足。基本的にはインポートしたい対象のパス、名前を指定するものですが、指定方法がいくつかあります。 このパスの解決は基本的に webpack (もしくはそれに相当するもの)が行ってくれます。 webpack を使っていない場合はまたちょっと違う解決のされ方をする…のかな?

Module Resolution

上記のページに書いてある通りですが、

// 絶対パス指定での import
import foo from "/abs/path/to/module";

// 相対パス指定での import
import bar from "../rel/path/to/module";
import bar2 from "./rel/path/to/module";

// 別途定義されたモジュールパスから見た相対パス指定での import
// npm install したライブラリからの読み込みなどはコレ。 デフォルトで node_modules 以下?
import React from "react";

など。 webpack などのバンドラを使わない場合、一番下の記述は相対パス指定として扱われそう。

developer.mozilla.org

まとめ

ということでざっくりと JS基礎と ES6 についてまとめました。本当によく使う部分だけまとめたので、 JS という言語そのものの書き方、あるいは ES6 の新機能は他にもたくさんあります。 が、とりあえずこれから JS を始める、あるいは軽く ES6 を使ったモダンな JS について知っておきたいというだけならこれだけで十分…だと思います。多分。

もっと詳しく色々な情報を知りたい場合は以下の参考資料をご覧ください。

参考資料

medium.freecodecamp.org

github.com

babeljs.io

qiita.com

qiita.com

▼ ES6 以前のJS基礎からモダンJSまでまとめてカバーしている入門書。

▼ ES6 仕様書。真面目に読むと大変なので参考程度に。 ECMAScript 2015 Language Specification – ECMA-262 6th Edition