在Javascript中,如何有条件地向对象添加成员?

在Javascript中,如何有条件地向对象添加成员?,javascript,Javascript,我想创建一个有条件添加成员的对象。 简单的方法是: var a = {}; if (someCondition) a.b = 5; 现在,我想写一段更地道的代码。我正在努力: a = { b: (someCondition? 5 : undefined) }; 但是现在,b是a的成员,其值为未定义。这不是期望的结果 有简便的解决办法吗 更新 var a = _.merge({}, { b: conditionB ? 4 : undefined, c: cond

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

var a = {};
if (someCondition)
    a.b = 5;
现在,我想写一段更地道的代码。我正在努力:

a = {
    b: (someCondition? 5 : undefined)
};
但是现在,
b
a
的成员,其值为
未定义。这不是期望的结果

有简便的解决办法吗

更新

var a = _.merge({}, {
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
})
我寻求一种解决办法,可以与几个成员一起处理一般情况

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),
 };
我会这么做

var a=someCondition?{b:5}:{};

在纯Javascript中,我想不出比您的第一个代码片段更地道的了

但是,如果使用jQuery库不是不可能的,那么应该满足您的要求,因为正如文档所述:

未定义的属性不会被复制

因此,你可以写:

var a = $.extend({}, {
    b: conditionB ? 5 : undefined,
    c: conditionC ? 5 : undefined,
    // and so on...
});

并获得您期望的结果(如果
conditionB
false
,则
b
将不存在于
a
)。

我认为您第一种有条件地添加成员的方法是非常好的。我真的不同意不希望有一个
a
b
成员的
值为
未定义
。使用
for
循环和
in
操作符添加
未定义的
检查非常简单。但无论如何,您可以轻松编写一个函数来过滤
未定义的成员

var filterUndefined = function(obj) {
  var ret = {};
  for (var key in obj) {
    var value = obj[key];
    if (obj.hasOwnProperty(key) && value !== undefined) {
      ret[key] = value;
    }
  }
  return ret;
};

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

您还可以使用
delete
操作符在位编辑对象。

如果目标是使对象显示为独立的,并且位于一组大括号内,您可以尝试以下操作:

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

    if (conditionC)
        this.c = 5;

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

这一点早就得到了回答,但看看其他想法,我想出了一些有趣的衍生工具:

将未定义的值指定给同一属性,然后将其删除 使用匿名构造函数创建对象,并始终将未定义的成员分配给在最后删除的同一虚拟成员。这将给你一个单一的行(不太复杂,我希望)每个成员+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;
};

如果希望在服务器端执行此操作(无jquery),可以使用lodash 4.3.0:

a = _.pickBy({ b: (someCondition? 5 : undefined) }, _.negate(_.isUndefined));

这项工作使用lodash 3.10.1

a = _.pick({ b: (someCondition? 5 : undefined) }, _.negate(_.isUndefined));

使用ECMAScript 2015,您可以使用:

var a、conditionB、conditionC、conditionD;
条件c=真;
a={};
赋值(a,条件b?{b:1}:null,
条件c?{c:2}:null,
条件d?{d:3}:null);

控制台日志(a)我认为@InspiredJW使用ES5做到了这一点,正如@trincot指出的,使用es6是一种更好的方法。但我们可以通过使用spread运算符以及逻辑和短路评估来添加更多的糖:

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

使用增强的对象属性并仅在属性为truthy时设置该属性如何,例如:

[isConditionTrue() && 'propertyName']: 'propertyValue'
因此,如果不满足条件,它不会创建首选属性,因此您可以放弃它。 见:

更新: 更好的做法是遵循Axel Rauschmayer在其博客文章中关于在对象文本和数组()中有条件地添加条目的方法:

这对我帮助很大

var a = {
    ...(condition ? {b: 1} : '') // if condition is true 'b' will be added.
}
我希望这是根据条件添加条目的更有效的方法。
有关如何在对象文本中有条件地添加条目的详细信息。

使用lodash库,您可以使用\uuu.merge

var a = _.merge({}, {
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
})
  • 如果条件B为
    false
    ,条件c为
    true
    ,则
    a={c:5}
  • 如果条件b和条件c都是
    true
    ,则
    a={b:4,c:5}
  • 如果条件B和条件C都是
    false
    ,则
    a={}

  • 使用lodash库,您可以使用

    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)
    
    现场演示:

    const obj={
    …(对)&{someprop:42},
    …(假)&{nonprop:“foo”},
    …({})和{棘手的:“你好”},
    }
    
    控制台日志(obj)
    您可以无条件添加所有未定义的值,然后使用
    JSON.stringify
    将它们全部删除:

    const person = {
      name: undefined,
      age: 22,
      height: null
    }
    
    const cleaned = JSON.parse(JSON.stringify(person));
    
    // Contents of cleaned:
    
    // cleaned = {
    //   age: 22,
    //   height: null
    // }
    

    我建议如下:

    const a={
    …(某些条件?{b:5}:{})
    }
    
    包装成一个对象

    像这样的东西比较干净

     const obj = {
       X: 'dataX',
       Y: 'dataY',
       //...
     }
    
     const list = {
       A: true && 'dataA',
       B: false && 'dataB',
       C: 'A' != 'B' && 'dataC',
       D: 2000 < 100 && 'dataD',
       // E: conditionE && 'dataE',
       // F: conditionF && 'dataF',
       //...
     }
    
     Object.keys(list).map(prop => list[prop] ? obj[prop] = list[prop] : null)
    
    或者使用
    map()
    函数

    const obj = {
      X: 'dataX',
      Y: 'dataY',
      //...
    }
    
    const array = [
      true && { A: 'dataA'},
      false &&  { B: 'dataB'},
      'A' != 'B' && { C: 'dataC'},
      2000 < 100 && { D: 'dataD'},
      // conditionE && { E: 'dataE'},
      // conditionF && { F: 'dataF'},
      //...
    
     ].map(val => Object.assign(obj, val))
    
    const obj={
    X:'dataX',
    Y:‘数据Y’,
    //...
    }
    常量数组=[
    true&&{A:'dataA'},
    false&&{B:'dataB'},
    'A'!='B'&&{C:'dataC'},
    2000<100&{D:'dataD'},
    //条件&&{E:'dataE'},
    //条件F&&{F:'dataF'},
    //...
    ].map(val=>Object.assign(obj,val))
    
    这是我能想到的最简洁的解决方案:

    var a = {};
    conditionB && a.b = 5;
    conditionC && a.c = 5;
    conditionD && a.d = 5;
    // ...
    
    更简单一点

    const a = {
        ...(condition && {b: 1}) // if condition is true 'b' will be added.
    }
    

    通过
    let
    定义一个var,然后只分配新属性

    let msg={
    至:hito@email.com",
    来自:hifrom@email.com",
    主题:“联系方式”,
    };
    如果(文件上传形式){//,条件如下
    msg.attachments=[//此处“attachments”是添加到msg Javascript对象的新属性
    {
    内容:“附件”,
    文件名:“文件名”,
    类型:“mime_类型”,
    处置:“附件”,
    },
    ];
    }
    
    现在
    msg
    变成

    {
        to: "hito@email.com",
        from: "hifrom@email.com",
        subject: "Contact form",
        attachments: [
          {
            content: "attachment",
            filename: "filename",
            type: "mime_type",
            disposition: "attachment",
          },
        ]
    }
    
    在我看来,这是一个非常简单的解决方案。

    更好的答案:

    const a = {
       ...(someCondition ? {b: 5} : {})
    }
    

    性能测试

    经典方法

    const a = {};
    if (someCondition)
        a.b = 5;
    
    const a2 = {
       ...(someCondition && {b: 5})
    }
    
    VS

    扩展运算符进近

    const a = {};
    if (someCondition)
        a.b = 5;
    
    const a2 = {
       ...(someCondition && {b: 5})
    }
    
    结果:

    经典的方法要快得多,所以要考虑到语法加糖的速度较慢

    TestClassicConditionCompleted();//~234.9ms
    TestClassicConditionNotCompleted();//~493.1ms
    TestSpreadOperator条件已满足();//~2649.4ms
    TestSpreadOperator条件未满足();//~2278.0ms

    函数测试扩展运算符条件已满足(){
    常数值=5;
    console.time('testSp
    
    const a2 = {
       ...(someCondition && {b: 5})
    }
    
    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 trueCondition = true;
    const falseCondition = false;
    const obj = {
      ...(trueCondition && { student: 10 }),
      ...(falseCondition && { teacher: 2 }),
    };
    
    // { student: 10 }