有条件地设置对象属性

79

是否有一些根据条件设置属性的语法?

data: {
    userId: 7,
    actionId: 36,
    express: (myCondition ? true : null) // does not work
}

我希望 express 可以被设定一个值或者不设定(即不存在名为express的键),定义后不需要额外的语句。我知道可以将它用作布尔值,但接收方正在使用 isset() 检查,我想知道是否可以避免修改它。


编辑: 看起来没有直接解决所述问题的解决方案。以下是接近的建议:

JSON.stringify (Chris Kessel, dystroy):

var json = JSON.stringify( {
    data: {
        userId: 7,
        actionId: 36,
        express: (myCondition ? true : null)
    }
});

匿名函数(Paulpro):

var data = new function(){
    this.userId = 7;
    this.actionId = 36;
    myCondition && (this.express = true);
};

额外声明 (x4rf41):

data: {
    userId: 7,
    actionId: 36
}
if(myCondition) data["express"] = true;

Eval(我的前同事):

eval("data = {userId: 7, actionId: 36 " + (myCondition ? ", express: true}" : "}"))

条件定义(不太清楚如何标记这个):

data = (
    (myCondition && { userId: 7, actionId: 36, express: true }) ||
    (!myCondition && { userId: 7, actionId: 36 })
);

当你说“根本没有设置”时,你是指属性存在但其值为undefined,还是该属性根本不存在? - jbabey
我的意思是该属性根本不应存在。 - mcmlxxxvi
@Paulpro:我认为你是正确的 :) - mcmlxxxvi
有很多有趣的答案,所以决定选择哪一个是很困难的。感谢大家的意见。 - mcmlxxxvi
显示剩余2条评论
7个回答

115

使用展开运算符

data: {
    userId: 7,
    actionId: 36,
    ...myCondition && {express: true}
}

请注意,如果你正在使用Flow,那么这种语法可能会产生类型检查错误。你可以更加明确地、不那么简洁地编写上面的代码,如下所示:

data: {
    userId: 7,
    actionId: 36,
    ...(myCondition ? {express: true} : {})
}

5
这是个很棒的回答。 - R. AbuBaker
如果不想要空对象:...(myCondition ? {express: true} : null) 那么可以通过以下方式过滤掉 null:data = data.filter(function(x) { return x !== null }); - user1345817
@user1345817 只是想插一句嘴,你添加的更新是不必要的,因为答案中的扩展运算符 (...) 在三元表达式的假值情况下会消除空对象 ({})。因此,该属性只会在真值情况下被添加。 - adstwlearn

78

像这样做:

data: {
    userId: 7,
    actionId: 36,
    express: (myCondition ? true : undefined)
}

当对象被转换为JSON时,其属性值为undefined的属性不会被写入。字符串化
编辑:从评论中得知实际上没有涉及JSON。OP使用了$.ajax,因此可能使用了$.param。不幸的是,$.param会为值为undefined的属性创建一个条目。因此,可能没有任何额外的代码行解决问题。

我只是将它提供给 AJAX 调用,它并没有被剥离 - 我目前没有明确地将其转换为字符串。 - mcmlxxxvi
我不知道你的API,但几乎可以确定它正在调用JSON.stringify。即使它没有,规范也不允许传递未定义的值,因此任何API都必须删除其值为undefined的属性。 - Denys Séguret
我正在使用jQuery,我不知道它对对象做了什么,但属性仍然存在。 - mcmlxxxvi
6
+1 对于 JSON.stringify 忽略未定义的属性,我学到了新东西,谢谢。 - jbabey
3
如果你不生成 JSON,那么就与 JSON 没有关系。 - Denys Séguret
显示剩余6条评论

9

如果您使用匿名函数而不是对象字面量表示法定义对象,则可以实现此操作:

var data = new function(){
    this.userId = 7;
    this.actionId = 36;
    myCondition && (this.express = true);
};

生成的data对象与原始对象完全相同,只是它的constructor将是匿名函数,而不是window.Object

5

首先,这是 JavaScript 而不是 JSON。

解决方案:

data: {
    userId: 7,
    actionId: 36
}
if(myCondition) data["express"] = true;

这并不是一个真正的答案:“在定义之后没有额外的语句”。显然,楼主知道他可以这样做。 - Denys Séguret
1
这在ES6中不起作用。显示了更漂亮和linting错误。 - jay rangras

3
你可以像这样做:

你可以这样做:

var json = JSON.stringify( {
    data: {
        userId: 7,
        actionId: 36,
        express: (myCondition ? true : null)
    }
});

7
不会剔除 null,但会剔除 undefined - mcmlxxxvi
是的,非常正确。我只是在我的代码中重复了原始内容。 - Chris Kessel

3
扩展运算符现在解决了这个问题。以下是两个比较的示例。
注意:我将date:更改为const date =,以便它是有效的可运行javascript。如果它应该在深层对象结构中,则也可以与data:一起使用。

const compareValue = 13;
const data =  {
    userId: 7,
    actionId: 36,
    ...(compareValue > 10 && {propertyForGreaterThan10: 'foo'}),
    ...(compareValue < 10 && {propertyForLessThan10: 'bar'}),
}
console.log(data);


2

虽然有点老,但是也有一个很好的解决方案:

data: {
    userId: 7,
    actionId: 36
}

Object.assign(data, !myCondition && { express: yourValue });

因此,如果条件为false,它将使用所需的值分配给您的express属性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接