0
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でネストの深いObjectの初期化を一括で行う

Last updated at Posted at 2025-01-04

やりたいこと

以下のようにネストが深いハッシュの場合、親がundefiendになるので一括で初期化ができない。hash['a']のキーが存在するのか不明な時はめんどくさい。

const hash = {}
hash['a']['b']['c'] = 1

image.png

愚直にやるなら

各階層でキーが存在するかを確認し初期化する必要がある。めんどくさい。

const hash = {}
if(!hash['a']) hash['a'] = {}
if(!hash['a']['b']) hash['a']['b'] = {}
hash['a']['b']['c'] = 1

image.png

Object.assignを使う

@akebi_mh 様からコメント頂きました。Object.assignを使うとワンライナーで実現できます。

const hash = {};
Object.assign(hash, {a:{b:{c:1}}});

image.png

再帰関数を使う

再帰関数を使って初期化していく方法。

この関数には問題があります。後半の「この解決策の問題点」を必ず参照してください

// hashオブジェクトに対して値が無ければ初期化する関数
const setProperty = (obj, ...keys) => {
  const key = keys[0]

  // 次のキーが無ければ終了
  if (keys[1] === undefiend || keys[1] === null) {
    obj[key] = {}
    return
  }

  // プロパティがなければ初期化する
  if (!obj[key]) {
    // 次の値が数値ならば配列にする
    if (Number.isInteger(keys[1])) {
      obj[key] = []
    } else {
      obj[key] = {}
    }
  }

  setProperty(obj[key], ...keys.slice(1))
}

使用例

image.png

解説

三点リーダ

「...」は可変長引数。使用例のようにsetPropertyに複数の引数を与えることができる

Number.isInteger

数値かどうか判定する。'0'は文字列、0は数値と分けてくれる。

.slice(1)

部分配列を返す。1なので、2番目の値以降の部分配列にする

この解決策の問題点

objは引数で取っているが、関数内で更新している。そのためESLintのno-param-reassignが発生してしまう。解決策求ム。

まとめ

あとちょっとでもっといい感じにできそう。良いアイディアお待ちしています。

0
0
1

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?