访问/过程(嵌套)对象,数组或JSON [英] Access / process (nested) objects, arrays or JSON

查看:971
本文介绍了访问/过程(嵌套)对象,数组或JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含对象和数组A(嵌套)数据结构。我怎样才能提取信息,即访问特定或多个值(或钥匙)?

例如:

  VAR数据= {
    code:42,
    项目:[{
        ID:1,
        名称:'富'
    },{
        ID:2,
        名称:'棒'
    }]
};

我怎么能在项目访问名称第二项


解决方案

preliminaries

JavaScript的只有它可以包含多个值的一个数据类型:对象即可。一个阵列为对象的一种特殊形式。

(平原)对象具有形式

  {键:值,键:值,...}

数组的形式为

  [值,值,...]

这两个数组和对象暴露键 - >值结构。以阵列的键必须是数字的,而任何串可被用作在对象密钥。键 - 值对也被称为在属性

属性可以使用访问或者点号

  VAR值= obj.someProperty;

括号标记,如果属性名称将不会是一个有效的JavaScript 标识符名称的 [规格] ,或者名称是一个变量的值:

  //空间是不是在标识符名称的有效字符
VAR值的obj = [一些房产];//属性名作为变量
变量名称=一些财产;
VAR值= OBJ [名]

由于这个原因,数组元素只能使用括号记号访问:

  VAR值= ARR [5]; // arr.5将是一个语法错误//属性名称/指数为变量
VAR X = 5;
VAR值= ARR [X];

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

JSON是数据的文本再presentation,就像XML,YAML,CSV,和其他人。与这样的数据的工作,它首先被转换为JavaScript的数据类型,即,数组和对象(以及如何与这些工作只是解释)。如何解析JSON在这个问题解析JSON在JavaScript中解释呢?

延伸阅读材料

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



访问嵌套的数据结构

一个嵌套的数据结构是指其他数组或对象,即它的值是数组或对象的数组或对象。这种结构可以通过连续施加点或支架符号来访问。

下面是一个例子:

  VAR数据= {
    code:42,
    项目:[{
        ID:1,
        名称:'富'
    },{
        ID:2,
        名称:'棒'
    }]
};

假设我们要访问的第二个项目的名称

下面是我们如何能做到这一步一步的:

我们可以看到数据是一个对象,因此我们可以使用点符号访问其属性。 属性被作为访问项目如下:

  data.items

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

  data.items [1]

这个值是一个对象,我们再次使用点表示法来访问名称属性。因此,我们最终得到:

  VAR ITEM_NAME = data.items [1]。名称;

另外,我们也可以使用括号标记的任何属性,特别是如果名字中包含了将使它无效的点符号使用的字符:

  VAR ITEM_NAME =数据['项目'] [1] ['名'];


我试图访​​问一个属性,但我只得到未定义回来?

很多时候你所得到的时间未定义,对象/数组根本没有与该名称的属性。

 无功富= {吧:{巴兹:42}};
的console.log(foo.baz); //未定义

使用 的console.log console.dir 和检查对象/数组的结构。您尝试访问的属性可能会实际上定义了一个嵌套的对象/阵列上。

 的console.log(foo.bar.baz); // 42


如果什么属性名是动态的,我不知道他们事先?

如果属性名称是未知的,或者我们要访问对象的所有属性/数组的元素,我们可以使用<$c$c>for...in [MDN] 的的对象循环和的 [MDN] 循环数组遍历所有属性/元素。

对象

要遍历数据的所有属性,我们可以遍历的目标像这样:

 的(数据VAR道具){
    //`prop`包含每个属性,即''code'`或`'的名字items'`
    //因此,`数据[丙]`是指每个属性的值,即
    //是`42`或阵列
}

根据该对象来自(你想做的事),你可能在每次迭代测试属性是否是真正的对象的属性,或者是继承财产。为此,您可以用<一个href=\"https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/hasOwnProperty\"><$c$c>Object#hasOwnProperty [MDN] 的。

的hasOwnProperty 替代为中... ,你可以使用<一个href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys\"><$c$c>Object.keys [MDN] 的来获得的属性名称的数组的:

  Object.keys(数据).forEach(函数(丙){
  //`prop`是属性名
  //`数据[道具]`是属性值
});

阵列

要遍历 data.items 阵列,我们使用了循环:

 为(VAR I = 0,1 = data.items.length; I&LT;升;我++){
    //`i`将在值`0`,`1`,`2`,...,即在每次迭代
    //我们可以在阵列中与`data.items [Ⅰ]`,例如访问的下一个元素:
    //
    // VAR OBJ = data.items [I]
    //
    //由于每个元素都是一个对象(在我们的例子),
    //我们现在可以用`obj.id`和`obj.name`访问对象的属性。
    //我们也可以使用`data.items [I] .id`。
}

你也可以使用为中... 来遍历数组,但也有此原因,应避免的原因:<一href=\"http://stackoverflow.com/questions/2265167/why-is-forvar-item-in-list-with-arrays-considered-bad-practice-in-javascript\">Why是对(列表中的项目VAR)'对数组认为不好的做法,在JavaScript中?。

通过浏览器支持的ECMAScript 5,阵列方法<一增加href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach\"><$c$c>forEach [MDN] 的成为一个有趣的选择,以及:

  data.items.forEach(功能(价值指数,数组){
    //回调为阵列中的每个元素执行。
    //`value`是元素本身(相当于`数组[索引]`)
    //`index`将是元件的阵列中的索引
    //`array`是到阵列本身的引用(即,`data.items`在这种情况下)
});

在支持ES2015(ES5)的环境中,你也可以使用<$c$c>for...of [MDN] 循环,这不仅适用于数组,但是任何<一个href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable\">iterable:

 为(data.items的VAR项){
   //`item`是数组元素,** **不索引
}

在每次迭代中,为...的直接为我们提供了可迭代的下一个元素,没有指标来访问或使用。


如果该数据结构的深度是未知的我?

在除未知键时,该数据结构的深度(即有多少每个阵列嵌套对象)有,可能是未知的,以及。如何访问深度嵌套的性能主要取决于准确的数据结构,然后呢?

如果该数据结构包含重复结构,例如二叉树重新presentation,该解决方案通常包括 递归 [维基] 访问数据结构的每一级别

下面是一个例子来获得的二进制树的第一叶节点

 函数getLeaf(节点){
    如果(node.leftChild){
        返回getLeaf(node.leftChild); //&LT; - 递归调用
    }
    否则,如果(node.rightChild){
        返回getLeaf(node.rightChild); //&LT; - 递归调用
    }
    否则{//节点必须是一个叶节点
        返回节点;
    }
}VAR first_leaf = getLeaf(根);

\r
\r

VAR根= {\r
    leftChild:{\r
        leftChild:{\r
            leftChild:空,\r
            rightChild:空,\r
            数据:42\r
        },\r
        rightChild:{\r
            leftChild:空,\r
            rightChild:空,\r
            数据:5\r
        }\r
    },\r
    rightChild:{\r
        leftChild:{\r
            leftChild:空,\r
            rightChild:空,\r
            数据:6\r
        },\r
        rightChild:{\r
            leftChild:空,\r
            rightChild:空,\r
            数据:7\r
        }\r
    }\r
};\r
功能getLeaf(节点){\r
    如果(node.leftChild){\r
        返回getLeaf(node.leftChild);\r
    }否则如果(node.rightChild){\r
        返回getLeaf(node.rightChild);\r
    }否则{//节点必须是一个叶节点\r
        返回节点;\r
    }\r
}\r
\r
警报(getLeaf(根)。数据);

\r

\r
\r

来访问与未知键和深度嵌套的数据结构的更通用的方法是测试值的类型并据此采取行动。

下面是增加了一个嵌套的数据结构内的所有基本值到一个数组(假设它不包含任何函数)的例子。如果我们遇到一个对象(或数组),我们简单地调用的toArray 再次上该值(递归调用)。

 函数的toArray(OBJ){
    VAR的结果= [];
    对于(OBJ中的道具VAR){
        VAR值= OBJ [道具]
        如果(typeof运算值==='对象'){
            result.push(的toArray(值)); //&LT; - 递归调用
        }
        其他{
            result.push(值);
        }
    }
    返回结果;
}

\r
\r

VAR数据= {\r
  code:42,\r
  项目:[{\r
    ID:1,\r
    名称:'富'\r
  },{\r
    ID:2,\r
    名称:'棒'\r
  }]\r
};\r
\r
\r
功能的toArray(OBJ){\r
  VAR的结果= [];\r
  对于(OBJ中的道具VAR){\r
    VAR值= OBJ [道具]\r
    如果(typeof运算值==='对象'){\r
      result.push(的toArray(值));\r
    }其他{\r
      result.push(值);\r
    }\r
  }\r
  返回结果;\r
}\r
\r
警报(JSON.stringify(的toArray(数据)));

\r

\r
\r



助手

由于复杂的物体或阵列的结构不一​​定是显而易见的,我们可以在每个步骤检查的值来决定如何进一步移动。 的console.log [MDN] console.dir [MDN] 帮助我们这样做。例如(在Chrome控制台输出):

 &GT;的console.log(data.items)
 [对象,对象]

在这里我们看到, data.items 是这两者都是对象在两个元素的数组。在Chrome浏览器控制台的对象甚至可以扩展,并立即进行检查。

 &GT;的console.log(data.items [1])
  目的
     ID:2
     名称:栏
     __proto__:对象

这告诉我们, data.items [1] 是一个对象,以及扩大后,我们看到它有三个属性, ID 名称 __ __原。后者是用于对象的原型链的内部属性。原型链和继承超出范围的这个答案,虽然。

I have a (nested) data structure containing objects and arrays. How can I extract the information, i.e. access a specific or multiple values (or keys)?

For example:

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

How could I access the name of the second item in items?

解决方案

Preliminaries

JavaScript has only one data type which can contain multiple values: Object. An Array is a special form of object.

(Plain) Objects have the form

{key: value, key: value, ...}

Arrays have the form

[value, value, ...]

Both arrays and objects expose a key -> value structure. Keys in an array must be numeric, whereas any string can be used as key in objects. The key-value pairs are also called the "properties".

Properties can be accessed either using dot notation

var value = obj.someProperty;

or bracket notation, if the property name would not be a valid JavaScript identifier name [spec], or the name is the value of a variable:

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

// property name as variable
var name = "some Property";
var value = obj[name];

For that reason, array elements can only be accessed using bracket notation:

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

// property name / index as variable
var x = 5;
var value = arr[x];

Wait... what about JSON?

JSON is a textual representation of data, just like XML, YAML, CSV, and others. To work with such data, it first has to be converted to JavaScript data types, i.e. arrays and objects (and how to work with those was just explained). How to parse JSON is explained in the question Parse JSON in JavaScript? .

Further reading material

How to access arrays and objects is fundamental JavaScript knowledge and therefore it is advisable to read the MDN JavaScript Guide, especially the sections



Accessing nested data structures

A nested data structure is an array or object which refers to other arrays or objects, i.e. its values are arrays or objects. Such structures can be accessed by consecutively applying dot or bracket notation.

Here is an example:

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

Let's assume we want to access the name of the second item.

Here is how we can do it step-by-step:

As we can see data is an object, hence we can access its properties using dot notation. The items property is accessed as follows:

data.items

The value is an array, to access its second element, we have to use bracket notation:

data.items[1]

This value is an object and we use dot notation again to access the name property. So we eventually get:

var item_name = data.items[1].name;

Alternatively, we could have used bracket notation for any of the properties, especially if the name contained characters that would have made it invalid for dot notation usage:

var item_name = data['items'][1]['name'];


I'm trying to access a property but I get only undefined back?

Most of the time when you are getting undefined, the object/array simply doesn't have a property with that name.

var foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined

Use console.log or console.dir and inspect the structure of object / array. The property you are trying to access might be actually defined on a nested object / array.

console.log(foo.bar.baz); // 42


What if the property names are dynamic and I don't know them beforehand?

If the property names are unknown or we want to access all properties of an object / elements of an array, we can use the for...in [MDN] loop for objects and the for [MDN] loop for arrays to iterate over all properties / elements.

Objects

To iterate over all properties of data, we can iterate over the object like so:

for(var 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
}

Depending on where the object comes from (and what you want to do), you might have to test in each iteration whether the property is really a property of the object, or it is an inherited property. You can do this with Object#hasOwnProperty [MDN].

As alternative to for...in with hasOwnProperty, you can use Object.keys [MDN] to get an array of property names:

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

Arrays

To iterate over all elements of the data.items array, we use a for loop:

for(var 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`.
}

One could also use for...in to iterate over arrays, but there are reasons why this should be avoided: Why is 'for(var item in list)' with arrays considered bad practice in JavaScript?.

With the increasing browser support of ECMAScript 5, the array method forEach [MDN] becomes an interesting alternative as well:

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)
}); 

In environments supporting ES2015 (ES5), you can also use the for...of [MDN] loop, which not only works for arrays, but for any iterable:

for (var item of data.items) {
   // `item` is the array element, **not** the index
}

In each iteration, for...of directly gives us the next element of the iterable, there is no "index" to access or use.


What if the "depth" of the data structure is unknown to me?

In addition to unknown keys, the "depth" of the data structure (i.e. how many nested objects per array) it has, might be unknown as well. How to access deeply nested properties depends on the exact data structure, then?

If the data structure contains repeating structures, e.g. the representation of a binary tree, the solution typically includes to recursively [Wikipedia] access each level of the data structure.

Here is an example to get the first leaf node of a binary tree:

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;
    }
}

var first_leaf = getLeaf(root);

var 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;
    }
}

alert(getLeaf(root).data);

A more generic way to access a nested data structure with unknown keys and depth is to test the type of the value and act accordingly.

Here is an example which adds all primitive values inside a nested data structure into an array (assuming it does not contain any functions). If we encounter an object (or array) we simply call toArray again on that value (recursive call).

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

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


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

alert(JSON.stringify(toArray(data)));



Helpers

Since the structure of a complex object or array is not necessarily obvious, we can inspect the value at each step to decide how to move further. console.log [MDN] and console.dir [MDN] help us doing this. For example (output of the Chrome console):

> console.log(data.items)
 [ Object, Object ]

Here we see that that data.items is an array with two elements which are both objects. In Chrome console the objects can even be expanded and inspected immediately.

> console.log(data.items[1])
  Object
     id: 2
     name: "bar"
     __proto__: Object

This tells us that data.items[1] is an object, and after expanding it we see that it has three properties, id, name and __proto__. The latter is an internal property used for the prototype chain of the object. The prototype chain and inheritance is out of scope for this answer, though.

这篇关于访问/过程(嵌套)对象,数组或JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆