備忘録がてらにメモ。
公式ドキュメントを読まないばかりに実装に無駄に時間をかけてしまった自分への戒めとして残しておく。
JavaScriptの[Object.defineProperty()]という関数は、対象のオブジェクトに対して指定したプロパティを定義するという関数となっている。
引数は[obj (対象のオブジェクト)]、[prop (プロパティの名前もしくはシンボル)]、[descriptor (定義)]の3つ。
以下のデモは、空のオブジェクトに対して[hogec]というプロパティに値を[fuga]という文字列を与え、その結果のオブジェクトを取得する。
例: sample1.js
let result = Object.defineProperty({}, "hoge", {"value": "fuga"}); console.log(result.hoge); // consoleでhogeの値を確認
※尚、hogeの値は第3引数の定義内の[value]に対して設定する。
こんな感じのコードを実行するとconsoleには[fuga]と表示される。
問題に遭遇したとき、僕は以下の様なコードを実装していた。
例: sample2.js
let list = [["hoge", "fuga"], ["foo", "bar"]]; let result = list.map(value => Object.defineProperty({}, value[0], {value: value[1]})).reduce((acc, cur) => Object.assign(acc, cur), {}); console.log(result); // 結果は {}
この例では変数listには2次元配列が入っていて、あるルールに従ってこれを1つの連想配列にまとめようとしていた。
何に最後に表示されたconsoleへの出力結果は空のオブジェクト……。
プログラムを少し変更してみても全く変わらない。
[Mozillaの該当ドキュメント]を読んでようやく分かったことは、[descriptor (定義)]には[enumerable]というプロパティがあるということだった。
この[enumerable]が[false]になっていると、[プロパティの列挙]に現れないということらしい。
ここでいう[プロパティの列挙]とは、プロパティの一覧を取得するような処理の中に含まれなくなるということだろう。
そしてこの[enumerable]のデフォルト値は[false]になっている。
サンプルにあった[Object.assign()]はあるオブジェクトのプロパティ全てを別のオブジェクトに全て追加する関数だ。
恐らくだが、このメソッドでのプロパティの追加対象に含まれなくなってしまったのだろう……。
先ほどのコードを正しく書き換えると以下のようになる。
例: sample3.js
let list = [["hoge", "fuga"], ["foo", "bar"]]; let result = list.map(value => Object.defineProperty({}, value[0], {value: value[1], enumerable: true})).reduce((acc, cur) => Object.assign(acc, cur), {}); console.log(result); // {hoge: "fuga", foo: "bar"}
ちなみに[descriptor (定義)]には他にも[configurable]や[writable]なども存在する。
迷ったときは、まずはしっかり仕様の書いてあるドキュメントを読もう。