如何访问和处理嵌套对象、数组或 JSON?

2023-11-27

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

例如:

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

我怎样才能访问name中的第二项items?


预赛

JavaScript 只有一种数据类型,可以包含多个值:Object. An Array是一种特殊形式的物体。

(普通)对象具有以下形式

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

数组的形式为

[value, value, ...]

数组和对象都公开了key -> value结构。数组中的键必须是数字,而任何字符串都可以用作对象中的键。键值对也称为“特性”.

可以使用以下方式访问属性点符号

const 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
const value = obj["some Property"];

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

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

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

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

等等...JSON 怎么样?

JSON 是数据的文本表示形式,就像 XML、YAML、CSV 等一样。要处理此类数据,首先必须将其转换为 JavaScript 数据类型,即数组和对象(刚刚解释了如何处理这些数据)。问题中解释了如何解析 JSON在 JavaScript 中解析 JSON? .

进一步阅读材料

如何访问数组和对象是 JavaScript 的基础知识,因此建议阅读MDN JavaScript 指南,特别是以下部分

  • 使用对象
  • Arrays
  • Eloquent JavaScript - 数据结构


访问嵌套数据结构

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

这是一个例子:

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

假设我们想要访问name第二项的。

我们可以按照以下步骤进行操作:

正如我们所看到的data是一个对象,因此我们可以使用点表示法访问它的属性。这items属性的访问方式如下:

data.items

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

data.items[1]

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

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

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

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

我正在尝试访问某个属性,但我只得到undefined back?

大多数时候当你得到undefined,对象/数组根本没有具有该名称的属性。

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

Use console.log or console.dir并检查对象/数组的结构。您尝试访问的属性实际上可能是在嵌套对象/数组上定义的。

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

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

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

迭代所有属性data,我们可以迭代object像这样:

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
}

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

迭代所有元素data.items array,我们使用一个for loop:

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`.
}

也可以使用for...in迭代数组,但有一些原因应该避免这种情况:为什么在 JavaScript 中使用数组的“for(var item in list)”被认为是不好的做法?.

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 (ES6), you can also use the for...of [MDN] loop, which not only works for arrays, but for any iterable:

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

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


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

除了未知的键之外,数据结构的“深度”(即有多少个嵌套对象)也可能是未知的。如何访问深度嵌套的属性通常取决于确切的数据结构。

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

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

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

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

访问具有未知键和深度的嵌套数据结构的更通用方法是测试值的类型并采取相应的操作。

这是一个示例,它将嵌套数据结构内的所有原始值添加到数组中(假设它不包含任何函数)。如果我们遇到一个对象(或数组),我们只需调用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;
}

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


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 ]

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

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

这告诉我们data.items[1]是一个对象,展开后我们看到它有三个属性,id, name and __proto__。后者是用于对象原型链的内部属性。不过,原型链和继承超出了这个答案的范围。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何访问和处理嵌套对象、数组或 JSON? 的相关文章

随机推荐

  • 数组之前的 Ruby * 运算符[重复]

    这个问题在这里已经有答案了 可能的重复 理解范围和数组中的 ruby splat 谁能告诉我下面代码中 的作用是什么 line name yabbi language ruby Hash line split Thanks 是 splat
  • jquery validate需要点击submit两次才能提交表单

    我在模态中有一个表单 用户必须填写表单 否则验证将显示必填字段错误消息 然后单击提交输入类型 它什么也不做 然后再次单击它 然后它将通过ajax发布 并返回 谢谢 消息 我已经浏览了 Stackoverflow 并应用了我遇到的问题的答案
  • CPAN 首次启动(代理配置)

    我需要通过代理运行 cpan 但是当我尝试配置时出现错误 并且第一次无法进入 cpan root srv linux01 cpan CPAN pm requires configuration but most of it can be d
  • 使用 ASP.NET 日历控件时如何隐藏周末?

    有时 在显示日历时 需要防止显示周末日期和日期标题中的周末名称 有没有办法使用ASP NET 日历控件 由于提供了控件 因此在不重写控件的情况下无法执行此操作 执行此操作的一种方法是覆盖当天渲染 and Render在将输出发送回客户端之前
  • 在应用程序购买中,用户在应用程序处于后台时取消交易:交易状态保持在购买状态

    当应用程序处于后台且用户尚未登录商店时 我在应用程序购买 沙盒环境 中取消用户时出现一些奇怪的行为 流程如下 用户未登录 未在 设置 gt 商店 中设置应用程序 ID 用户点击购买按钮 这调用 SKPaymentQueue defaultQ
  • 动态地将可调用对象添加到类作为实例“方法”

    我实现了一个元类 它拆除用它创建的类的类属性 并根据这些参数的数据构建方法 然后将这些动态创建的方法直接附加到类对象 所讨论的类允许轻松定义 Web 表单对象在网络测试框架中使用 它一直工作得很好 但现在我需要添加一种更复杂类型的方法 为了
  • 在ios中使用查询字符串创建NSURLRequest

    我在 ios 中创建了一个用户查询表单 我使用 php 作为服务器端 我在 IOS 中构造了如下所示的查询字符串 http www mydomain in androidmail enquiry php name Vinoth Kumar
  • 如何将包含单引号的字符串保存到 PostgreSQL 中的文本列

    我在 Smartwcm Web 应用程序 SDK 中使用 hibernate 和 PostgreSQL 作为数据库 我在其中一个表中有一个字段 其数据类型是文本 当我尝试使用 hibernate 使用相应的 POJO 将值插入表中时 如果我
  • 无法使用 VS 2013 RTM 编译 OpenCV 2.4.5

    有人用 VS 2013 RTM 编译过 openCV 吗 我尝试在 IlmImf 模块中获取一堆 min 不属于命名空间 std max 不属于命名空间 std 并且 opencv features2d 无法编译并出现以下错误 opencv
  • 如何设置
    元素的箭头样式?

    我正在使用这段代码 另请参阅JSFiddle 以更改悬停时箭头的背景颜色 但是 这不起作用 因为箭头仅在单击时更改其颜色 summary webkit details marker color B6B6B6 font size 20px m
  • ClassInitialize 中生成的数据驱动测试:不再在 Visual Studio 2012 中工作

    我已从 Visual Studio 2010 升级到 Visual Studio 2012 在我的单元测试项目中 我有一个 ClassInitialize 方法 它生成一个 CSV 文件 然后使用连接到 CSV 的 DataSource 将
  • 数据库如何自动生成唯一标识符?

    我有一个带有 id guid 列的 sql 表 如何强制数据库为每条新记录自动生成新的 guid Add DEFAULT newid
  • Global.asax 中的 ASP.NET 路由

    我试图通过以下方式在我的 Web 表单应用程序中添加一条路线 http msdn microsoft com en us library cc668201 aspx adding routes to a web forms applicat
  • faces-redirect 和后退按钮导致其他链接无法正常工作

    我有一个关于面孔导航的问题 所以我有一个页面 它采用请求参数来加载特定用户 此页面显示 commandLink 列表 单击该列表后 将使用隐式导航重定向到另一个页面 通过调用 preRenderView 中的方法来加载用户 我们重定向到的页
  • 如何将协作者添加到 Firebase 应用程序?

    在最新版本的Firebase 在 Google I O 2016 期间宣布 如何将我想要的其他人添加到我的项目或应用程序中collaborate和 我通过以下途径认识了 IAM 角色Settings gt Permissions 这是正确的
  • Bootstrap Tour 不记得我离开的地方

    当我到达第二页时 我在多页游览中启动 Bootstrap Tour 时遇到问题 我以点击事件开始游览localStorage被设定为false 游览从单击事件开始正常 但是当我转到游览的第二步并加载新页面时 游览不会从中断处继续 如何在这个
  • 使 WCHAR 为空终止

    我有这个 WCHAR 文件名 1 作为函数的返回值 它是 sys 32 函数 因此我无法更改返回的类型 我需要使 fileName 以 null 结尾 因此我尝试将 0 附加到它 但似乎没有任何效果 一旦我得到一个以 null 结尾的 WC
  • Jasper Reports 使用 comparatorExpression 进行交叉表排序

    我正在尝试根据某些自定义方案对交叉表中的动态列进行排序 在文档中 我发现提到了comparatorExpression 交叉表组存储桶比较器表达式 这个表达式的结果是 用于按升序或降序对存储桶进行排序 如果没有比较器 指定表达式时 将使用自
  • 创建/更新文档日期的摄取管道

    我正在尝试实现类似于 Mysql 的行为 为我通过 ES 管道索引的每个文档的元数据添加 insert at updated at 我的管道是这样的 description Adds createdAt and updatedAt styl
  • 如何访问和处理嵌套对象、数组或 JSON?

    我有一个包含对象和数组的嵌套数据结构 如何提取信息 即访问特定或多个值 或键 例如 var data code 42 items id 1 name foo id 2 name bar 我怎样才能访问name中的第二项items 预赛 Ja