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

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

我会这样做

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

在纯Javascript中,我想不出比第一个代码片段更习惯的东西了。

但是,如果使用jQuery库不是不可能的,那么$.extend()应该可以满足您的需求,因为正如文档所述:

未定义的属性不会被复制。

因此,你可以这样写:

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

并获得您期望的结果(如果条件b为假,则b将不存在于a中)。


我认为你第一个有条件地增加成员的方法是完全没问题的。我不同意不让元素b (a)的值为undefined。使用带有in操作符的for循环来添加一个未定义的检查非常简单。但无论如何,你可以很容易地编写一个函数来过滤掉未定义的成员。

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

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


我认为@InspiredJW用ES5做到了,正如@trincot指出的那样,使用es6是更好的方法。但我们可以添加更多的糖,通过使用扩散运算符,和逻辑与短路计算:

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

使用增强对象属性并只设置为真值的属性,例如:

[isConditionTrue() && 'propertyName']: 'propertyValue'

因此,如果条件不满足,它不会创建首选属性,因此您可以丢弃它。 见:http://es6-features.org/ ComputedPropertyNames

更新: 最好遵循Axel Rauschmayer在他的博客文章中关于在对象字面量和数组中有条件地添加条目的方法(http://2ality.com/2017/04/conditional-literal-entries.html):)

const arr = [
  ...(isConditionTrue() ? [{
    key: 'value'
  }] : [])
];

const obj = {
  ...(isConditionTrue() ? {key: 'value'} : {})
};

对我帮助很大。


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

我希望这是基于条件添加条目的更有效的方法。 有关如何有条件地在对象字面量中添加条目的详细信息。


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

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

如果条件b为假,条件c为真,则a = {c: 5} 如果条件b和条件c都为真,则a = {b: 4, c: 5} 如果条件b和条件c都为假,则a = {}


使用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)

const obj = {
   ...(condition) && {someprop: propvalue},
   ...otherprops
}

现场演示:

Const obj = { (true) && {someprop: 42}, …(false) && {nonprop: "foo"}, …({})&&{狡猾的:"hello"}, } console.log (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 = {
   ...(someCondition? {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)

包装成数组

或者如果你想使用Jamie Hill的方法并且有一个很长的条件列表,那么你必须写。语法多次。为了更简洁,可以将它们包装到一个数组中,然后使用reduce()将它们作为单个对象返回。

const obj = {
  X: 'dataX',
  Y: 'dataY',
  //...

...[
  true && { A: 'dataA'},
  false && { B: 'dataB'},
  'A' != 'B' && { C: 'dataC'},
  2000 < 100 && { D: 'dataD'},
  // conditionE && { E: 'dataE'},
  // conditionF && { F: 'dataF'},
  //...

 ].reduce(( v1, v2 ) => ({ ...v1, ...v2 }))
}

或者使用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))

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

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定义一个变量,然后赋值一个新属性

let msg = {
    to: "hito@email.com",
    from: "hifrom@email.com",
    subject: "Contact form",    
};

if (file_uploaded_in_form) { // the condition goes here
    msg.attachments = [ // here 'attachments' is the new property added to msg Javascript object
      {
        content: "attachment",
        filename: "filename",
        type: "mime_type",
        disposition: "attachment",
      },
    ];
}

现在味精变成了

{
    to: "hito@email.com",
    from: "hifrom@email.com",
    subject: "Contact form",
    attachments: [
      {
        content: "attachment",
        filename: "filename",
        type: "mime_type",
        disposition: "attachment",
      },
    ]
}

在我看来,这是一个非常简单易行的解决方案。


性能测试

经典的方法

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


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

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

这可能是ES6中最短的解决方案

console.log({
   ...true && {foo: 'bar'}
})
// Output: {foo:'bar'}
console.log({
   ...false && {foo: 'bar'}
})
// Output: {}

有条件地向对象添加成员

const trueCondition = true;
const falseCondition = false;
const obj = {
  ...(trueCondition && { student: 10 }),
  ...(falseCondition && { teacher: 2 }),
};

// { student: 10 }

为了完整起见,如果您想添加额外的描述符,可以使用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>


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

以下是本尼的结果:

清洁

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

下面的代码片段应该可以工作。

const a = {}

const conditionB = true;
const conditionC = true;
const conditionD = true;
const conditionE = true;

const b = {
  ...(conditionB && { b : 5}),
  ...(conditionC && { c : 5}),
  ...(conditionD && { d : 5}),
  ...(conditionE && { e : 5}),
 };

console.log(b);

我希望这有助于解决你的问题

身体< > <标题> GeeksforGeeks h1 > < / < p id =“极客”> < / p > < !——检查数组包含的脚本 对象与否——> <脚本> Var obj = {"geeks1":10, "geeks2":12} Var arr = ["geeks1", "geeks2", "geeks3", obj]; 如果(加勒比海盗。过滤器(值= = = >价值obj)。长度> 0) document . write(“true”); 其他的 document . write(“false”); > < /脚本 身体< / >


简单的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例子


const isAdult = true;

const obj = {
  ...(isAdult ? { age: 18 }: { age: 17}),
};

//>> { student: 18 }