📏

My コーディングルール [javascript 編]

2023/05/07に公開2

初めに

新しい現場に join した時や新しいメンバーが join したときに毎回同じ話をしている気がするので、ポリシーを明確にするために自分が気をつけていることをまとめました。

このままドキュメントに転用できる物を目指していますが、現場のルールが第一なので利用される際はその辺りをうまく改変して使ってください🙏

コーディングルール

constlet を使用する

もはや常識レベルだけど念の為。(なんなら let もほとんど使うことはない)

// Bad
var familyName = 'Suzuki'
var firstName = 'Ichiro'
// Good
const familyName = 'Suzuki'
let firstName = 'Ichiro'

厳密等価(不等価)演算子(===!==)を使う(nullundefined は除く)

予期せぬバグの混入を避けるため厳密等価(不等価)演算子を使いましょう。

// Bad
if (value == 0) {
  return 'value is zero.'
}
// Good
if (value === 0) {
  return 'value is zero.'
}

ただし、null と undefined は多くの場合区別する必要がないので等価(不等価)演算子を使いましょう。

参考: https://typescriptbook.jp/reference/values-types-variables/undefined-vs-null

// Bad
if (value === null) { // もしくは if (value === undefined) {
  return 'value is null.'
}
// Good
if (value == null) { // もしくは if (value == undefined) {
  return 'value is null.'
}

テンプレートリテラルを使う

// Bad
const message = '私の名前は' + familyName + firstName + 'です。'
// Good
const message = `私の名前は${familyName}${firstName}です。`

分割代入を使う

プロパティが存在しない場合はエラーになるので注意。

const person = {
  name: 'Suzuki Ichiro',
  age: '49',
  dob: '1973年10月22日',
}

// Bad
const name = person.name
const age = person.age
const dob = person.dob

// Good
const { name, age, dob } = person

アロー関数を使う

省略できる return やブレース({})も省略しましょう。

// Bad
function computeData(value, addition) {
  return value + addition
}
// Good
const computeData = (value, addition) => value + addition
// 省略しない場合
const computeData = (value, addition) => {
  return value + addition
}

ループ処理は for...of を使う(配列、オブジェクト)

単純なループをしたい場合は for...of を使いましょう。
while についても可読性の観点で不利とされているので使わない。

const dayOfWeeks = ['月', '火', '水', '木', '金', '土', '日']

// Bad(for)
for (let i = 0; i < dayOfWeeks.length - 1; i++) {
  console.log(dayOfWeeks[i])
}
// Bad(for...each)
dayOfWeeks.forEach((dayOfWeek) => {
  console.log(dayOfWeek)
})

// Good
for (const dayOfWeek of dayOfWeeks) {
  console.log(dayOfWeek)
}

オブジェクトのプロパティをループする場合も同様に for...of を使いましょう。
for...infor...of でキーを指定するより Object.values() を使ってループする方がシンプルになります。

const person = {
  name: 'Suzuki Ichiro',
  age: '49',
  dob: '1973年10月22日',
}

// Bad(for...in)
for (const propertyName in person) {
  console.log(person[propertyName])
}
// Bad(for...of)
for (const propertyName of person) {
  console.log(person[propertyName])
}

// Good
for (const item of Object.values(person)) {
  console.log(item)
}
余談

Q. for...inforEach はダメなの?
A. 経験上、 for...in は使い所がなかった。forEach は場合による。

for...in について

  • 配列の場合はインデックス値、オブジェクトの場合はプロパティ名が取得できる。

    ただ配列にインデックス値だけ欲しい場合がないのと、オブジェクトのプロパティ名が欲しい場合は Object.keys() を使った方がシンプル。

    ⇨ つまり使い所がない🤔

  • オブジェクトのプロパティ全が対象になるため予期せぬ値が現れる場合がある。

    参考: https://web-begginer-log.com/js_for/#toc2

    ⇨ あまりこの問題に遭遇することはないと思うけど、そもそも for...in である必要もないので使わなければよいと思う🤔

forEach について

極論どっちでも良いと思っている。ただし理由なく混在するのは避けたいので、どちらを使うか決めておきたい。
for...of はループ途中で return できるが、index が使えない。
実行速度は forEach の方が早いらしい(参考

どちらにしても .map().find() 等を使った方がいいのであまり使うことはない🤔

オブジェクト定義

プロパティと変数名が同じ場合、右辺を省略できるので可能な限り省略。
オブジェクトに設定する変数は最初からそういう設計(変数名)にすると良いかも。

const name = 'Suzuki Ichiro'
const age = '49'
const dob = '1973年10月22日'

// Bad
const person = {
  name: name,
  age: age,
  dob: dob,
}

// Good
const person = {
  name,
  age,
  dob,
}

jsdoc を書く

関数を定義した場合は必ず jsdoc を記載しましょう。
jsdoc を書けない、書くのが難しいと感じた時は関数の機能や目的が的確でない可能性があるので見直しましょう。

余談
  • コード中のコメントは不要派だけど、関数は jsdoc で概要をつかみたいので書いておきたい。
  • 最終的に jsdoc を出力するのが目的ではないので、あまり厳密に記載しなくて良いと思っている。
    ⇨ 多くの場合 Typescript を使うし、型や戻り値は vscode 等で確認できるのでいらないと思っている🤔(現場によっては要求されるかもしれない)
  • vscode 等でマウスオーバーで jsdoc の内容が見れるようになるので積極的に書いていきたい。
/**
 * 小数値をパーセント表記に変換する
 * @param value 変換対象の小数値
 * @returns パーセント表記に変換した文字列
 */
const convertToFormatPercent = (value) => `${value * 100}%`

convertToFormatPercent(0.12) // 12%

終わりに

できればロジック編、Typescript 編、React 編も順次書いていきたい。

Discussion

standard softwarestandard software

マイルールに意見するのもなんなのですが、(曖昧)等価演算子について以前記事書いたことあります。

https://qiita.com/standard-software/items/08597efad6dff1413897

https://jp.quora.com/プログラミングでは-より短いコードで同じ目的を達/answers/195454000?ch=10&share=0f106aa1&srid=7Ndeg

if (value == null) {}
とするなら
if (value === null || value === undefined) {}
と書いたほうが非常に厳密で意図がはっきりしていて読みやすいです。

リンク先にある、nullを使わずundefinedに統一するというのにはとても賛成です。

hiroki-sato-workmanhiroki-sato-workman

仰る通り、null と undefined 両方判定する方が親切ですね!

私個人としては「value == null ということは undefined も対象にしたいんだな」という認識なのですが、ちゃんと両方判定する関数を作ってチェックした方が良いかもですね 🤔