1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScript オブジェクトの深くネストされているプロパティに値をセットする setProperty

Last updated at Posted at 2019-01-17

前の記事で、getProperty を作りました。

JavaScript オブジェクトの深くネストされているプロパティに安全にアクセスする getProperty - Qiita
https://qiita.com/standard-software/items/bb044217d0a4b394b8e2

今回は、オブジェクトの深くネストされているプロパティに値をセットする setProperty を作ってみました。

JSでは、値の全書き換えのときに深いネストのプロパティ値を書くのは、そんなに面倒でもなんでもないです。(括弧の対応は少し面倒かも)

ですが、そのオブジェクトの一部の値だけ上書きしたいとか、そのときにその深いネストのところのプロパティが存在したりしなかったり不定とかいう場合に、この setProperty は便利になるでしょう。

ソースコード

function isObject (item) {
  return typeof item === 'object' 
    && item !== null && !Array.isArray(item);
}

function setProperty(object, path, value) {
  if (!isObject(object)) { return; }
  
  const propertyArray = path.split('.');
  for (let i = 0; i <= propertyArray.length - 1; i += 1) {
    if (propertyArray[i] === '' ) { throw new Error('setProperty path'); }
  }

  let result = object;
  for (let i = 0; i <= propertyArray.length - 2; i += 1) {
    if (!isObject(result[propertyArray[i]])) { 
      result[propertyArray[i]] = {};
    }
    result = result[propertyArray[i]];
  }
  result[propertyArray[propertyArray.length - 1]] = value;
}

let testObj1 = {
}
var path = 'a.b';   setProperty(testObj1, path, true); console.log(path, testObj1);
var path = 'a';     setProperty(testObj1, path, true); console.log(path, testObj1);
var path = 'a.b.c'; setProperty(testObj1, path, true); console.log(path, testObj1);
// var path = '';      setProperty(testObj1, path, true); console.log(path, testObj1);
// var path = 'a.';    setProperty(testObj1, path, true); console.log(path, testObj1);
// var path = '.a';    setProperty(testObj1, path, true); console.log(path, testObj1);
var path = 'a.c';   setProperty(testObj1, path, true); console.log(path, testObj1);
var path = 'b';     setProperty(testObj1, path, true); console.log(path, testObj1);
var path = 'b.c';   setProperty(testObj1, path, true); console.log(path, testObj1);

動作確認部分でコメントアウトしているものは例外発生します。プロパティのパスをピリオドで分解したときに空文字が入っているものがあるからです。

もしかしたらプロパティ名に使えない記号文字が入っていたら、なんらかのエラーが出てしまうかもです。もしご存知でしたら教えてください。

そういうパターンも網羅しておいて、プロパティパス部分にこういう文字列を記載すると例外が発生するよ。ということを明示的にテストコードを書くとソースコードの品質があがりますね。

例外が発生するか発生しないかのテストの書き方は次の記事で書いてあるので、ご参考にしてください。

有名なテストフレームワークには多分例外補足テストの処理が搭載されているとは思いますが、大掛かりなものではなくてもソースコピペで十分に例外処理可能なテストフレームワークを作ることもできます。

JavaScriptで世界一簡単なテストフレームワークに例外捕捉機能追加した - Qiita
https://qiita.com/standard-software/items/d4fb99655e17a3a68fcb

1
1
4

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
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?