66234


JavaScript(TypeScript)で、階層構造のObject（Object内にObjectを持つとき）に文字列でアクセスする上手な方法はありますでしょうか。

`Reflect.set()`を使ってみましたが、`key`に含まれる`.`がそのまま文字列の一部として認識されたため、2階層目以降のプロパティにたどり着けませんでした。  
一応、`lodash`を利用することで実現はできたのですが、他に賢い方法がありましたら、ご教示頂けますでしょうか。

以下は試しに動かしたときのメモと結果です。

**memo.txt**

[code]

    interface SampleDetail {
      c: number;
      d: boolean;
    }
    
    interface Sample {
      a: string;
      b: SampleDetail;
    }
    
    //import _ from "lodash";
    // ここから下、実際には適当なクラス内のメソッド内で実行
        const sampleList: Sample[] = [
          { a: "hoge", b: { c: 100, d: true } },
          { a: "fuga", b: { c: 200, d: false } }
        ];
    
        let result = false;
        result = Reflect.set(sampleList[0], "a", "hogehoge"); // ok
        //console.log(sampleList, result);
    
        result = Reflect.set(sampleList[0], "b.c", -100); // 新しく b.c というプロパティが作られてしまう
        //console.log(sampleList, result); // Reflect.setの結果はOKだけど、やりたいことではない
    
        _.set(sampleList[1], "a", "fugafuga");
        //console.log(sampleList);
    
        // lodashを使うとやりたいことを実現できる
        _.set(sampleList[1], "b.c", -200);
        console.log(sampleList);
    
    
[/code]

**4.log**

[code]

    [
      {
        "a": "hogehoge",
        "b": {
          "c": 100,
          "d": true
        },
        "b.c": -100
      },
      {
        "a": "fugafuga",
        "b": {
          "c": -200,
          "d": false
        }
      }
    ]
    
[/code]

ちなみに、質問に至った背景としては、Vue.jsをTypeScriptで書いていてドメインモデルを細かくclass分割したところ、下位コンポーネントの変更をemitして上位コンポーネントからObjectの変更を伝え直すときに、Reflectもしくはlodashが必要になりました。  
下記の記事を参考にしていましたが、vueのバージョンが違ったのかclass-
styleでmixin部分のコードがうまく動かなかったため、emit時に文字列指定で上位コンポーネント内のpropを変更するアイデア部分だけ頂戴しました。

[VueコンポーネントでObjectを双方向バインディングする際の実装 -
Qiita](https://qiita.com/algi_nao/items/adc0b874f100d96e7f46)


CC BY-SA 4.0
2020-03-08T06:37:09.027
63659
2020-05-03T05:57:15.630
2020-03-08T06:55:52.040
3060
38124
question
javascript vue.js typescript
階層構造のObjectを文字列指定で操作したい


[dot-prop](https://www.npmjs.com/package/dot-
prop)の利用、または参考にするのはいかがでしょうか。Objectとはいえ、`__proto__`や`prototype`、`constructor`といったkeyのアクセスも防がないといけないので大変ですが、そのあたりもカバーされています。

補足

  * Reflectはサポートされていないブラウザもありますのでブラウザ制約を確認しておくと良いかもしれません。（[参考](https://caniuse.com/#search=Reflect)）
  * lodashはimportの仕方によってはファイルサイズが大きくなってしまう場合があるので、そのあたりも気をつけると良いかもしれません。


CC BY-SA 4.0
2020-05-03T05:57:15.630
66234
2020-05-03T05:57:15.630
7997
63659
answer