Help us understand the problem. What is going on with this article?

JavaScript オブジェクトの深くネストされているプロパティに安全にアクセスする getProperty

もう何番煎じかわかりませんが、深いネストにアクセスするための関数を作ってみました。

ソースコード

function getProperty(object, propertyPath) {
  if (!object) { return undefined }

  let result = object;
  const propertyArray = propertyPath.split('.');
  for (let i = 0; i <= propertyArray.length - 1; i += 1) {
    if (propertyArray[i] === '' ) { return undefined; }
    if (typeof result[propertyArray[i]] === 'undefined') { return undefined; }
    result = result[propertyArray[i]];
  }
  return result;
}

let testObj1 = {
  a: {
    b: {
      c: false
    }
  }
}

var path = 'a';       console.log( getProperty(testObj1, path) );
var path = 'a.b';     console.log( getProperty(testObj1, path) );
var path = 'a.b.c';   console.log( getProperty(testObj1, path) );
var path = 'a.b.c.d'; console.log( getProperty(testObj1, path) );
var path = 'a.b.b';   console.log( getProperty(testObj1, path) );
var path = '';        console.log( getProperty(testObj1, path) );
var path = 'a.';      console.log( getProperty(testObj1, path) );
var path = '.a';      console.log( getProperty(testObj1, path) );
var path = 'a.c';     console.log( getProperty(testObj1, path) );
var path = 'b';       console.log( getProperty(testObj1, path) );
var path = 'b.c';     console.log( getProperty(testObj1, path) );

値が取得できる場合は値を取得、できない場合は、undefined が返ります。例外は発生しないので、安心して深いところにあるプロパティ値を取得することができます。

こちらの情報によると、lodashにはここで紹介したgetPropertyと同じ機能のget関数があるようですので、普通はそれを使うと思います。この記事のコードは、何かのご参考程度にしてください。

【JavaScript】ネストされたObjectのキーが存在するかチェックする | Black Everyday Company
https://kuroeveryday.blogspot.com/2016/07/key-exists-in-nested-object.html

Google検索してバグがあるものが見つかります。

Googleにヒットする、いくつかのサイトのコードにはバグがあるのでご注意ください。

魔術 黒文字列キーでネストされたJavaScriptオブジェクトにアクセスする - CODE Q&A 問題解決
https://code.i-harness.com/ja-jp/q/630d47

JavaScript 黒魔術 - 文字列をキーとしてネストしたプロパティにアクセスする | phiary
http://phiary.me/js-black-magic-nested-property-accessor/

これらのところで「reduce x && x[y]」と記載されている方法は、obj.a.b.c = false の場合に、「obj, 'a.b.c.d'」などでアクセスすると undefined ではなく false が戻るようになってしまっているバグがあるようです。

reduce という扱いが少しむずかしいループ系の関数や、それと組み合わせてのand演算子の戻り値というやり方で書いたために、ミスになってしまったのでしょう。

JSでなるべくショートハンドで書くことがよいとされる間違った文化がある。

ここが一番言いたいことなのですが、

JSでは、ショートハンドといわれる短い形式で記述するのが流行りでもあり、「記述量が少ない=バグが出にくい」と勘違いしている中途半端な開発者の人を時々見かけます。これは、そういうのが裏目に出たという典型例の一つになるのかもしれません。

ショートハンドなand演算子の戻り値は、悪い慣習です。使う価値はまずなくバグの温床です。

また、reduce, map などでは ループ時の内部値を console.log 出力もできなかったり 開始 終了処理なども記載しにくく改良もしにくいので少し気をつけて使うのがいいでしょう。

他の人のコードを動作確認する時やリファクタリングが面倒です。

「reduce や map 使うな for 使え」という主張はしませんが、 「for はダサいし古いから老害しか使わない。最新のできるエンジニアは reduce や map 使いましょう、かっこいいから。」と盲目的に信じている開発者は実際にいます。私からすると愚かな中途パンパな技術しか持ち合わせてないんだな、と感じます。

自分が経験したのは、ベンチャーで時流に乗って儲けている状況のことを自分の実力と勘違いしちゃっている若造のエンジニアにいましたね。結構な率で若者は若さゆえの過ちをそういう形でするんだよな。と興味深く観察させてもらいました。

reduce とか map とか Array.forEach とかは、結局のところ for ループを抽象化した程度のもので、その抽象化されていることによって時には、役に立たない場合があるということです。reduceの動きは詳細まで把握しにくいので for ループで書いておいた方が内部値を確認しやすかったり、仕様変更時に break や continue でいろいろ対応できるというメリットもあるものなのです。

プログラムは書くよりも読むほうが難しい、という格言を知ってほしいものです。

テストコード

この記事では、テストコードまで書きませんでしたが、console.log での出力は行いました。

よりよくやるなら、テストコード込みで開発してしまうのが、より望ましいでしょう。

手前味噌ですが、これらの記事を参考にしてみてください。

JavaScriptで(そしてどんな言語でも同じで)世界一簡単なテストフレームワークを作って使おう - Qiita
https://qiita.com/standard-software/items/559d871794bfa38651f4

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

ライブラリ

最近はこちらのライブラリを開発しています。

standard-software/partsjs: JavaScript Code Parts TypeSafe Library Compatible with any js platform
https://github.com/standard-software/partsjs

getProperty
https://github.com/standard-software/partsjs/blob/v5.3.3/source_code/object/object_common.js#L99

getProperty を同時複数で行える inProperty
https://github.com/standard-software/partsjs/blob/v5.3.3/source_code/object/inProperty.js#L51

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした