
こんにちは、etau です 🤓
今日は弊社のコーディング ガイドラインで、V8 ランタイム以降、使用を解禁した三項演算子について考えていきます。
聖書「リーダブルコード」には、こう書かれています。

使うなと書かれているので、V8 ランタイム対応前まではこの教えにしたがい、三項演算子を使うことはありませんでした。
特に困ることも、不自由だと感じることもありませんでした。
そして V8 ランタイムへ
2020 年 2 月、V8 ランタイムに対応した Google Apps Script には大きなアップデートがいくつか盛り込まれていました。
var から let, const への書き換え
GAS の書き方が目に見えて変わった点として、変数宣言時に var を使わなくなったことがあげられます。
では、変数宣言時にはなにを使うのかというと let …ではなく、基本的には定数を宣言するための const を使用します。

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
宣言時に、b
はundefined
となるので、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
に代入するタイミングで戻り値を設定してあげれば、b
はconst
で宣言することができます…が、コードのボリュームが気になります。
本来であれば、関数にドキュメンテーション コメントを書き足す必要があるため、さらにコードのボリュームは増えます。

三項演算子を使った解決策
やっと本題です。
では、禁じ手としていた三項演算子を使ってコードを書いていきましょう。
function myFunction() { const a = 1; const b = a === 0 ? 0 : 1; console.log(b); // 1 }
コードのボリュームを考えると、これはもう禁じ手を超えて必殺技のレベルですね。
ここでリーダブルコードの文章を別のページを読んでみると、以下のようにも書かれています。
「わかりやすければ三項演算子を使っていいじゃない!(意訳」
まとめ
というわけで弊社のコーディング ガイドラインとして、三項演算子は定数宣言時の二者択一 (if…else 文の代用) の場合に利用するものとし、それ以外の場合にはコードが読みにくくなるので、別の関数を使っていきます。
三項演算子を使う派・使わない派、どちらも喧嘩しないでいきましょう🤓
◯◯ を「使う・使わない」より大事なことはチームでの運用ルール通りにコードを書くということです。