2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

JavaScriptは演算子をうまく使うことで、値がnullのときの挙動を決めたり、デフォルト値を設定したりすることができます。

本記事では5つのTipsを紹介します。

前提知識

JavaScriptには型が存在していますが、明示的に型を宣言する必要はありません。
これは、実行時にJavaScriptが自動で型を評価してくれるためです。
また、型の変換も自動で行ってくれます。
(この仕様がバグの温床となることもあるのですが…)

中でも、真偽値に変換したときtrueとなる値をtruthyな値、falseとなる値をfalsyな値と呼びます。
以下はその一覧です。

truthy falsy
falsy以外のすべての値 null、undefined、NaN、0、""(空文字)

厳密には上記でfalsyをすべて網羅しているわけではありません。
細かく確認する場合は以下を確認してください。
https://developer.mozilla.org/ja/docs/Glossary/Falsy

truthy、falsyの概念を抑えておいてください。

"||"を使ったデフォルト値の設定

基本の説明

すでにご存知の方が多いかと思いますが、基本から確認します。

||は論理和と呼ばれる演算子です。
一般的には以下のように使います。

if (score > 100 || score < 0) {
  // なにかの処理
}

設定した条件のうち、いずれかが真ならtrue、すべて偽ならfalseとなる演算子であると認識しているかと思います。

しかし、その実態を正確に理解するのであれば

  • 値がtruthyならばその値を返す
  • falsyなら次の値を評価する

という挙動になっています。

どういうことか順を追って確認します。

let score = 110;
if (score > 100 || score < 0) {
    // なにかの処理
}

score = -1;
if (score > 100 || score < 0) {
  // なにかの処理
}

score = 50;
if (score > 100 || score < 0) {
  // なにかの処理
}

scoreが110のとき

score > 100は真になるので、score > 100の評価結果であるtrueが返ってきます。
よって、if()にはtrueが設定されます。

scoreが-1のとき

score > 100は偽になるので、score < 0を評価します。
結果は真であるので、if()にはtrueが設定されます。

scoreが50のとき

score > 100は偽になるので、score < 0を評価します。
こちらも偽になりますが、ほかに評価対象がないのでif()にはfalseが設定されます。

このように、一つずつ順番に評価して、truthyな値があればそれを返す。
なければ最後の値を返す、という挙動になっているのです。

デフォルト値の設定

前置きが長くなりましたが、この挙動を応用すると値が未設定のときにデフォルト値を設定することができます。

userNameという変数に対して、userオブジェクトのnameプロパティを設定したいとします。
またnameプロパティが未設定の場合、デフォルト値としてTaroを設定したいです。

if文を使わずに、以下のように書くことができます。

const userName = user.name || "Taro";

一見すると条件式でもないのに||を使っているのが奇妙に思えますが、先ほど確認した論理和の挙動をなぞれば簡単に理解できます。

user.nameがtruthy(設定済)の場合

user.nameが設定されている場合、trueであるとみなされます。
よって、userNameにはuser.nameが設定されます。
ここでのポイントはあくまでもuser.nameの値がそのまま設定されるということです。
(真偽値に変換後の値が設定されるわけではない)

user.nameがfalsy(未設定)の場合

user.namenullundefinedなど未設定の場合、falseとみなされます。
よって、"Taro"の評価に移ります。
"Taro"はtruthyなのでuserNameには"Taro"が設定されます。

このように、falsyな値の場合には次の値に移ることを利用して、デフォルト値の設定をすることができました。

""(空文字)や、数値の0はfalsyであるため想定外の挙動になる可能性があり、考慮が必要です。

"&&"を使った条件付き処理実行

基本の説明

こちらも基本から確認します。

&&は論理積と呼ばれる演算子です。
一般的には以下のように使います。

if (isAdmin && isAuthenticated ) {
  // なにかの処理
}

設定した条件がすべて真ならtrue、一つでも偽ならfalseとなる演算子であると認識しているかと思います。

しかし、その実態を正確に理解するのであれば

  • 値がfalsyならばその値を返す
  • 値がtruthyなら次の値を評価する

という挙動になっており、||とは逆になっています。

つまり、一つずつ値を順番に評価して、falsyな値があればそれを返す。
なければ最後の値を返します。

条件付き処理の実行

ある条件を満たす場合にのみ、実行したい処理があるとします。
管理者の場合に、機能を有効化する処理を実行する場合を考えてみます。

if文を使わずに、以下のように書くことができます。

isAdmin && enableFunction();

isAdminがtruthy(管理者)の場合

isAdmintrueなので、次の値の評価に移ります。
よって、enableFunctionが実行されます。

isAdminがfalsy(管理者ではない)の場合

isAdminfalseなので、falseがそのまま返ります。
評価はそこで終わるので、enableFunctionの実行には到達しません。

このようにfalsyな値の場合にはそこで評価が止まることを利用して、条件を満たす場合にのみ実行される処理を定義することができました。

"!!"を使った真偽値への変換

基本の説明

!は論理否定と呼ばれる演算子です。
一般的には以下のように使います。

if (!isNaN(num)) {
  // 何らかの処理
}

真偽値を反転させます。trueならfalseに、falseならtrueにします。

真偽値への変換

!は真偽値でない値にも使用できます。
真偽値以外の場合にはtruthyならfalseに、falsyならtrueにします。

そして、!!は否定の否定、二重否定と呼ばれます。
つまり反対の反対なので、truthyならtrueに、falsyならfalseにします。

明示的に値を真偽値に変換したい場合に使用することができます。

const userName = "Taro";
console.log(`${userName}:${!!userName}`); // Taro:true

const num = 100;
console.log(`${num}:${!!num}`); // 100:true

const hoge = undefined;
console.log(`${hoge}:${!!hoge}`); // undefined:false

ただ、これはBoolean関数を使っても同じことができるので、あまり使う機会はないかもしれません。

オプショナルチェーン(?.)の使い方

今まで紹介した3つのtipsは従来のJavaScriptにもともとあった演算子を応用した使い方でした。

ここから紹介する2つのtipsは、比較的新しい書き方になります。

ECMAScript(JavaScriptの仕様のようなもの)の2020バージョン(ES2020)から使える記法です。

概要

オプショナルチェーンは、オブジェクトのプロパティがnullまたはundefinedのときに、エラーにせずundefinedを返します。

オプショナルチェーンを使わない場合

usersオブジェクトのfetchUserInfoメソッドで、指定したnameの情報から住所を取得したいとします。

const userAddress = users.fetchUserInfo(name).address;

もし、fetchUserInfoの結果がnullまたはundefinedの場合、エラーが発生します。
nullまたはundefinedの値に対してaddressプロパティを取得しようとするためです。

値を取得できない可能性がある場合、if文を書いてチェックをする必要があります。

オプショナルチェーンを使う場合

オプショナルチェーンを使うと、値のチェックが不要になります。

const userAddress = users.fetchUserInfo(name)?.address;

?.を使っています。
fetchUserInfoの結果がnullまたはundefinedの場合、addressの取得をせず、undefinedを返却します。

これにより、エラーの発生を防ぐことができます。

Null合体演算子(??)の使い方

こちらも新しい書き方です。

概要

||と似た挙動をします。

  • 値がNull値(nullundefined)なら次の値を評価する
  • 値がNull値でないならばその値を返す

という挙動になります。

||はtruthy、falsyでの判断だったため、""(空文字)や数値の0の場合には考慮が必要でした。
しかし、??はNull値の場合にのみ次の値に移るため、より正確に評価することができます。

Null合体演算子を使わない場合

デフォルト値設定のため、||を使うとすると、意図しない挙動になる場合があります。

// user.nameが""(空文字)の場合でも、デフォルト値が設定される
const userName = user.name || "Taro";
// user.hpが0の場合でも、デフォルト値が設定される
const hitPoint = user.hp || 50;

""(空文字)をそのまま設定したい、0をそのまま設定したい、という場合には||は使えません。

Null合体演算子を使う場合

// user.nameが""(空文字)の場合、デフォルト値が設定される
const userName = user.name ?? "Taro";
// user.hpが0の場合、デフォルト値が設定される
const hitPoint = user.hp ?? 50;

??を使うと、nullまたはundefinedの時のみデフォルト値が設定されるようになるため、""(空文字)や0をそのまま設定することが可能です。

ケースによって使い分けが必要ですが、基本的には??を使うのがよいでしょう。

まとめ

演算子を利用して、便利に処理を書く方法を確認してきました。
うまく使えば、コード量を少なく、簡潔に書くことができます。
しかし、複雑な処理で多用すると、かえって可読性が下がる場合もあるので、状況に応じて使い分けることが重要です。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?