Jak*_*ake 50 javascript object
情况:我有一个包含多个子和子子对象的大对象,其属性包含多种数据类型.出于我们的目的,此对象看起来像这样:
var object = {
aProperty: {
aSetting1: 1,
aSetting2: 2,
aSetting3: 3,
aSetting4: 4,
aSetting5: 5
},
bProperty: {
bSetting1: {
bPropertySubSetting : true
},
bSetting2: "bString"
},
cProperty: {
cSetting: "cString"
}
}
Run Code Online (Sandbox Code Playgroud)
我需要循环遍历此对象并构建显示层次结构的键列表,因此列表最终看起来像这样:
aProperty.aSetting1
aProperty.aSetting2
aProperty.aSetting3
aProperty.aSetting4
aProperty.aSetting5
bProperty.bSetting1.bPropertySubSetting
bProperty.bSetting2
cProperty.cSetting
Run Code Online (Sandbox Code Playgroud)
我有这个函数,它循环遍历对象并吐出密钥,但不是分层次的:
function iterate(obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property]);
}
else {
console.log(property + " " + obj[property]);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有人能告诉我怎么做吗?这里有一个jsfiddle让你搞砸:http://jsfiddle.net/tbynA/
Art*_*oev 103
我为你做了一个FIDDLE.我存储一个stack
字符串,然后输出它,如果该属性是基本类型:
function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
} else {
console.log(property + " " + obj[property]);
$('#output').append($("<div/>").text(stack + '.' + property))
}
}
}
}
iterate(object, '')
Run Code Online (Sandbox Code Playgroud)
最近我收到了很多关于这个问题的赞成票,所以我决定用一些ES2015 +魔术和更多功能风格来改进解决方案.
它可能不太可读,但我喜欢它的样子:)你仍然可以使用上面更简单的解决方案 - 这两者应该完全相同.
const isObject = val =>
typeof val === 'object' && !Array.isArray(val);
const paths = (obj = {}) =>
Object.entries(obj)
.reduce(
(product, [key, value]) =>
isObject(value) ?
product.concat([
[key, paths(value)] // adds [root, [children]] list
]) :
product.concat([key]), // adds [child] list
[]
)
const addDelimiter = (a, b) =>
a ? `${a}.${b}` : b;
const pathToString = ([root, children]) =>
children.map(
child =>
Array.isArray(child) ?
addDelimiter(root, pathToString(child)) :
addDelimiter(root, child)
)
.join('\n');
const input = {
aProperty: {
aSetting1: 1,
aSetting2: 2,
aSetting3: 3,
aSetting4: 4,
aSetting5: 5
},
bProperty: {
bSetting1: {
bPropertySubSetting: true
},
bSetting2: "bString"
},
cProperty: {
cSetting: "cString"
}
};
// ^ implies a "root" level will be ["", paths(input)]
// ideally paths() should return that structure, but I could not figure out how :)
// shows desired output format
console.log(pathToString(["", paths(input)]));
// showcase the resulting data structure
// any object can be recursively represented as a list [objectPropertyName, [...nestedPropertyNames]]
// console.log(paths(input));
Run Code Online (Sandbox Code Playgroud)
小智 53
Artyom Neustroev 的解决方案不适用于复杂的对象,因此这里有一个基于他的想法的可行解决方案:
function propertiesToArray(obj) {
const isObject = val =>
typeof val === 'object' && !Array.isArray(val);
const addDelimiter = (a, b) =>
a ? `${a}.${b}` : b;
const paths = (obj = {}, head = '') => {
return Object.entries(obj)
.reduce((product, [key, value]) =>
{
let fullPath = addDelimiter(head, key)
return isObject(value) ?
product.concat(paths(value, fullPath))
: product.concat(fullPath)
}, []);
}
return paths(obj);
}
Run Code Online (Sandbox Code Playgroud)
Ond*_*dar 15
如果对象在其对象图中有循环,则会遇到问题,例如:
var object = {
aProperty: {
aSetting1: 1
},
};
object.ref = object;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可能希望保留已经完成的对象的引用并将它们从迭代中排除.
如果对象图太深,你也会遇到问题:
var object = {
a: { b: { c: { ... }} }
};
Run Code Online (Sandbox Code Playgroud)
你会得到太多的递归调用错误.两者都可以避免:
function iterate(obj) {
var walked = [];
var stack = [{obj: obj, stack: ''}];
while(stack.length > 0)
{
var item = stack.pop();
var obj = item.obj;
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
var alreadyFound = false;
for(var i = 0; i < walked.length; i++)
{
if (walked[i] === obj[property])
{
alreadyFound = true;
break;
}
}
if (!alreadyFound)
{
walked.push(obj[property]);
stack.push({obj: obj[property], stack: item.stack + '.' + property});
}
}
else
{
console.log(item.stack + '.' + property + "=" + obj[property]);
}
}
}
}
}
iterate(object);
Run Code Online (Sandbox Code Playgroud)
Mat*_*ula 11
https://github.com/hughsk/flat
var flatten = require('flat')
flatten({
key1: {
keyA: 'valueI'
},
key2: {
keyB: 'valueII'
},
key3: { a: { b: { c: 2 } } }
})
// {
// 'key1.keyA': 'valueI',
// 'key2.keyB': 'valueII',
// 'key3.a.b.c': 2
// }
Run Code Online (Sandbox Code Playgroud)
只需循环获取索引.
你不需要递归!
以下函数函数将按从最深到最深的顺序输出条目,并将键的值作为[key, value]
数组输出。
function deepEntries( obj ){
'use-strict';
var allkeys, curKey = '[', len = 0, i = -1, entryK;
function formatKeys( entries ){
entryK = entries.length;
len += entries.length;
while (entryK--)
entries[entryK][0] = curKey+JSON.stringify(entries[entryK][0])+']';
return entries;
}
allkeys = formatKeys( Object.entries(obj) );
while (++i !== len)
if (typeof allkeys[i][1] === 'object' && allkeys[i][1] !== null){
curKey = allkeys[i][0] + '[';
Array.prototype.push.apply(
allkeys,
formatKeys( Object.entries(allkeys[i][1]) )
);
}
return allkeys;
}
Run Code Online (Sandbox Code Playgroud)
然后,要输出您正在寻找的结果类型,只需使用它。
function stringifyEntries(allkeys){
return allkeys.reduce(function(acc, x){
return acc+((acc&&'\n')+x[0])
}, '');
};
Run Code Online (Sandbox Code Playgroud)
如果您对技术位感兴趣,那么这就是它的工作原理。它的工作原理是获取您传递Object.entries
的obj
对象的 并将它们放入数组中allkeys
。然后,从开始allkeys
到结束,如果它发现allkeys
条目值之一是一个对象,则它获取该条目的键为curKey
,并curKey
在将结果数组推送到结束之前为其每个自己的条目键添加前缀allkeys
。然后,它将添加allkeys
到目标长度的条目数添加到目标长度,以便它也将遍历那些新添加的键。
例如,请注意以下事项:
function deepEntries( obj ){
'use-strict';
var allkeys, curKey = '[', len = 0, i = -1, entryK;
function formatKeys( entries ){
entryK = entries.length;
len += entries.length;
while (entryK--)
entries[entryK][0] = curKey+JSON.stringify(entries[entryK][0])+']';
return entries;
}
allkeys = formatKeys( Object.entries(obj) );
while (++i !== len)
if (typeof allkeys[i][1] === 'object' && allkeys[i][1] !== null){
curKey = allkeys[i][0] + '[';
Array.prototype.push.apply(
allkeys,
formatKeys( Object.entries(allkeys[i][1]) )
);
}
return allkeys;
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您只想要属性,而不想要具有属性的对象,那么您可以像这样过滤掉:
deepEntries(object).filter(function(x){return typeof x[1] !== 'object'});
Run Code Online (Sandbox Code Playgroud)
例子:
function stringifyEntries(allkeys){
return allkeys.reduce(function(acc, x){
return acc+((acc&&'\n')+x[0])
}, '');
};
Run Code Online (Sandbox Code Playgroud)
上述解决方案在 IE 中不起作用,而只能在 Edge 中起作用,因为它使用了 Object.entries 函数。如果您需要 IE9+ 支持,那么只需将以下Object.entries
polyfill添加到您的代码中。如果您出于某种原因,实际上确实需要 IE6+ 支持,那么您还需要一个Object.keys
and JSON.stringify
polyfill(此处均未列出,因此请在其他地方找到)。
if (!Object.entries)
Object.entries = function( obj ){
var ownProps = Object.keys( obj ),
i = ownProps.length,
resArray = new Array(i); // preallocate the Array
while (i--)
resArray[i] = [ownProps[i], obj[ownProps[i]]];
return resArray;
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
74276 次 |
最近记录: |