home wiki.fukuchiharuki.me
Menu
#author("2017-12-27T16:48:50+00:00","default:haruki","haruki")
* キーワード [#t66b9647]
- JavaScript
- オブジェクト
- プロパティ

* したいこと [#te139c2c]

 name = "a.b"

で

 data.a.b

を参照したい。また更新したい。

* どうやって [#a7802d0a]

** 参照 [#f9bba347]

 console.log(
   [data, ...name.split('.')].reduce((data, prop) => data[prop])
 )

** 更新 [#dc4fd270]

 ;[data, ...(a => { a.pop(); return a })(name.split('.'))].reduce((data, prop) => data[prop])[(a => a.pop())(name.split('.'))] = value

* ちなみに [#ne421bc1]

** 前提知識 [#sa8ec491]

*** オブジェクトのプロパティは連想配列のようにできる [#fc7b1c8a]

 data.a.b

は

 data[a][b]

と同じ

*** 配列のインデックスは文字列でもよい [#dbc17b81]

 data.c

が文字列なら

 data.c[0]

と

 data.c['0']

は同じに振る舞う。

** 解説 [#d39a1cde]

*** name.split('.') [#t38a8b13]

プロパティの階層を掘るのに「.」を使うことを決めて、プロパティ名の配列を作る。

*** [data, ...names] [#u363d7ae]

dataが先頭にあって、プロパティ名が後に続く配列を作る。

*** .reduce((data, prop) => data[prop]) [#iec5c1d5]

dataから順番にプロパティを掘っていく。先にdataを先頭に乗せたのはそのため。

*** (a => { a.pop(); return a })(names) [#d563ac30]

更新の場合、末端のプロパティのプリミティブ型の値(の、ばっかり)を得てしまっても意味がない。ので、ひとつ手前まで取得するように、プロパティ名の配列(末端を除く)を作成する。

*** (a => a.pop())(name.split('.')) [#jcedc308]

ひとつ手前までのオブジェクトまたは配列まで取得したら最後に末端のプロパティ名またはインデックスを指定する。そこに値を代入する。

*** ; [#ba5be070]

文末に「;」を書かない派だと、前の文によっては誤解が生じるので文を切っておく。

* 参考 [#yf784ea8]
- [[String.prototype.split() - JavaScript | MDN>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split]] 
- [[スプレッド演算子 - JavaScript | MDN>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_operator]]
- [[Array.prototype.reduce() - JavaScript | MDN>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce]]
- [[Array.prototype.pop() - JavaScript | MDN>https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/pop]]