MENU

【GAS】三項演算子をかっこよく使おう

  • URLをコピーしました!

こんにちは、etau です 🤓

今日は弊社のコーディング ガイドラインで、V8 ランタイム以降、使用を解禁した三項演算子について考えていきます。

聖書「リーダブルコード」には、こう書かれています。

三項演算子・do/while ループ goto などのプログラミング構成要素を使うと、コードが読みにくくなることが多い。代替となるものが必ずあるので、これらは使わないほうがいいだろう。

使うなと書かれているので、V8 ランタイム対応前まではこの教えにしたがい、三項演算子を使うことはありませんでした。

特に困ることも、不自由だと感じることもありませんでした。

目次

そして V8 ランタイムへ

2020 年 2 月、V8 ランタイムに対応した Google Apps Script には大きなアップデートがいくつか盛り込まれていました。

var から let, const への書き換え

GAS の書き方が目に見えて変わった点として、変数宣言時に var を使わなくなったことがあげられます。

MDN Web Docs
var - JavaScript | MDN var 文は関数スコープまたはグローバルスコープの変数を宣言し、任意でそれをある値に初期化します。

では、変数宣言時にはなにを使うのかというと let …ではなく、基本的には定数を宣言するための const を使用します。

MDN Web Docs
let - JavaScript | MDN let 文はブロックスコープのローカル変数を宣言します。任意で値を代入して初期化できます。
MDN Web Docs
const - JavaScript | MDN const 宣言は定数を宣言し、これは let キーワードを使って宣言する変数と同様にブロックスコープを持ちます。定数の値は、再代入(すなわち代入演算子 の使用)による変更...

let については for 文のカウンター変数の初期化時に利用するくらいなのですが、今回テーマとなっている三項演算子を利用しない場合は、以下のような場面でも let の出番があります。

条件分岐後の値の代入

三項演算子を使わないポリシーをつらぬき通そうとすると、イヤな場面に出くわします。

条件分岐後の変数宣言です。

例をあげて説明します。

わずらわしい let

変数 a の値が 0 の場合は、変数 b に 0, そうでない場合には変数 b に 1 を代入するというコードを書きます。

function myFunction() {

  const a = 1;

  if (a === 0) {
    const b = 0;

  } else {
    const b = 1;
  }

  console.log(b);  // ReferenceError: b is not defined

}

const を使って書こうとすると ReferenceError: b is not defined とエラーが表示されます。

V8 ランタイム以前の Rhino ランタイム時でvar を使って宣言していた際には気にしなくてよかったブロック スコープによるエラーです。

このコードを実際に動くものにしようとすると以下のようになります。

function myFunction() {

  const a = 1;
  let b;

  if (a === 0) {
    b = 0;

  } else {
    b = 1;
  }

  console.log(b);  // 1

}

めでたし、めでたし。

…とはならず、変数bに初期値が代入された以降は再代入される可能性がゼロにも関わらず const として宣言できないわずらわしさと危険性が残ります。

正確にはlet b宣言時に、bundefinedとなるので、if…else 文で 0 または 1 が再代入されています

関数を使った解決策

リーダブルコードにしたがって、三項演算子を使わない方法では、別関数からbの値を取得する方法があります。

function myFunction() {

  const a = 1;
  const b = getBValue(a);

  console.log(b);  // 1

}

function getBValue(a) {

  if (a === 0) {
    return 0;

  } else {
    return 1;
  }

}

別関数内でさきほどのコードでbに代入するタイミングで戻り値を設定してあげれば、bconstで宣言することができます…が、コードのボリュームが気になります。

本来であれば、関数にドキュメンテーション コメントを書き足す必要があるため、さらにコードのボリュームは増えます。

三項演算子を使った解決策

やっと本題です。

では、禁じ手としていた三項演算子を使ってコードを書いていきましょう。

function myFunction() {

  const a = 1;
  const b = a === 0 ? 0 : 1;

  console.log(b);  // 1

}

コードのボリュームを考えると、これはもう禁じ手を超えて必殺技のレベルですね。

ここでリーダブルコードの文章を別のページを読んでみると、以下のようにも書かれています。

三項演算子が読みやすくて簡潔な例をあげよう。

time_str += (hour >= 12) ? "pm" : "am";

三項演算子を使わないと以下のようになる。

if (hour >= 12) {
 time_str += "pm";
} else {
 time_str += "am";
}


長くて冗長な感じがする。この場合は三項演算子のほうが読みやすいだろう。

「わかりやすければ三項演算子を使っていいじゃない!(意訳」

まとめ

というわけで弊社のコーディング ガイドラインとして、三項演算子は定数宣言時の二者択一 (if…else 文の代用) の場合に利用するものとし、それ以外の場合にはコードが読みにくくなるので、別の関数を使っていきます。

三項演算子を使う派・使わない派、どちらも喧嘩しないでいきましょう🤓

◯◯ を「使う・使わない」より大事なことはチームでの運用ルール通りにコードを書くということです。

gas-using-conditional-operators_featured-image-1

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

株式会社フロント・ワークス代表取締役の etau です 🤓
へーしゃは「ノンプロ協会」に、個人では「ノンプロ研」所属しています。
趣味は「マンガ」「料理 (特にスパイス カレー)」「お酒」「コーヒー」「コーチング」「マネジメント」です。

目次