我想创建一个对象,有条件地添加成员。 简单的方法是:

var a = {};
if (someCondition)
    a.b = 5;

现在,我想写一个更习惯的代码。我在努力:

a = {
    b: (someCondition? 5 : undefined)
};

但是现在,b是a的一个元素,它的值是未定义的。这不是我们想要的结果。

有没有方便的解决办法?

更新

我寻求一个解决方案,可以处理一般情况与几个成员。

a = {
  b: (conditionB? 5 : undefined),
  c: (conditionC? 5 : undefined),
  d: (conditionD? 5 : undefined),
  e: (conditionE? 5 : undefined),
  f: (conditionF? 5 : undefined),
  g: (conditionG? 5 : undefined),
 };

当前回答

这个问题早就有答案了,但在研究其他想法时,我想到了一些有趣的衍生品:

将未定义的值赋给相同的属性,然后删除它

使用匿名构造函数创建对象,并始终将未定义的成员分配给您在最后删除的同一个虚拟成员。这将给你一个单行(不是太复杂,我希望)每个成员+ 1额外的行结束。

var a = new function() {
    this.AlwaysPresent = 1;
    this[conditionA ? "a" : "undef"] = valueA;
    this[conditionB ? "b" : "undef"] = valueB;
    this[conditionC ? "c" : "undef"] = valueC;
    this[conditionD ? "d" : "undef"] = valueD;
    ...
    delete this.undef;
};

其他回答

这是我能想到的最简洁的解决方案:

var a = {};
conditionB && a.b = 5;
conditionC && a.c = 5;
conditionD && a.d = 5;
// ...

简单的es6解决方案

带有(&)的单一条件

const didIPassExam = true Const study = { 星期一:“写作”, 周二:“阅读”, /*有条件检查,如果为真,则增加周三学习*/ ...(didIPassExam &&{星期三:'睡得开心'}) } console.log(研究)

带有(?):)

Const分数= 110 //const得分= 10 Const storage = { 答:10 b: 20, ...(得分> 100 ?{c: 30}: {d:40}) } console.log(存储)

解释

假设你有一个这样的存储对象

const storage = {
  a : 10,
  b : 20,
}

你想在此基础上有条件地增加一个道具

const score = 90

如果分数大于100,您现在希望将道具c:30添加到存储区。

如果score小于100,则需要将d:40添加到存储中。你可以这样做

const score = 110

const storage = {
  a:10,
  b:20,
  ...(score > 100  ? {c: 30} : {d:40}) 
}

上面的代码给出存储为

{
  a: 10,
  b: 20,
  c: 30
}

如果分数= 90

然后你得到存储

{
  a: 10,
  b: 20,
  d: 40
}

Codepen例子

在EcmaScript2015中,你可以使用Object.assign:

Object.assign(a, conditionB ? { b: 1 } : null,
                 conditionC ? { c: 2 } : null,
                 conditionD ? { d: 3 } : null);

var a,条件b,条件c,条件; 条件c = true; A = {}; 对象。赋值(a, conditionB ?{b: 1}: null, conditionC吗?{c: 2}: null, conditionD吗?{d: 3}: null); console.log(一个);

一些评论:

对象。Assign会原地修改第一个参数,但它也会返回更新后的对象:所以你可以在一个更大的表达式中使用这个方法来进一步操作对象。 而不是null,你可以传递undefined或{},有相同的结果。您甚至可以提供0,因为原始值被包装了,而Number没有自己的可枚举属性。

更简洁

进一步考虑第二点,你可以把它缩短如下(正如@Jamie指出的那样),因为假值没有自己的可枚举属性(false, 0, NaN, null, undefined,”,除了document.all):

Object.assign(a, conditionB && { b: 1 },
                 conditionC && { c: 2 },
                 conditionD && { d: 3 });

条件a,条件b,条件c,条件d; conditionC = "this is true "; 条件= NaN;/ / falsy a = {}; 物体。assign(a,条件b && {b: 1}, 条件&& {c: 2}, 条件&& {d: 3}); console.log (a);

如果目标是让对象看起来是自包含的,并且在一组大括号中,你可以尝试这样做:

var a = new function () {
    if (conditionB)
        this.b = 5;

    if (conditionC)
        this.c = 5;

    if (conditionD)
        this.d = 5;
};

为了完整起见,如果您想添加额外的描述符,可以使用Object.defineProperty()。注意,我特意添加了enumerable: true,否则该属性不会出现在console.log()中。这种方法的优点是,如果你想添加多个新属性,你也可以使用Object.defineProperties()(然而,这样每个属性都依赖于相同的条件…)

const select = document.getElementById("condition"); const output = document.getElementById("output"); let a = {}; let b = {}; select.onchange = (e) => { const condition = e.target.value === "true"; condition ? Object.defineProperty(a, "b", { value: 5, enumerable: true, }) : (a = {}); condition ? Object.defineProperties(b, { c: { value: 5, enumerable: true, }, d: { value: 6, enumerable: true, }, e: { value: 7, enumerable: true, }, }) : (b = {}); outputSingle.innerText = JSON.stringify(a); outputMultiple.innerText = JSON.stringify(b); }; Condition: <select id="condition"> <option value="false">false</option> <option value="true">true</option> </select> <br/> <br/> Single Property: <pre id="outputSingle">{}</pre><br/> Multiple Properties: <pre id="outputMultiple">{}</pre>