0
0

More than 1 year has passed since last update.

自作 isEmpty が意外と難しかった件

Last updated at Posted at 2022-08-16

とにかく empty

  • undefined
  • null
  • [](Arrayの要素0)
  • {}(Objectのメンバーなし)
  • ''(空文字)

javascriptには様々な型(値)がありますが、四の五の言わず empty として判定したい!

emptyにしたくない値

  • 0
  • true
  • false

isEmpty(最終版)

util.js
const isEmpty = (obj) => {
  if (-1 < ['number','boolean'].indexOf(typeof obj)) {
    return false
  }

  return (!obj || 0 === Object.keys(obj).length)
}

isEmpty ver.1

util.js
const isEmpty = (obj) => {
  if ('number' === typeof obj) {
    return false
  }

  return (!obj ? true : (0 === Object.keys(obj).length))
}

isEmpty ver.2

util.js
const isEmpty = (obj) => {
  return ('number' === typeof obj ? false : (!obj || 0 === Object.keys(obj).length))
}

ttatsf さんの指摘により修正しました。
三項演算子やORでつなぐのは反則にしています。見にくいですからね。
1回ずつならOKかと

実行結果(isEmpty)

let aaa
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = null
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = []
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = {}
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = undefined
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = ''
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = 0
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))
aaa = '0'
console.log('isEmpty',typeof(aaa),String(aaa),'=', util.isEmpty(aaa))

---

isEmpty undefined undefined = true
isEmpty object null = true
isEmpty object  = true
isEmpty object [object Object] = true
isEmpty undefined undefined = true
isEmpty string  = true
isEmpty number 0 = false
isEmpty string 0 = false

顛末

最初は、return (!obj ? true : (0 === Object.keys(obj).length)) だけでした。
文字列の'0'はfalseになりますが、数値の0がtrueになることに気づかず、数時間溶かしました:sob:
if ('number' === typeof obj) { を付けることで、falseが返るようになりました。
愚直にif分を並べればこういうこともないのでしょうが、短くかっこよく書きたいのがプログラマの性なのでしかたありません。

  • '0'(文字列の0): false(修正前と同じ)
  • 0(数値): true -> false(修正前はtrue)

追記
boolean で期待通りの結果にならないので修正しました

  • true : true -> false(修正前はtrue)
  • false: true -> false(修正前はtrue)

おまけ

toNumber(最終版) 

util.js
const toNumber = (str) => {
  return (isNaN(str) ? 0 : +v)
}

四の五の言わず数値に変換したい!

816423sさんの指摘により修正しました。
自作isEmptyの依存がなくなりました。
+をつけることで数値に変換できるのがキモですね。

trueのとき1、falseのとき0になります。
数値に変換する値にbooleanをいれることはないので問題ないです。

toNumber ver.1

util.js
const toNumber = (str) => {
  return (isEmpty(str) ? 0 : Number(str))
}

実行結果(toNumber)

let aaa
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = null
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = []
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = {}
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = undefined
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = ''
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = 0
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = '0'
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = -1
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))
aaa = '-1'
console.log('toNumber',typeof(aaa),String(aaa),'=', util.toNumber(aaa))

--

toNumber undefined undefined = 0
toNumber object null = 0
toNumber object  = 0
toNumber object [object Object] = 0
toNumber undefined undefined = 0
toNumber string  = 0
toNumber number 0 = 0
toNumber string 0 = 0
toNumber number -1 = -1
toNumber string -1 = -1

ご意見、ご感想

期待通りの結果にならないとか、もっと短くかっこよく書けるとか、気が付いたらコメントお願いします。

編集後記

公開したあとにバグが見つかるとは:sweat:

たかが空判定ですが、大規模なプロジェクトで個々のプログラマのスキル任せにしていたらと思うとゾッとします:fearful:
小規模なプロジェクトでも手戻りすることには変わりないので、ライブラリアンは必須ですね。

0
0
3

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