繁体   English   中英

在 JavaScript 中,如何通过解构和短路评估有条件地为 object 赋值?

[英]In JavaScript, how can I conditionally assign value to object with destructuring and short circuit evaluation?

假设我有这个设置:

const objA = { name: "Jacob", email: "jacob@email.com" };
const objB = { lastName: "Smith" };

为什么我可以这样做:

const lastName = objA.lastName || objB.lastName;

但不是这个?

const { lastName } = objA || objB;

能够在开发工具中重新创建上述示例。

我的真实世界应用程序:我有“正常”和“传统”帐户角色,在查询这两种类型的角色后,我希望能够:

const { schoolAdmin } = account || legacyAccount;

...而是必须这样做:

const schoolAdmin = account.schoolAdmin || legacyAccount.schoolAdmin;

诚然,这没什么大不了的,但我觉得我缺少了一些东西,我可以在这里使用解构。 Jr dev,抱歉,如果这是一个虚拟问题,(有时没有帐户。有时有一个帐户没有 schoolAdmin 角色!与 legacyAccount 类似。)

发生什么了

你不能的原因是因为一个空的 object 返回 true。 例如,在 devtools 中尝试!!{} ,它返回 true。

知道这一点,很容易意识到|| 接线员总是 select 第一个 object。

要对此进行测试,您可以尝试以下操作:

const objA = { name: "Jacob", email: "jacob@email.com" };
const objB = { lastName: "Smith" };
let { lastName } = objB || objA; // Returns Smith

和:

const objA = { name: "Jacob", email: "jacob@email.com" };
const objB = { lastName: "Smith" };
let { lastName } = objA || objB; // Returns undefined

建议的解决方案

解决方案是将两个 object 分散为一个。 注意两件事的先后顺序,下面会解释!

const { lastName } = { ...objB, ...objA };
  • 如果 objA 具有 lastName 属性,则无论 objB 是否具有该属性都将使用它,因为它只会覆盖它。

  • 如果 objA 没有该属性,则不会从 objB 覆盖 lastName,因此会返回其值。 (如果它们都不具有该属性,则为未定义)

正如评论中所解释的那样|| 不评估对象的联合,它返回第二个

你可以这样做:

const { lastName } = { ...objA, ...objB };

它确实创建了一个工会

您的表达式试图从=赋值运算符右侧的子表达式返回的 object 中的属性分配lastName 右边的子表达式objA || objB objA || objB计算结果为objA ,它没有lastName属性,因此您的lastName变量收到值undefined

如果objB中不存在该属性,您可以只使用objA并提供objA的默认值:

const { lastName = objB.lastName } = objA;

或者,您可以将objAobjB到单个 object 中,并从中解构:

const { lastName } = { ...objB, ...objA };

撒的时候,顺序倒过来。 最后一个 object 覆盖了第一个 object 的值。因此,如果您想要更喜欢 objA 的值, objAobjA最后。

这种扩展选项提供了令人满意的对称性,但可能效率较低。 从性能的角度来看,第一个选项更好。 但是,就我个人而言,我认为您不喜欢的代码提供了尽可能好的性能和清晰度:

const lastName = objA.lastName || objB.lastName;

这是完全明确的,不会执行不必要的操作。

还应该指出的是,我的两种解决方案都不是严格等同于非解构方法。 如果objA.lastName是除undefined之外的虚假值( ""nullfalse ), objB.lastName 0而在我的两个解决方案中,将使用虚假的objA.lastName 感谢VLAZ在评论中提到这一点。

暂无
暂无

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

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