繁体   English   中英

无法从 Javascript 中的 object 访问属性

[英]Can't access property from object in Javascript

编辑:重组问题,更清晰,更清洁:

我有一个来自 Sequelize 的data object 由 node-express 发送:

{
    "page": 0,
    "limit": 10,
    "total": 4,
    "data": [
        {
            "id": 1,
            "title": "movies",
            "isActive": true,
            "createdAt": "2020-05-30T19:26:04.000Z",
            "updatedAt": "2020-05-30T19:26:04.000Z",
            "questions": [
                {
                    "questionsCount": 4
                }
            ]
        }
    ]
}

最大的问题是,我如何获得questionsCount的值? 问题是,我无法提取它,这两种方法给了我undefined的结果:

  1. category.questions[0].questionsCount
  2. category.questions[0]['questionsCount']

我能够使用toJSON()获得它(我认为来自 Sequelize lib),如下所示:

category.questions[0].toJSON().questionsCount

但我想知道问题的答案,或者至少清楚地解释为什么我必须使用toJSON()来获取questionsCount


更多上下文:

我的 controller 中有这个GET

exports.getCategories = (req, res) => {
  const page = myUtil.parser.tryParseInt(req.query.page, 0)
  const limit = myUtil.parser.tryParseInt(req.query.limit, 10)

  db.Category.findAndCountAll({
    where: {},
    include: [
      {
        model: db.Question,
        as: "questions",
        attributes: [[db.Sequelize.fn('COUNT', 'id'), 'questionsCount']]
      }
    ],
    offset: limit * page,
    limit: limit,
    order: [["id", "ASC"]],
  })
    .then(data => {

      data.rows.forEach(function(category) {
        console.log("------ May 31 ----> " + JSON.stringify(category.questions[0]) + " -->" + category.questions[0].hasOwnProperty('questionsCount'))
        console.log(JSON.stringify(category))
        console.log(category.questions[0].toJSON().questionsCount)
      })

      res.json(myUtil.response.paging(data, page, limit))
    })
    .catch(err => {
      console.log("Error get categories: " + err.message)
      res.status(500).send({
        message: "An error has occured while retrieving data."
      })
    })
}

我遍历data.rows以获取每个category object。

console.log输出为:

------ May 31 ----> {"questionsCount":4} -->false

{"id":1,"title":"movies","isActive":true,"createdAt":"2020-05-30T19:26:04.000Z","updatedAt":"2020-05-30T19:26:04.000Z","questions":[{"questionsCount":4}]}

4

尝试这个

category.data[0].questions[0].questionCount

您必须使用 toJSON 的原因是因为它有时用于自定义字符串化行为。 就像在将值分配给将返回的 object 之前进行一些计算,所以这里最常用来计算“问题的数量,然后返回一个带有属性 questionscount 的 object或更少看起来像这样

var cathegory = {
  data: 'data',
  questions:[{
    // some calulation here to get the questionsCount 
      result=4,
    toJSON () {
      return  {"questionsCount":this.result}       
    } 
  }
 ]
};

console.log(cathegory.questions[0].toJSON().questionsCount) //4
console.log(JSON.stringify(cathegory))  // {"data":"data","questions":[{"questionsCount":4}]}
console.log("------ May 31 ----> " + JSON.stringify(cathegory.questions[0]) + " -->" + cathegory.questions[0].hasOwnProperty('questionsCount')) //false

尝试这样做category.data[0].questions.questionCount

正如其他人已经提到的,您需要category.data[0].questions[0].questionCount

让我通过向您展示原因来补充这一点。 看看你的 object,我用每个部分的访问方式对其进行了注释:

category = { // category
    "page": 0,
    "limit": 10,
    "total": 2,
    "data": [ // category.data
        { // category.data[0]
            "id": 1,
            "title": "movies",
            "createdAt": "2020-05-30T19:26:04.000Z",
            "updatedAt": "2020-05-30T19:26:04.000Z",
            "questions": [ // category.data[0].questions
                { // category.data[0].questions[0]
                    "questionCount": 2 // category.data[0].questions[0].questionCount
                }
            ],
            "questionsCount": "newValue here!"
        }
    ]
}

https://github.com/sequelize/sequelize/blob/master/docs/manual/core-concepts/model-querying-finders.md

默认情况下,所有查找器方法的结果都是 model class 的实例(而不是简单的 JavaScript 对象)。 这意味着在数据库返回结果后,Sequelize 会自动将所有内容包装在适当的实例对象中。 在少数情况下,当结果太多时,这种包装可能效率低下。 要禁用此包装并改为接收普通响应,请将 { raw: true } 作为选项传递给 finder 方法

(我强调)
或者直接在源码中, https://github.com/sequelize/sequelize/blob/59b8a7bfa018b94ccfa6e30e1040de91d1e3d3dd/lib/model.js#L2028

@returns {Promise<{count: number, rows: Model[]}>}

所以问题是你得到了一个Model对象的数组,你可以使用他们的get()方法进行导航。 这是一个不幸的巧合,您期望一个数组,并得到一个数组,所以您认为它是“那个”数组。 试试{raw:true}的东西,我猜它看起来像这样:

db.Category.findAndCountAll({
    where: {},
    include: [
      {
        model: db.Question,
        as: "questions",
        attributes: [[db.Sequelize.fn('COUNT', 'id'), 'questionsCount']]
      }
    ],
    offset: limit * page,
    limit: limit,
    order: [["id", "ASC"]],
    raw: true                            // <--- hopefully it is this simple
  }) [...]


toJSON()也在附近, https://github.com/sequelize/sequelize/blob/59b8a7bfa018b94ccfa6e30e1040de91d1e3d3dd/lib/model.js#L4341

 /** * Convert the instance to a JSON representation. * Proxies to calling `get` with no keys. * This means get all values gotten from the DB, and apply all custom getters. * * @see * {@link Model#get} * * @returns {object} */ toJSON() { return _.cloneDeep( this.get({ plain: true }) ); }

所以它确实有效,因为它做了你需要的,删除了get()东西并提供了一个实际的 JavaScript object 匹配你的结构(POJSO? - 对不起,我无法抗拒)。 我很少使用它,因此总是忘记,但关键的背景“技巧”是有点与其名称相反, toJSON()预计不会创建实际的 JSON 字符串,而是提供替换 object 仍然被JSON.stringify()字符串化JSON.stringify() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#toJSON_behavior

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM