javascript でネストされた連想配列の値を書き換える
実装レシピが浮かびません。
試した(実装中の)コードは記述します。
重要:ESscript5標準(IE11対応)
実現したいことのベタ処理(3階層分)
javascriipt
1// hasOwnPropertyとか除く・・・ 2(function (t, a, b, c, v) { 3 var arr = [a, b, c]; 4 var len = arr.length; 5 var idx = 0; 6 t[arr[0]][arr[1]][arr[2]] = v; 7 return t; 8})({a: {b: {c: '1'}}},'a','b','c','3'); 9// -> console: {a: {b: {c: '3'}}}
実際に書いているコード
javascript
1(function () { 2 function UserException (message, type) { 3 this.name = "UserException"; 4 this.message = message || 'Unexpected error information.'; 5 this.type = type || 'info'; 6 } 7 // 基底セッター&ゲッター 8 Function.prototype.setter = function(member, /*...multilayered, */value) {// -> member, multilayered, valueは実質使用しない....残余引数で対応したい 9 var _obj = this;// -> Class化されたオブジェクトに対応 10 // argumentsを通常配列化 11 var _args = Array.from(arguments); // -> ポリフィルを作成した(IEとか対応) 12 // ↓別の書き方...バグが有った際はこちらを使用すれば対応出来ると思われる。 13 //var _args = Array.prototype.slice.call(arguments); 14 //var _args =[].slice.call(arguments); 15 if (_args.length < 2) { 16 var msg = 'Unexpected execution: there are not enough arguments to execute ' + typeof this + '.'; 17 throw new UserException(msg, 'error'); // -> typeは列挙型にしたい 18 } 19 var changeAssignValue = _args.pop(); // -> _argsから最後の要素を削除し、変数[changeAssignValue]でキャッチする 20 var menberLayeredLength = _args.length; 21 var menberListIndex = 0; 22 var hasMenber = false; 23 var memberName = void(0); 24 while (menberListIndex < menberLayeredLength) { 25 memberName = _args[menberListIndex]; 26 hasMenber = _obj.hasOwnProperty(memberName); // -> _objではダメ。。1階層目以外書き換え不可 27 menberListIndex++; 28 if (hasMenber || menberLayeredLength == menberListIndex+1) {// -> 代入判定の条件は?? 29 // propertyの書き換え 30 Object.defineProperty(_obj, memberName, { value: changeAssignValue, writable: false, enumerable: true }); 31 } else { 32 // nothing 33 } 34 } 35 return _obj; 36 }; 37})()
最終的に出来上がったソースコード
javascriot
1(function () { 2 // 基底セッター 3 Object.prototype.setter = function(member, /*...multilayered, */value) {// -> member, multilayered, valueは実質使用しない....残余引数で対応したい 4 var obj = this;// -> Class化されたオブジェクトに対応 5 // 通常配列化 6 var _args = Array.from(arguments); // -> ポリフィルを作成した(IEとか対応) 7 if (_args.length < 2) { 8 var msg = 'Unexpected execution: there are not enough arguments to execute ' + typeof this + '.'; 9 throw new TypeError(msg); 10 } 11 var changeAssignValue = _args.pop(); // -> _argsから最後の要素を削除し、変数[changeAssignValue]でキャッチする 12 var menberKeyList = getMenberKeyList(_args.flat(1/0)); //-> _argsの中身を単配列化&階層を配列に詰める 13 var menberLayeredLength = menberKeyList.length; 14 var menberListIndex = 0; 15 var hasMenber = false; 16 var memberName = void(0); 17 var _obj = obj; // -> 処理用変数 18 var isLast = false; 19 while (menberListIndex < menberLayeredLength) { 20 isLast = (menberListIndex == menberLayeredLength - 1); 21 memberName = menberKeyList[menberListIndex]; 22 hasMenber = _obj.hasOwnProperty(memberName); // -> objではダメ。。1階層目以外書き換え不可 23 if (hasMenber) { 24 // 最後のindexのみ、propertyの書き換え 25 if (isLast) { 26 Object.defineProperty(_obj, memberName, { value: changeAssignValue, writable: false, enumerable: true }); 27 } 28 _obj = _obj[memberName]; 29 } else { 30 //_obj[memberName] = {};// -> 不用意なメンバー追加は避けた方が良いかも。。。 31 } 32 menberListIndex++; 33 } 34 return obj; 35 }; 36 // 念のため、列挙不可へ書き換え...jQueryUIの処理とバッティングする 37 Object.defineProperty(Object.prototype, 'setter', { value: Object.prototype.setter, writable: false, enumerable: false }); 38 39 // 基底ゲッター 40 Object.prototype.getter = function(member/*, ...multilayered*/){// -> m, multilayeredは実質使用しない....残余引数で対応 41 var obj = this;// -> Class化されたオブジェクトに対応 42 // 通常配列化 43 var _args = Array.from(arguments); // -> ポリフィルを作成した(IEとか対応) 44 if (_args.length < 1) { 45 var msg = 'Unexpected execution: there are not enough arguments to execute ' + typeof this + '.'; 46 throw new TypeError(msg); 47 } 48 var results = null; 49 var menberKeyList = getMenberKeyList(_args.flat(1/0)); //-> _argsの中身を単配列化&階層を配列に詰める 50 var menberLayeredLength = menberKeyList.length; 51 var menberListIndex = 0; 52 var hasMenber = false; 53 var memberName = void(0); 54 var _obj = obj; // -> 処理用変数 55 while (menberListIndex < menberLayeredLength) { 56 isLast = (menberListIndex == menberLayeredLength - 1); 57 memberName = menberKeyList[menberListIndex]; 58 hasMenber = _obj.hasOwnProperty(memberName); // -> objではダメ。。1階層目以外書き換え不可 59 if (hasMenber) { 60 if (isLast) { 61 results = _obj[memberName]; 62 } 63 _obj = _obj[memberName]; 64 } 65 menberListIndex++; 66 } 67 return results; 68 }; 69 // 念のため、列挙不可へ書き換え...jQueryUIの処理とバッティングする 70 Object.defineProperty(Object.prototype, 'getter', { value: Object.prototype.getter, writable: false, enumerable: false }); 71 72 // Array[ポリフィル:IE11対応] 73 Object.defineProperty(Array.prototype, 'flat', { writable: false, enumerable: false, value: (function (){ 74 return (Array.prototype.flat) ? Array.prototype.flat : function (deepth) { 75 var _arr = this; 76 if (isNaN(deepth)) { deepth = 1; } 77 return deepth > 0 ? _arr.reduce(function (acc, val) { 78 return acc.concat(Array.isArray(val) ? val.flatDeep(deepth - 1) : val); 79 }, []) : _arr.slice(); 80 }; 81 })()}); 82 Object.defineProperty(Array, 'from', { writable: false, enumerable: false, value: (function () { 83 return (Array.from) ? Array.from : function (arrayLike/*, mapFn, thisArg */) { 84 var arr = this; 85 var items = Object(arrayLike); 86 if (arrayLike == null) { 87 throw new TypeError('Array.from requires an array-like object - not null or undefined'); 88 } 89 var mapFn = arguments.length > 1 ? arguments[1] : void undefined;// -> 受け取った場合はそれを使う 90 var _this; 91 if (typeof mapFn !== 'undefined') { 92 if (!isCallable(mapFn)) { 93 throw new TypeError('Array.from: when provided, the second argument must be a function'); 94 } 95 if (arguments.length > 2) { 96 _this = arguments[2]; 97 } 98 } 99 var len = toLength(items.length); 100 var Arr = isCallable(arr) ? Object(new arr(len)) : new Array(len); 101 var index = 0; 102 var item; 103 while (index < len) { 104 item = items[index]; 105 if (mapFn) { 106 Arr[index] = typeof _this === 'undefined' ? mapFn(item, index) : mapFn.call(_this, item, index); 107 } else { 108 Arr[index] = item; 109 } 110 index += 1; 111 } 112 Arr.length = len; 113 return Arr; 114 }; 115 // 秘匿関数 116 function isCallable (fn) { 117 return typeof fn === 'function' || Object.prototype.toString.call(fn) === '[object Function]'; 118 } 119 function toInteger (value) { 120 var number = Number(value); 121 if (isNaN(number)) { 122 return 0; 123 } 124 if (number === 0 || !isFinite(number)) { 125 return number; 126 } 127 return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); 128 } 129 function toLength (value) { 130 var maxSafeInteger = Math.pow(2, 53) - 1; // 2^53-1 約9千兆 131 var len = toInteger(value); 132 return Math.min(Math.max(len, 0), maxSafeInteger); 133 }; 134 })()}); 135 136 /** 秘匿関数 */ 137 // 階層を順番に並び替えて返却(単配列化) 138 function getMenberKeyList (obj) { 139 return (!Array.isArray(obj) || obj.length < 1) ? [] : (function (r, o) { 140 var i = 0; 141 while (i < o.length) { 142 var k = o[i]; 143 if (Array.isArray(k)) { k = k.flat(1/0).join('.'); } 144 if (typeof k != 'string') { k = k.toString(); } 145 k = k.split('.'); 146 r = r.concat(k); 147 i++; 148 } 149 return r; 150 })([], obj); 151 } 152 /** under test code */ 153 154 // -> test code setter by type Array. 155 var nestedArray = [[[[[[1,2,3]]]]]]; 156 console.log(nestedArray.setter('0.0.0.0.0.1',5)); // -> [0: [0: [0: [0: [0: [0: 1. 1: 5, 2: 3]]]]]]; 157 // -> test code setter by type Object. 158 var nestedObject = {a: {b: {c: {d: {e: 'hoge', z: 'fuga'}}}}}; 159 console.log(nestedObject.setter('a.b','c',['d','e'],'hogehoge')); // -> {a: {b: {c: {d: {e: 'hogehoge', z: 'fuga'}}}}}; 160 // -> test code setter by type Instance. 161 var _func = function _func () { this.mem1 = {mem2: {mem3: {mem4: {mem5: 'member5', mem6: 'member6'}}}}; }; 162 var nestedPropIns = new _func(); 163 console.log(nestedPropIns.setter('mem1.mem2.mem3.mem4.mem5', '12345')); // -> _func: {mem1: {mem2: {mem3: {mem4: {mem5: '12345', mem6: 'member6'}}}}}; 164 165 // -> test code getter by type Array. 166 console.log(nestedArray.getter('0.0.0.0.0.1'));// -> 5 167 console.log(nestedArray.getter('0.0.0.0.0.4'));// -> null 168 // -> test code getter by type Object. 169 console.log(nestedObject.getter('a.b','c',['d','e'])); // -> hogehoge 170 console.log(nestedObject.getter('a.b','c',['d','j'])); // -> null 171 // -> test code getter by type Instance. 172 console.log(nestedPropIns.getter('mem1.mem2.mem3.mem4.mem5')); // -> 12345 173 console.log(nestedPropIns.getter('mem1.mem2.mem3.mem5.mem5')); // -> null 174})();
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/11 09:55
2020/10/11 13:16
2020/10/11 17:56
2020/10/11 20:56