【问题标题】:Key value pair is not being set, if undefined, but has a default value如果未定义,则未设置键值对,但具有默认值
【发布时间】:2018-04-17 14:42:20
【问题描述】:

我有一个具有各种键值的对象(简化):

const params = {
  dev: {
    api: {},
    iot: {},
  },
  test: {
    api: {},
    iot: {},
  }
};

我想通过 Object.keys().forEach 函数填充:

Object.keys(params).forEach(key => {
  params[key].iot.keyName = `/firstURL/`;
  params[key].api.anotherKeyName = `/url/var2`;
});

目前,它按预期填充,但如果我从 params 对象中删除密钥(API/IOT),我会收到 undefined 错误。

我的想法是检查是否首先定义了键,如果没有(实际上永远不会),则使用默认值:

Object.keys(params).forEach(key => {
  params[key].iot.keyName = params[key].iot.keyName || `/firstURL/`;
  params[key].api.anotherKeyName = params[key].api.anotherKeyName || `/url/var2`;
});

我从params 对象中删除键的原因是它们总是动态生成的(取决于您所处的环境)。

当我检查它是否存在时,为什么会收到 keyName 未定义错误,如果不存在,请为其赋值?

非常感谢。

【问题讨论】:

  • 你有什么问题?
  • "...但是如果我从 params 对象中删除密钥 (API/IOT),我会收到未定义的错误。" 您何时以及如何删除密钥(也就是说,属性)?请使用 minimal reproducible example 来更新您的问题,以展示问题,最好是使用 Stack Snippets([<>] 工具栏按钮;here's how to do one可运行
  • 道歉,补充 :)
  • params[key].iot 不存在,因此您正在尝试访问未定义对象的属性

标签: javascript object foreach


【解决方案1】:

目前,它按预期填充,但如果我从 params 对象中删除 keys (API/IOT),我会收到未定义的错误。

(我的重点)

当然。您的代码不会以任何方式检查以确保它们首先存在。为此:

Object.keys(params).forEach(key => {
  if (params[key].iot) params[key].iot.keyName = `/firstURL/`;
  if (params[key].api) params[key].api.anotherKeyName = `/url/var2`;
});

旁注:您可能会查看 Object.values,在 ES2017 中添加但完全可填充:

Object.values(params).forEach(entry => {
  if (entry.iot) entry.iot.keyName = `/firstURL/`;
  if (entry.api) entry.api.anotherKeyName = `/url/var2`;
});

【讨论】:

  • 我建议一直使用三元运算符:params[key].iot ? params[key].iot.keyName : /firstUrl/
  • @LordAlpaca:我不会。也不是&& 版本。 :-)
  • 非常感谢您的回复@T.J.Crowder,就在我想我理解访问键/值的时候......这些值实际上是动态生成的,我们可以假设这些键永远不会存在并且会总是需要先创建。有没有合适的方法来适应您的上述检查?非常感谢。
  • @Ben:我不是 100% 确定我知道您所说的“我们可以假设这些密钥永远不会存在”是什么意思,但如果您是字面意思,那么:params[key].iot = {keyName: `/firstURL/`};(和另一个的等价物)。这会在条目上创建一个名为 iot 的属性,并为其分配一个对象作为其值;该对象将有keyName
  • ^ 效果很好@T.J.Crowder,再次感谢你:)
【解决方案2】:

为什么我在检查是否出现 keyName is undefined 错误时 存在,如果不存在,给它赋值?

您没有收到keyNameundefined 的消息。如果您仔细观察,消息会显示Cannot read property 'keyName' of undefined"

const params = {
  dev: {},
  test: {}
};

Object.keys(params).forEach(key => {
  params[key].iot.keyName = params[key].iot.keyName || `/firstURL/`;
  params[key].api.anotherKeyName = params[key].api.anotherKeyName || `/url/var2`;
});

这不是在抱怨 keyName 它是在抱怨你无法在 undefined 的其他东西上读取该属性 - 那是 iot

您正在检查keyName 是否存在,如果不存在则为其设置默认值,但这不是问题。 问题是iot 不存在。


您收到错误是因为,虽然您可以简单地通过为其分配值来创建新属性,但您无法访问不存在的属性上的属性,这就是您正在做的事情:

params[key].iot.keyName = `/firstURL/`;

如果iot 不存在,则无法访问iot.keyName

举例说明:

var obj = {};

obj.key1 = "foo";        // works
obj.key2.subKey = "bar"; // fails because key2 doesn't exist so bar can't be created on it

在访问属性的属性之前,您需要添加一些检查以查看属性是否存在。这是一个例子:

var obj = {};

obj.key1 = "foo";        // works

if(obj.key2){
  obj.key2.subKey = "bar"; // works when key2 exists
} else {
  obj.key2 = {};           // Create the key
  obj.key2.subKey = "bar"; // Now, you can access it and make sub-keys
}

console.log(obj);

一种简单的思考方式是对几代人进行类比。

  • params是第一代
  • iot 是第二代(params 的孩子)
  • keyName是第三代(iot的孩子和孙子 params)

就像在现实世界中一样,如果你没有孩子,你就不能照顾你的孙子。孩子们必须先来。当还没有孩子时,您的代码会尝试使用孙子。

【讨论】:

  • 感谢您的回复。我的猜测是我误解了使用默认值? params[key].iot.keyName = params[key].iot.keyName || /firstURL/; 我知道它不存在,如果它不存在,那么为该属性分配一个默认值?
  • @Ben 只有当iot 已经存在时才是正确的。但是,如果iot 不存在,则无法访问keyName 为其设置默认值。换句话说,您不能一次创建多个级别的属性/键。它们必须一次创建一个级别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 2016-09-01
  • 2010-10-20
  • 2013-10-01
  • 1970-01-01
  • 2020-03-19
相关资源
最近更新 更多