1
0

More than 3 years have passed since last update.

JavaScript の OR演算子で未定義を回避する記述はヤバいのでメモる

Last updated at Posted at 2021-03-31

JavaScript の OR演算子で未定義を回避する記述はヤバいのでメモる

JavaScript 界隈でよくみかける

    const a = _a || 555     // OR演算子で未定義を回避する記述

という記述。なんかヤバい感じがしていたので確認したら案の定だったので、メモしておきます。

推測するに、「引数 _a が undefined だったら、デフォルト値 555 を入れておく」という操作を一行で完結に書いている。
しかし、0'' や当然 false も未定義(undefined)と同じ判定になるので、このコードはヤバい。

確認コード

let html = ''

function arg_undef_test( a1, a2, a3, a4, a5, a6, a7, a8 )
{
    html += `<div>a1: 456 -> ${ a1 || 123 }</div>` // -> 456 OK
    html += `<div>a2: true -> ${ a2 || 123 }</div>` // -> true OK
    html += `<div>a3: false -> ${ a3 || 123 }</div>` // -> 123 NG 期待は false
    html += `<div>a4: -1 -> ${ a4 || 123 }</div>` // -> -1 OK
    html += `<div>a5: 0 -> ${ a5 || 123 }</div>` // -> 123 NG 期待は 0
    html += `<div>a6: null -> ${ a6 || 123 }</div>` // -> 123 NG 期待は null
    html += `<div>a7: '' -> '${ a7 || 123 }'</div>` // -> '123' NG 期待は ''
    html += `<div>a8: undefined -> ${ a8 || 123 }</div>` // -> 123 OK まぁ期待した動きにはなるんだけど、、、

    html += '<hr>'

    const undef = ( _a, _b ) => ( _a === undefined ? _b : _a )

    html += `<div>a1: 456 -> ${ undef( a1, 123 ) }</div>` // -> 456 OK
    html += `<div>a2: true -> ${ undef( a2, 123 ) }</div>` // -> true OK
    html += `<div>a3: false -> ${ undef( a3, 123 ) }</div>` // -> false OK
    html += `<div>a4: -1 -> ${ undef( a4, 123 ) }</div>` // -> -1 OK
    html += `<div>a5: 0 -> ${ undef( a5, 123 ) }</div>` // -> 0 OK
    html += `<div>a6: null -> ${ undef( a6, 123 ) }</div>` // -> null OK
    html += `<div>a7: '' -> '${ undef( a7, 123 ) }'</div>` // -> '' OK
    html += `<div>a8: undefined -> ${ undef( a8, 123 ) }</div>` // -> 123 OK
}  

arg_undef_test(
    456,    // a1
    true,   // a2
    false,  // a3
    -1,     // a4
    0,      // a5
    null,   // a6
    ''      // a7
)

// class member undef test ----
const boo = {
    f1: 456,
    f2: true,
    f3: false,
    f4: -1,
    f5: 0,
    f6: null,
    f7: '',
}

html += '<hr>'

html += `<div>f1: 456 -> ${ boo.f1 || 123 }</div>` // -> 456 OK
html += `<div>f2: true -> ${ boo.f2 || 123 }</div>` // -> true OK
html += `<div>f3: false -> ${ boo.f3 || 123 }</div>` // -> 123 NG 期待は false
html += `<div>f4: -1 -> ${ boo.f4 || 123 }</div>` // -> -1 OK
html += `<div>f5: 0 -> ${ boo.f5 || 123 }</div>` // -> 123 NG 期待は 0
html += `<div>f6: null -> ${ boo.f6 || 123 }</div>` // -> 123 NG 期待は null
html += `<div>f7: '' -> '${ boo.f7 || 123 }'</div>` // -> '123' NG 期待は ''
html += `<div>f8: undefined -> ${ boo.f8 || 123 }</div>` // -> 123 OK

html += '<hr>'

const undef = ( _a, _b ) => ( _a === undefined ? _b : _a )

html += `<div>f1: 456 -> ${ undef( boo.f1, 123 ) }</div>` // -> 456 OK
html += `<div>f2: true -> ${ undef( boo.f2, 123 ) }</div>` // -> true OK
html += `<div>f3: false -> ${ undef( boo.f3, 123 ) }</div>` // -> false OK
html += `<div>f4: -1 -> ${ undef( boo.f4, 123 ) }</div>` // -> -1 OK
html += `<div>f5: 0 -> ${ undef( boo.f5, 123 ) }</div>` // -> 0 OK
html += `<div>f6: null -> ${ undef( boo.f6, 123 ) }</div>` // -> null OK
html += `<div>f7: '' -> '${ undef( boo.f7, 123 ) }'</div>` // -> '' OK
html += `<div>f8: undefined -> ${ undef( boo.f8, 123 ) }</div>` // -> 123 OK

document.body.innerHTML = html

実行結果

解説

まとめ

面倒でも、未定義を確認するコードを一行。

const undef = ( _a, _b ) => ( _a === undefined ? _b : _a )

書こうよ。>おれもな

追記 Null合体(??) を教えていただきました🙏

||?? に置き換えればよいという、、、スグレモノ。なぜ、いままで知らなかったのか。>反省

let html = ''

function arg_undef_test( a1, a2, a3, a4, a5, a6, a7, a8 )
{
    html += `<div>a1: 456 -> ${ a1 || 123 }</div>` // -> 456 OK
    html += `<div>a2: true -> ${ a2 || 123 }</div>` // -> true OK
    html += `<div>a3: false -> ${ a3 || 123 }</div>` // -> 123 NG 期待は false
    html += `<div>a4: -1 -> ${ a4 || 123 }</div>` // -> -1 OK
    html += `<div>a5: 0 -> ${ a5 || 123 }</div>` // -> 123 NG 期待は 0
    html += `<div>a6: null -> ${ a6 || 123 }</div>` // -> 123 NG 期待は null
    html += `<div>a7: '' -> '${ a7 || 123 }'</div>` // -> '123' NG 期待は ''
    html += `<div>a8: undefined -> ${ a8 || 123 }</div>` // -> 123 OK まぁ期待した動きにはなるんだけど、、、

    html += '<hr>'

    html += `<div>a1: 456 -> ${ a1 ?? 123 }</div>` // -> 456 OK
    html += `<div>a2: true -> ${ a2 ?? 123 }</div>` // -> true OK
    html += `<div>a3: false -> ${ a3 ?? 123 }</div>` // -> false OK
    html += `<div>a4: -1 -> ${ a4 ?? 123 }</div>` // -> -1 OK
    html += `<div>a5: 0 -> ${ a5 ?? 123 }</div>` // -> 0 OK
    html += `<div>a6: null -> ${ a6 ?? 123 }</div>` // -> 123 NGってか ?? は期待どおり OK
    html += `<div>a7: '' -> '${ a7 ?? 123 }'</div>` // -> '' OK
    html += `<div>a8: undefined -> ${ a8 ?? 123 }</div>` // -> 123 OK
}  

arg_undef_test(
    456,    // a1
    true,   // a2
    false,  // a3
    -1,     // a4
    0,      // a5
    null,   // a6
    ''      // a7
)

// class member undef test ----
const boo = {
    f1: 456,
    f2: true,
    f3: false,
    f4: -1,
    f5: 0,
    f6: null,
    f7: '',
}

html += '<hr>'

html += `<div>f1: 456 -> ${ boo.f1 || 123 }</div>` // -> 456 OK
html += `<div>f2: true -> ${ boo.f2 || 123 }</div>` // -> true OK
html += `<div>f3: false -> ${ boo.f3 || 123 }</div>` // -> 123 NG 期待は false
html += `<div>f4: -1 -> ${ boo.f4 || 123 }</div>` // -> -1 OK
html += `<div>f5: 0 -> ${ boo.f5 || 123 }</div>` // -> 123 NG 期待は 0
html += `<div>f6: null -> ${ boo.f6 || 123 }</div>` // -> 123 NG 期待は null
html += `<div>f7: '' -> '${ boo.f7 || 123 }'</div>` // -> '123' NG 期待は ''
html += `<div>f8: undefined -> ${ boo.f8 || 123 }</div>` // -> 123 OK

html += '<hr>'

html += `<div>f1: 456 -> ${ boo.f1 ?? 123 }</div>` // -> 456 OK
html += `<div>f2: true -> ${ boo.f2 ?? 123 }</div>` // -> true OK
html += `<div>f3: false -> ${ boo.f3 ?? 123 }</div>` // -> false OK
html += `<div>f4: -1 -> ${ boo.f4 ?? 123 }</div>` // -> -1 OK
html += `<div>f5: 0 -> ${ boo.f5 ?? 123 }</div>` // -> 0 OK
html += `<div>f6: null -> ${ boo.f6 ?? 123 }</div>` // -> 123 OK いいね
html += `<div>f7: '' -> '${ boo.f7 ?? 123 }'</div>` // -> '' OK
html += `<div>f8: undefined -> ${ boo.f8 ?? 123 }</div>` // -> 123 OK

document.body.innerHTML = html

(あらら、 Qiita のシンタックスハイライトが ?? に追従できていない感)

で、「オプショナルチェイニング演算子 (?.) 」なるものを知る。なんじゃこりゃー。あとで調べる。

1
0
2

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
1
0