個人の感想です
黙ってstrict
"use strict";
Node.jsのサーバサイドのソースや、browserifyやwebpackをでバンドルするのを前提にして、jsファイルごとにモジュール化されているならとにかく先頭に書きましょう。
これだけでヤバい実装はエラーで死ぬようになるので安心です。
エラーが出力されるのは幸福です(極論)
なお、昔ながらのhtmlにscriptタグを並べてjsファイルを複数読み込ませるスタイルの際は注意が必要です。
ファイルの先頭に"use strict";
を宣言すると、グローバルレベルでstrictモードが適用されるため、strictモードに対応していないライブラリが死ぬ可能性があります。
strict程度で死ぬライブラリなんて...
そんな時はjsファイルの中身全体をfunctionでくくりましょう
(function() {
"use strict";
console.log("こいつ...できる...!");
}());
今ではあまり見なくなったパターンですね。
もう「var」なんて言わない
変数の宣言をvarで行ってたのは過去の話です。
巷に溢れるJavaScriptの入門サイトや入門書などでは未だに「varで変数を宣言します」と書いてるかもしれませんが、それは時代に追いつけてないだけです。
今風なJavaScripterは
- const
- let
を使います。
基本的には再代入不可能なconstを使い、処理の都合でどうしても再代入の必要があるなら断腸の想いでletにしましょう。
ES6 Compatibility tableによるとInternetExplorerでもバージョンが11ならletとconstは対応してます。(for-in, for-ofのループでは使えません。)
「再代入不可能」ということ
上述の通りconstは再代入不可能です。
const a = 1;
a = 2;
こんなことをすればその段階でコンソールにエラーが吐かれます。
勝手に変数が書き換えられないって安心だね!
ただし、エラーが出るのは 変数を丸ごと書き換える時だけです。
どういうことかというと、下記のコードはエラーになりません。
const array = [];
array[0] = 1;
const object = {
a: 1
};
object.a = 2;
この場合、arrayやobjectに対して再代入をしているわけではないので、constの責務の対象外です。
話は逸れますが、配列やオブジェクトは参照というトラップもあって意図しない書き換えが発生しやすいですので常に気を配る必要があります。
やってみた
Vivaldiのコンソールにて
for (var i = 0 ...はもう飽きたろう?
とりあえずletにしておきましょう
const array = [1, 2, 3];
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
}
ループ処理の定番パターンですね。
でも毎回毎回i < array.length
とかarray[i]
とか書くのは正直ダサい感じがします。
そんな時はArray.prototypeのメソッド群を使います。
上記の場合だと
const array = [1, 2, 3];
array.forEach((value) => {
console.log(value);
});
なんだかカッコよくなりましたし、記述量も減ってスッキリします。
コードの記述量はできるだけ少なくしたいところです。
まずはわかりやすいforEachから使ってみて、感覚をつかめてきたらfilterやreduce、mapといったメソッドに手を出してみるといいでしょう。
ただし、reduceやmapに関しては直感的にわかりにくいコードになることもありますので、各々の開発現場の空気を読みながら使いましょう。
ドキュメンテーションコメントを書く
巷には「JavaScriptの変数には型がない」という言説もあるみたいですが、それは錯覚です。
動的型付け言語なのでソース中に現れないだけで内部的には型の概念はあります。
typeof
ってあるじゃろ?
それをソース中に表現できるのがドキュメンテーションコメントです。
例えばこんなファンクション。
function hoge(arg1, arg2) {
return arg1 + arg2;
}
jsでは文字列の連結も+演算子で行うため、このファンクションは引数が数値でも文字列でも動きます。
しかし、実装者としては数値同士の足し算を想定しているかもしれません。
そんな時はこうします。
/**
*
* @param {number} arg1
* @param {number} arg2
* @return {number}
*/
function hoge(arg1, arg2) {
return arg1 + arg2;
}
こうしておけば後から読む人も引数に何を渡すべきか、返り値はどうなっているかを理解できます。
また、引数にnumber以外の変数を渡そうとするとエディタが叱ってくれたりします。
これで実装のミスが減りますね。
JSDocでAPIドキュメントも作れるようになります。
自分で型の定義もできるんだ
jsを書いてるとデータをオブジェクトにまとめて扱うことがよくあります。
自作のオブジェクトだとプロパティ名をエディタが補完してくれなくてタイプミスしたりすることが結構あります。
そんな時のためのコメントもあります。
/**
* @typedef {Object} Person
* @prop {number} age
* @prop {string} gender
*
*/
こうすることで自分で型を定義できます。
当然、自分で作った型をドキュメンテーションコメント内で使うこともできます。
/**
*
* @param {Person} person
*/
function fuga(person) {
}
こうやっておけば引数が先ほど定義したPersonオブジェクトであることがわかるので、エディタがプロパティを補完してくれるようになりますし、各プロパティの型にも気を使ってくれます。
ちゃんとメンテナンスしようね
言わずもがなですが、ドキュメンテーションコメントが実態から乖離すると、 エディタが出すべき警告を出さなかったり、誤ったコード補完をしたりしてえらい目にあいます。
実装内容が変わったらそれに合わせて必ずドキュメンテーションコメントもメンテナンスしましょう。
ていうか、ドキュメンテーションコメントと実装が食い違ってくるとエディタが警告を出すはずです。
「warningやし、まあええか」と思わずにこまめに修正しましょう。
TypeScript使えばいいんじゃね?
はい。
上記のドキュメンテーションコメントのようなことが実装上強制されるので安心感があります。
ただし、導入前にコンパイル環境を作る手間や、多少なりとも言語の学習コストがかかることを考えておきましょう。
基本的に実行しないと不具合がわからないJavaScriptを実行せずにある程度チェックできるのは嬉しいですよね。
私はTypeScriptが大好きです。
あのMicrosoftがこんないい文明を作るなんて...!