访问/处理(嵌套)对象,数组或JSON

Fel*_*ing 811 javascript arrays nested object data-manipulation

我有一个包含对象和数组的嵌套数据结构.如何提取信息,即访问特定或多个值(或键)?

例如:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};
Run Code Online (Sandbox Code Playgroud)

我怎么能访问name第二项items

Fel*_*ing 1088

预赛

JavaScript只有一种数据类型,可以包含多个值:Object.一个阵列是对象的一种特殊形式.

(普通)对象具有形式

{key: value, key: value, ...}
Run Code Online (Sandbox Code Playgroud)

数组有形式

[value, value, ...]
Run Code Online (Sandbox Code Playgroud)

数组和对象都暴露了一个key -> value结构.数组中的键必须是数字,而任何字符串都可以用作对象中的键.键值对也称为"属性".

可以使用点表示法访问属性

const value = obj.someProperty;
Run Code Online (Sandbox Code Playgroud)

括号表示法,如果属性名称不是有效的JavaScript 标识符名称[spec],或者名称是变量的值:

// the space is not a valid character in identifier names
const value = obj["some Property"];

// property name as variable
const name = "some Property";
const value = obj[name];
Run Code Online (Sandbox Code Playgroud)

因此,只能使用括号表示法访问数组元素:

const value = arr[5]; // arr.5 would be a syntax error

// property name / index as variable
const x = 5;
const value = arr[x];
Run Code Online (Sandbox Code Playgroud)

等等...... JSON怎么样?

JSON是数据的文本表示,就像XML,YAML,CSV等.要处理这些数据,首先必须将其转换为JavaScript数据类型,即数组和对象(以及如何使用这些数据进行解释).JavaScript中的Parse JSON问题解释了如何解析JSON .

进一步阅读材料

如何访问数组和对象是JavaScript的基本知识,因此建议您阅读MDN JavaScript指南,尤其是部分



访问嵌套数据结构

嵌套数据结构是引用其他数组或对象的数组或对象,即其值是数组或对象.可以通过连续应用点或括号表示来访问这样的结构.

这是一个例子:

const data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};
Run Code Online (Sandbox Code Playgroud)

假设我们想要访问name第二个项目.

以下是我们如何逐步完成的工作:

我们可以看到data一个对象,因此我们可以使用点表示法访问其属性.该items物业访问如下:

data.items
Run Code Online (Sandbox Code Playgroud)

值是一个数组,要访问它的第二个元素,我们必须使用括号表示法:

data.items[1]
Run Code Online (Sandbox Code Playgroud)

此值是一个对象,我们再次使用点表示法来访问该name属性.所以我们最终得到:

const item_name = data.items[1].name;
Run Code Online (Sandbox Code Playgroud)

或者,我们可以为任何属性使用括号表示法,特别是如果名称包含使点符号用法无效的字符:

const item_name = data['items'][1]['name'];
Run Code Online (Sandbox Code Playgroud)

我正在尝试访问一处房产,但我只undefined回来了?

大多数情况下,当您获得时undefined,对象/数组根本没有具有该名称的属性.

const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
Run Code Online (Sandbox Code Playgroud)

使用console.logconsole.dir检查对象/数组的结构.您尝试访问的属性实际上可能是在嵌套对象/数组上定义的.

console.log(foo.bar.baz); // 42
Run Code Online (Sandbox Code Playgroud)

如果属性名称是动态的,我事先不知道怎么办?

如果属性名称未知或我们要访问的对象的所有属性/数组元素,我们可以使用for...in [MDN]环为目的和for [MDN]环对数组遍历所有属性/元素.

对象

要遍历所有属性data,我们可以像这样迭代对象:

for (const prop in data) {
    // `prop` contains the name of each property, i.e. `'code'` or `'items'`
    // consequently, `data[prop]` refers to the value of each property, i.e.
    // either `42` or the array
}
Run Code Online (Sandbox Code Playgroud)

根据对象的来源(以及您想要做什么),您可能必须在每次迭代中测试该属性是否真的是对象的属性,或者它是继承的属性.您可以使用Object#hasOwnProperty [MDN]执行此操作.

作为for...inwith的替代方法hasOwnProperty,您可以使用Object.keys [MDN]获取属性名称数组:

Object.keys(data).forEach(function(prop) {
  // `prop` is the property name
  // `data[prop]` is the property value
});
Run Code Online (Sandbox Code Playgroud)

数组

要遍历data.items 数组的所有元素,我们使用for循环:

for(let i = 0, l = data.items.length; i < l; i++) {
    // `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
    // we can access the next element in the array with `data.items[i]`, example:
    // 
    // var obj = data.items[i];
    // 
    // Since each element is an object (in our example),
    // we can now access the objects properties with `obj.id` and `obj.name`. 
    // We could also use `data.items[i].id`.
}
Run Code Online (Sandbox Code Playgroud)

也可以使用for...in迭代数组,但有理由为什么应该避免这种情况:为什么'for(列表中的var项)'与数组在JavaScript中被认为是不好的做法?.

随着ECMAScript 5对浏览器的支持不断增加,数组方法forEach [MDN]也成为一个有趣的选择:

data.items.forEach(function(value, index, array) {
    // The callback is executed for each element in the array.
    // `value` is the element itself (equivalent to `array[index]`)
    // `index` will be the index of the element in the array
    // `array` is a reference to the array itself (i.e. `data.items` in this case)
}); 
Run Code Online (Sandbox Code Playgroud)

在支持ES2015(ES6)的环境中,您还可以使用[MDN]循环,它不仅适用于数组,而且适用于任何可迭代:for...of

for (const item of data.items) {
   // `item` is the array element, **not** the index
}
Run Code Online (Sandbox Code Playgroud)

在每次迭代中,for...of直接给我们迭代的下一个元素,没有"索引"来访问或使用.


如果我不知道数据结构的"深度"怎么办?

除了未知密钥之外,数据结构的"深度"(即它有多少嵌套对象)也可能是未知的.如何访问深层嵌套属性通常取决于确切的数据结构.

但是,如果数据结构包含重复模式,例如二叉树的表示,则解决方案通常包括以递归方式 [Wikipedia]访问数据结构的每个级别.

以下是获取二叉树的第一个叶节点的示例:

function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild); // <- recursive call
    }
    else if (node.rightChild) {
        return getLeaf(node.rightChild); // <- recursive call
    }
    else { // node must be a leaf node
        return node;
    }
}

const first_leaf = getLeaf(root);
Run Code Online (Sandbox Code Playgroud)

const root = {
    leftChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 42
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 5
        }
    },
    rightChild: {
        leftChild: {
            leftChild: null,
            rightChild: null,
            data: 6
        },
        rightChild: {
            leftChild: null,
            rightChild: null,
            data: 7
        }
    }
};
function getLeaf(node) {
    if (node.leftChild) {
        return getLeaf(node.leftChild);
    } else if (node.rightChild) {
        return getLeaf(node.rightChild);
    } else { // node must be a leaf node
        return node;
    }
}

console.log(getLeaf(root).data);
Run Code Online (Sandbox Code Playgroud)

访问具有未知密钥和深度的嵌套数据结构的更通用方法是测试值的类型并相应地采取行动.

下面是一个将嵌套数据结构中的所有原始值添加到数组中的示例(假设它不包含任何函数).如果我们遇到一个对象(或数组),我们只需toArray再次调用该值(递归调用).

function toArray(obj) {
    const result = [];
    for (const prop in obj) {
        const value = obj[prop];
        if (typeof value === 'object') {
            result.push(toArray(value)); // <- recursive call
        }
        else {
            result.push(value);
        }
    }
    return result;
}
Run Code Online (Sandbox Code Playgroud)

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};


function toArray(obj) {
  const result = [];
  for (const prop in obj) {
    const value = obj[prop];
    if (typeof value === 'object') {
      result.push(toArray(value));
    } else {
      result.push(value);
    }
  }
  return result;
}

console.log(toArray(data));
Run Code Online (Sandbox Code Playgroud)



助手

由于复杂对象或数组的结构不一定明显,我们可以检查每一步的值来决定如何进一步移动.console.log [MDN]console.dir [MDN]帮助我们这样做.例如(Chrome控制台的输出):

> console.log(data.items)
 [ Object, Object ]
Run Code Online (Sandbox Code Playgroud)

在这里,我们看到这data.items是一个包含两个元素的数组,这两个元素都是对象.在Chrome控制台中,甚至可以立即展开和检查对象.

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object
Run Code Online (Sandbox Code Playgroud)

这告诉我们这data.items[1]是一个对象,在扩展它之后,我们看到它有三个属性id,name__proto__.后者是用于对象原型链的内部属性.但是,原型链和继承超出了这个答案的范围.

  • 这里链接的一些内容实际上是在jQuery中询问如何做到这一点,公平地说这里简化了1或2个事情.不知道是否要更多地使用这个或者单独回答 - 这里所涉及的基础知识是什么是一个对象什么是数组通常是真正被问到的...... (3认同)
  • 这是我在Stack Overflow上见过的最深入的答案-它回答了我的问题!谢谢! (2认同)
  • 这一页让我了解了 ARRAY 和 OBJ 之间的区别 (2认同)

小智 68

您可以通过这种方式访问​​它

data.items[1].name
Run Code Online (Sandbox Code Playgroud)

要么

data["items"][1]["name"]
Run Code Online (Sandbox Code Playgroud)

两种方式都是平等的.

  • 首先是更直观,更易读和更短的;)我更喜欢仅在属性名称为变量时使用方括号属性语法。 (3认同)

hol*_*ple 32

如果你试图item通过id或者通过或name不知道它在数组中的位置来访问示例结构,最简单的方法是使用underscore.js库:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

_.find(data.items, function(item) {
  return item.id === 2;
});
// Object {id: 2, name: "bar"}
Run Code Online (Sandbox Code Playgroud)

根据我的经验,使用更高阶函数而不是foror for..in循环会导致代码更容易推理,因此更易于维护.

只需2美分.


Tra*_*s J 21

有时,可能需要使用字符串访问嵌套对象.例如,简单的方法是第一级

var obj = { hello: "world" };
var key = "hello";
alert(obj[key]);//world
Run Code Online (Sandbox Code Playgroud)

但复杂的json往往不是这种情况.随着json变得越来越复杂,在json中查找值的方法也变得复杂.用于导航json的递归方法是最好的,并且如何利用该递归取决于所搜索的数据的类型.如果涉及条件语句,json搜索可以是一个很好的工具.

如果正在访问的属性已知,但路径很复杂,例如在此对象中

var obj = {
 arr: [
    { id: 1, name: "larry" },    
    { id: 2, name: "curly" },
    { id: 3, name: "moe" }
 ]
};
Run Code Online (Sandbox Code Playgroud)

并且您知道您希望在对象中获得数组的第一个结果,也许您想要使用它

var moe = obj["arr[0].name"];
Run Code Online (Sandbox Code Playgroud)

但是,这将导致异常,因为没有具有该名称的对象的属性.能够使用它的解决方案是展平对象的树方面.这可以递归地完成.

function flatten(obj){
 var root = {};
 (function tree(obj, index){
   var suffix = toString.call(obj) == "[object Array]" ? "]" : "";
   for(var key in obj){
    if(!obj.hasOwnProperty(key))continue;
    root[index+key+suffix] = obj[key];
    if( toString.call(obj[key]) == "[object Array]" )tree(obj[key],index+key+suffix+"[");
    if( toString.call(obj[key]) == "[object Object]" )tree(obj[key],index+key+suffix+".");   
   }
 })(obj,"");
 return root;
}
Run Code Online (Sandbox Code Playgroud)

现在,复杂的对象可以展平

var obj = previous definition;
var flat = flatten(obj);
var moe = flat["arr[0].name"];//moe
Run Code Online (Sandbox Code Playgroud)

以下是使用jsFiddle Demo此方法的一种方法.


Mic*_*ski 21

对象和数组有许多内置方法可以帮助您处理数据.

注意:在许多示例中,我使用的是箭头函数.它们与函数表达式类似,但它们以this词汇方式绑定值.

Object.keys(),Object.values()(ES 2017)和Object.entries()(ES 2017)

Object.keys()返回一个对象键Object.values()的数组,返回一个对象值Object.entries()的数组,并以一种格式返回一个对象键和相应值的数组[key, value].

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

console.log(Object.keys(obj)) // ['a', 'b', 'c']
console.log(Object.values(obj)) // [1, 2, 3]
console.log(Object.entries(obj)) // [['a', 1], ['b', 2], ['c', 3]]
Run Code Online (Sandbox Code Playgroud)

Object.entries() 具有for-of循环和解构赋值

const obj = {
  a: 1
 ,b: 2
 ,c: 3
}

for (const [key, value] of Object.entries(obj)) {
  console.log(`key: ${key}, value: ${value}`)
}
Run Code Online (Sandbox Code Playgroud)

Object.entries()使用for-of循环解构赋值迭代结果非常方便.

For-of循环允许您迭代数组元素.语法是for (const element of array)(我们可以constvar或替换let,但const如果我们不打算修改,最好使用element).

解构赋值允许您从数组或对象中提取值并将它们分配给变量.在这种情况下const [key, value]意味着我们不是将[key, value]数组赋给,而是将该数组element的第一个元素分配给key第二个元素value.它相当于:

for (const element of Object.entries(obj)) {
  const key = element[0]
       ,value = element[1]
}
Run Code Online (Sandbox Code Playgroud)

如您所见,解构使这更简单.

Array.prototype.every()Array.prototype.some()

如果指定的回调函数为数组的每个元素every()返回,true则该方法返回.该方法返回,如果指定的回调函数将返回对一些(至少一个)元素.truesome()truetrue

const arr = [1, 2, 3]

// true, because every element is greater than 0
console.log(arr.every(x => x > 0))
// false, because 3^2 is greater than 5
console.log(arr.every(x => Math.pow(x, 2) < 5))
// true, because 2 is even (the remainder from dividing by 2 is 0)
console.log(arr.some(x => x % 2 === 0))
// false, because none of the elements is equal to 5
console.log(arr.some(x => x === 5))
Run Code Online (Sandbox Code Playgroud)

Array.prototype.find()Array.prototype.filter()

这些find()方法返回满足提供的回调函数的第一个元素.该filter()方法返回满足所提供的回调函数的所有元素的数组.

const arr = [1, 2, 3]

// 2, because 2^2 !== 2
console.log(arr.find(x => x !== Math.pow(x, 2)))
// 1, because it's the first element
console.log(arr.find(x => true))
// undefined, because none of the elements equals 7
console.log(arr.find(x => x === 7))

// [2, 3], because these elements are greater than 1
console.log(arr.filter(x => x > 1))
// [1, 2, 3], because the function returns true for all elements
console.log(arr.filter(x => true))
// [], because none of the elements equals neither 6 nor 7
console.log(arr.filter(x => x === 6 || x === 7))
Run Code Online (Sandbox Code Playgroud)

Array.prototype.map()

map()方法返回一个数组,其中包含在数组元素上调用提供的回调函数的结果.

const arr = [1, 2, 3]

console.log(arr.map(x => x + 1)) // [2, 3, 4]
console.log(arr.map(x => String.fromCharCode(96 + x))) // ['a', 'b', 'c']
console.log(arr.map(x => x)) // [1, 2, 3] (no-op)
console.log(arr.map(x => Math.pow(x, 2))) // [1, 4, 9]
console.log(arr.map(String)) // ['1', '2', '3']
Run Code Online (Sandbox Code Playgroud)

Array.prototype.reduce()

reduce()方法通过使用两个元素调用提供的回调函数将数组减少为单个值.

const arr = [1, 2, 3]

// Sum of array elements.
console.log(arr.reduce((a, b) => a + b)) // 6
// The largest number in the array.
console.log(arr.reduce((a, b) => a > b ? a : b)) // 3
Run Code Online (Sandbox Code Playgroud)

reduce()方法采用可选的第二个参数,即初始值.当您调用的数组reduce()可以包含零个或一个元素时,这非常有用.例如,如果我们想创建一个sum()以数组作为参数并返回所有元素之和的函数,我们就可以这样写:

const sum = arr => arr.reduce((a, b) => a + b, 0)

console.log(sum([]))     // 0
console.log(sum([4]))    // 4
console.log(sum([2, 5])) // 7
Run Code Online (Sandbox Code Playgroud)


tim*_*ate 15

这是简单的解释:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

/*
1. `data` is object contain `items` object*/
console.log(data);

/*
2. `items` object contain array of two objects as elements*/
console.log(data.items);

/*
3. you need 2nd element of array - the `1` from `[0, 1]`*/
console.log(data.items[1]);

/*
4. and you need value of `name` property of 2nd object-element of array)*/
console.log(data.items[1].name);
Run Code Online (Sandbox Code Playgroud)

  • 只是想快速评论这个问题,因为这个问题的作者没有选择最佳答案。这实际上是最好的答案。所以其他人都在寻找这个问题的答案,这是最好的。 (2认同)

Ale*_*ith 11

这个问题很古老,所以作为当代更新.随着ES2015的出现,您可以选择获取所需的数据.现在有一个称为对象解构的功能,用于访问嵌套对象.

const data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

const {
  items: [, {
    name: secondName
  }]
} = data;

console.log(secondName);
Run Code Online (Sandbox Code Playgroud)

上面的例子创建了一个从一个被调用的数组中secondNamename键调用的变量items,孤独的,说是跳过数组中的第一个对象.

值得注意的是,这个例子可能有些过分,因为简单的数组访问更容易阅读,但它在分解对象时非常有用.

这是对您的特定用例的简要介绍,解构可能是一种不常见的语法,一开始就习惯了.我建议您阅读Mozilla的Destructuring Assignment文档以了解更多信息.


Evg*_*eny 10

要访问嵌套属性,您需要指定其名称,然后搜索该对象.

如果您已经知道确切的路径,那么您可以在脚本中对其进行硬编码,如下所示:

data['items'][1]['name']
Run Code Online (Sandbox Code Playgroud)

这些也有效 -

data.items[1].name
data['items'][1].name
data.items[1]['name']
Run Code Online (Sandbox Code Playgroud)

如果您事先不知道确切的名称,或者用户是为您提供名称的用户.然后需要动态搜索数据结构.这里有人建议可以使用for循环完成搜索,但是有一种非常简单的方法来遍历路径Array.reduce.

const data = { code: 42, items: [{ id: 1, name: 'foo' }, { id: 2, name: 'bar' }] }
const path = [ 'items', '1', 'name']
let result = path.reduce((a,v) => a[v], data)
Run Code Online (Sandbox Code Playgroud)

路径是一种说法:首先用密钥取对象items,这恰好是一个数组.然后取1-st元素(0索引数组).最后name在该数组元素中使用带有键的对象,该元素恰好是字符串bar.

如果你有一条很长的道路,你甚至可以String.split用来让所有这些变得更容易 -

'items.1.name'.split('.').reduce((a,v) => a[v], data)
Run Code Online (Sandbox Code Playgroud)

这只是简单的JavaScript,不使用任何第三方库,如jQuery或lodash.


Sat*_*pta 10

这里提到了 4 种不同的方法来获取对象属性:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};
// Method 1
let method1 = data.items[1].name;
console.log(method1);

// Method 2
let method2 = data.items[1]["name"];
console.log(method2);

// Method 3
let method3 = data["items"][1]["name"];
console.log(method3);

// Method 4  Destructuring
let { items: [, { name: second_name }] } = data;
console.log(second_name);
Run Code Online (Sandbox Code Playgroud)


小智 9

你可以使用lodash _get功能:

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.get(object, 'a[0].b.c');
// => 3
Run Code Online (Sandbox Code Playgroud)


And*_*ejs 8

如果您愿意包含库,使用JSONPath将是最灵活的解决方案之一:https: //github.com/s3u/JSONPath(node and browser)

对于您的用例,json路径将是:

$..items[1].name
Run Code Online (Sandbox Code Playgroud)

所以:

var secondName = jsonPath.eval(data, "$..items[1].name");
Run Code Online (Sandbox Code Playgroud)


Joh*_*nny 8

var ourStorage = {


"desk":    {
    "drawer": "stapler"
  },
"cabinet": {
    "top drawer": { 
      "folder1": "a file",
      "folder2": "secrets"
    },
    "bottom drawer": "soda"
  }
};
ourStorage.cabinet["top drawer"].folder2; // Outputs -> "secrets"
Run Code Online (Sandbox Code Playgroud)

要么

//parent.subParent.subsubParent["almost there"]["final property"]
Run Code Online (Sandbox Code Playgroud)

基本上,在每个子对象之间展开一个点,该子对象在该子对象下展开,并且当对象名称由两个字符串组成时,必须使用[“ obj Name”]表示法。否则,只需一个点就足够了。

来源:https : //learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-objects

除此之外,访问嵌套数组的过程如下:

var ourPets = [
  {
    animalType: "cat",
    names: [
      "Meowzer",
      "Fluffy",
      "Kit-Cat"
    ]
  },
  {
    animalType: "dog",
    names: [
      "Spot",
      "Bowser",
      "Frankie"
    ]
  }
];
ourPets[0].names[1]; // Outputs "Fluffy"
ourPets[1].names[0]; // Outputs "Spot"
Run Code Online (Sandbox Code Playgroud)

来源:https//learn.freecodecamp.org/javascript-algorithms-and-data-structures/basic-javascript/accessing-nested-arrays/

描述上述情况的另一个更有用的文档:https : //developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Basics#Bracket_notation

通过点走进行属性访问:https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors#Dot_notation


Rud*_*osa 7

我更喜欢JQuery.它更清洁,易于阅读.

 $.each($.parseJSON(data), function (key, value) {
    alert(value.<propertyname>);
});
Run Code Online (Sandbox Code Playgroud)


Din*_*yan 7

为了以防万一,有人在2017年或以后访问此问题并寻找一种易于记忆的方式,这是一篇有关在JavaScript中访问嵌套对象的精心撰写的博客文章,

无法读取未定义错误的属性“ foo”

1. Oliver Steele的嵌套对象访问模式

最简单最干净的方法是使用Oliver Steele的嵌套对象访问模式

const name = ((user || {}).personalInfo || {}).name;
Run Code Online (Sandbox Code Playgroud)

有了这个符号,您将永远不会遇到

无法读取undefined的属性“名称”

您基本上检查用户是否存在,如果不存在,则动态创建一个空对象。这样,将始终从存在的对象或空对象访问下一级密钥,而永远不会从未定义的对象访问

2.使用数组归约访问嵌套对象

为了能够访问嵌套数组,您可以编写自己的数组reduce util。

const getNestedObject = (nestedObj, pathArr) => {
    return pathArr.reduce((obj, key) =>
        (obj && obj[key] !== 'undefined') ? obj[key] : undefined, nestedObj);
}

// pass in your object structure as array elements
const name = getNestedObject(user, ['personalInfo', 'name']);

// to access nested array, just pass in array index as an element the path array.
const city = getNestedObject(user, ['personalInfo', 'addresses', 0, 'city']);
// this will return the city from the first address item.
Run Code Online (Sandbox Code Playgroud)

还有一个很好的处理类型库最小typy,做这一切为您服务。

  • 这个问题主要是关于存在的访问属性。关于您所指的内容(已经包括大多数解决方案)已经存在一个问题:[安全访问Javascript嵌套对象](/sf/ask/1272488451/)或[使用以下方法访问嵌套的JavaScript对象字符串键](/sf/ask/454402441/)。但是无论如何:*“不幸的是,您不能使用此技巧访问嵌套数组。” *为什么不呢?数组是对象,因此它也应该工作。您能否提供一个没有的示例? (2认同)
  • 您没有一致地应用模式。当然,如果元素“ 1”不存在,`... [1] .bar`会导致错误。但是如果`foo`不存在,`.... foo.bar`也是如此。您也必须“保护”访问“ 1”,就像“保护”任何其他属性访问一样。数组只是一个对象。“数组元素”只是一个属性。正确应用的名称应为`((((user || {})。address || {})[1] || {})。name`。 (2认同)
  • @DineshPandiyan 你应该透露你是 typy 的作者,我是在阅读你的博文后才来到这里的 (2认同)

Kam*_*ski 6

动态方法

在下面的deep(data,key)函数中,您可以使用任意key字符串 - 在您的情况下items[1].name(您可以在任何级别使用数组表示法[i]) - 如果键无效,则返回未定义。

let deep = (o,k) => k.split('.').reduce((a,c,i) => {
    let m=c.match(/(.*?)\[(\d*)\]/);
    if(m && a!=null && a[m[1]]!=null) return a[m[1]][+m[2]];
    return a==null ? a: a[c];
},o);

// TEST

let key = 'items[1].name' // arbitrary deep-key

let data = {
    code: 42,
    items: [{ id: 11, name: 'foo'}, { id: 22, name: 'bar'},]
};

console.log( key,'=', deep(data,key) );
Run Code Online (Sandbox Code Playgroud)


Run*_* FS 5

如果您要寻找一个或多个满足特定条件的对象,可以使用query-js进行一些选择

//will return all elements with an id larger than 1
data.items.where(function(e){return e.id > 1;});
//will return the first element with an id larger than 1
data.items.first(function(e){return e.id > 1;});
//will return the first element with an id larger than 1 
//or the second argument if non are found
data.items.first(function(e){return e.id > 1;},{id:-1,name:""});
Run Code Online (Sandbox Code Playgroud)

还有一个single和一个,singleOrDefault它们分别像first和一样工作firstOrDefault。唯一的区别是,如果发现多个匹配项,它们将抛出。

查询-JS的进一步解释,你可以用这个启动


Moh*_*ere 5

The Underscore js Way

这是一个JavaScript库,提供了很多有用的信息 functional programming帮助程序,而没有扩展任何内置对象。

解:

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'foo'
  }, {
    id: 2,
    name: 'bar'
  }]
};

var item = _.findWhere(data.items, {
  id: 2
});
if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}

//using find - 

var item = _.find(data.items, function(item) {
  return item.id === 2;
});

if (!_.isUndefined(item)) {
  console.log('NAME =>', item.name);
}
Run Code Online (Sandbox Code Playgroud)


dab*_*eng 5

我不认为提问者只关心一级嵌套对象,所以我提供了以下演示来演示如何访问深度嵌套的 json 对象的节点。好的,让我们找到id为'5'的节点。

var data = {
  code: 42,
  items: [{
    id: 1,
    name: 'aaa',
    items: [{
        id: 3,
        name: 'ccc'
      }, {
        id: 4,
        name: 'ddd'
      }]
    }, {
    id: 2,
    name: 'bbb',
    items: [{
        id: 5,
        name: 'eee'
      }, {
        id: 6,
        name: 'fff'
      }]
    }]
};

var jsonloop = new JSONLoop(data, 'id', 'items');

jsonloop.findNodeById(data, 5, function(err, node) {
  if (err) {
    document.write(err);
  } else {
    document.write(JSON.stringify(node, null, 2));
  }
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://rawgit.com/dabeng/JSON-Loop/master/JSONLoop.js"></script>
Run Code Online (Sandbox Code Playgroud)


Thi*_*ura 5

古老的问题,但是没有人提到lodash(只是下划线)。

如果您已经在项目中使用lodash,那么在一个复杂的示例中,我认为这是一种优雅的方法:

选项1

_.get(response, ['output', 'fund', 'data', '0', 'children', '0', 'group', 'myValue'], '')
Run Code Online (Sandbox Code Playgroud)

和...一样:

选项2

response.output.fund.data[0].children[0].group.myValue
Run Code Online (Sandbox Code Playgroud)

第一个选项和第二个选项的区别在于,在选项1中,如果路径中缺少一个属性(未定义),则不会出错,它将返回第三个参数。

对于数组过滤器,lodash有,_.find()但是我宁愿使用regular filter()。但是我仍然认为上述方法_.get()在处理真正复杂的数据时超级有用。我过去曾经面对过非常复杂的API,这很方便!

我希望这对于谁在寻找操作标题所暗示的真正复杂数据的选项可能有用。


小智 5

jQuery 的 grep函数可让您过滤数组:

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

$.grep(data.items, function(item) {
    if (item.id === 2) {
        console.log(item.id); //console id of item
        console.log(item.name); //console name of item
        console.log(item); //console item object
        return item; //returns item object
    }

});
// Object {id: 2, name: "bar"}
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Run Code Online (Sandbox Code Playgroud)


And*_*rut 5

动态访问多级对象。

var obj = {
  name: "salut",
  subobj: {
    subsubobj: {
      names: "I am sub sub obj"
    }
  }
};

var level = "subobj.subsubobj.names";
level = level.split(".");

var currentObjState = obj;

for (var i = 0; i < level.length; i++) {
  currentObjState = currentObjState[level[i]];
}

console.log(currentObjState);
Run Code Online (Sandbox Code Playgroud)

工作提琴:https : //jsfiddle.net/andreitodorut/3mws3kjL/


Rat*_*ore 5

在 2020 年,您可以使用 @babel/plugin-proposal-optional-chaining 访问对象中的嵌套值非常容易。

 const obj = {
 foo: {
   bar: {
     baz: class {
   },
  },
 },
};

const baz = new obj?.foo?.bar?.baz(); // baz instance

const safe = new obj?.qux?.baz(); // undefined
const safe2 = new obj?.foo.bar.qux?.(); // undefined
Run Code Online (Sandbox Code Playgroud)

https://babeljs.io/docs/en/babel-plugin-proposal-optional-chaining

https://github.com/tc39/proposal-optional-chaining


Rah*_*ala 5

您可以使用语法jsonObject.key来访问该值。如果您想访问数组中的值,则可以使用语法jsonObjectArray[index].key.

以下是访问各种值的代码示例,为您提供思路。

var data = {
    code: 42,
    items: [{
        id: 1,
        name: 'foo'
    }, {
        id: 2,
        name: 'bar'
    }]
};

// if you want 'bar'
console.log(data.items[1].name);

// if you want array of item names
console.log(data.items.map(x => x.name));

// get the id of the item where name = 'bar'
console.log(data.items.filter(x => (x.name == "bar") ? x.id : null)[0].id);
Run Code Online (Sandbox Code Playgroud)


Eng*_*faq 5

我就是这样做的。

 let groups = [
        {
            id:1,
            title:"Group 1",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                },
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        },
        {
            id:2,
            title:"Group 2",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                {
                    id:2,
                    name:"Jamal",
                    battry:'10%'
                },
                {
                    id:3,
                    name:"Hamid",
                },
               
            ]
        },
        {
            id:3,
            title:"Group 3",
            members:[
                {
                    id:1,
                    name:"Aftab",
                    battry:'10%'
                },
                
                {
                    id:3,
                    name:"Hamid",
                },
                {
                    id:4,
                    name:"Aqeel",
                },
            ]
        }
    ]
    
    groups.map((item) => {
      //  if(item.id == 2){
        item.members.map((element) => {
             if(element.id == 1){
                 element.battry="20%"
             }
         })
        //}
    })
    
    groups.forEach((item) => {
        item.members.forEach((item) => {
            console.log(item)
    })
    })
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

566689 次

最近记录:

6 年,3 月 前