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

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),
 };

当前回答

性能测试

经典的方法

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

VS

展开算子法

const a2 = {
   ...(someCondition && {b: 5})
}

结果:

经典的方法要快得多,所以要考虑到语法糖化更慢。

testClassicConditionFulfilled ();// ~ 234.9ms testClassicConditionNotFulfilled ();/ / ~ 493 1ms。 testSpreadOperatorConditionFulfilled ();/ / ~紧密4ms。 testSpreadOperatorConditionNotFulfilled ();/ / ~ 2239。卫生组织

function testSpreadOperatorConditionFulfilled() { const value = 5; console.time('testSpreadOperatorConditionFulfilled'); for (let i = 0; i < 200000000; i++) { let a = { ...(value && {b: value}) }; } console.timeEnd('testSpreadOperatorConditionFulfilled'); } function testSpreadOperatorConditionNotFulfilled() { const value = undefined; console.time('testSpreadOperatorConditionNotFulfilled'); for (let i = 0; i < 200000000; i++) { let a = { ...(value && {b: value}) }; } console.timeEnd('testSpreadOperatorConditionNotFulfilled'); } function testClassicConditionFulfilled() { const value = 5; console.time('testClassicConditionFulfilled'); for (let i = 0; i < 200000000; i++) { let a = {}; if (value) a.b = value; } console.timeEnd('testClassicConditionFulfilled'); } function testClassicConditionNotFulfilled() { const value = undefined; console.time('testClassicConditionNotFulfilled'); for (let i = 0; i < 200000000; i++) { let a = {}; if (value) a.b = value; } console.timeEnd('testClassicConditionNotFulfilled'); } testClassicConditionFulfilled(); // ~ 234.9ms testClassicConditionNotFulfilled(); // ~493.1ms testSpreadOperatorConditionFulfilled(); // ~2649.4ms testSpreadOperatorConditionNotFulfilled(); // ~2278.0ms

其他回答

在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);

我更喜欢,使用代码这个吧,你可以运行这个代码

const three = {
  three: 3
}

// you can active this code, if you use object `three is null`
//const three = {}

const number = {
  one: 1,
  two: 2,
  ...(!!three && three),
  four: 4
}

console.log(number);

我用另一个选项做了一个小的基准测试。我喜欢从一些物体上去除“累赘”。通常是错误的值。

以下是本尼的结果:

清洁

const clean = o => {
    for (const prop in o) if (!o) delete o[prop];
}

clean({ value });

传播

let a = {
    ...(value && {b: value})
};

if

let a = {};
if (value) {
    a.b = value;
}

结果

clean  :  84 918 483 ops/s, ±1.16%    | 51.58% slower    
spread :  20 188 291 ops/s, ±0.92%    | slowest, 88.49% slower    
if     : 175 368 197 ops/s, ±0.50%    | fastest

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

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

    if (conditionC)
        this.c = 5;

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

使用lodash库,您可以使用_.omitBy

var a = _.omitBy({
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
}, _.IsUndefined)

当您有可选的请求时,这会非常方便

var a = _.omitBy({
    b: req.body.optionalA,  //if undefined, will be removed
    c: req.body.optionalB,
}, _.IsUndefined)