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

2020/09/27 17:01 · javascript ·  · 0评论

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

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

现在,我想编写一个更惯用的代码。我在尝试:

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

但是,现在b是,a其值为的成员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),
 };

在纯Javascript中,我想不出比您的第一个代码片段更多的习惯用法。

但是,如果不是不可能使用jQuery库,那么$ .extend()应该符合您的要求,因为如文档所述:

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

因此,您可以编写:

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

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

我认为@InspiredJW是使用ES5完成的,正如@trincot指出的那样,使用es6是更好的方法。但是,我们可以使用散布运算符和逻辑与短路评估来添加更多的糖:

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

借助EcmaScript2015,您可以使用Object.assign

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

一些说明:

  • Object.assign 就地修改第一个参数,但它也会返回更新的对象:因此,您可以在更大的表达式中使用此方法,以进一步操作该对象。
  • 代替null您可以通过undefined{},结果相同。您甚至可以提供0,因为原始值是包装的,并且Number没有自己的可枚举属性

更简洁

进一步考虑第二点,你可以如下(@Jamie指出),作为falsy值没有自己的枚举的属性(缩短false0NaNnullundefined'',除外document.all):

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

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

现场演示:

const obj = {
  ...(true) && {someprop: 42},
  ...(false) && {nonprop: "foo"},
  ...({}) && {tricky: "hello"},
}

console.log(obj);

将扩展语法与布尔值一起使用(如此处所建议)是无效的语法。价差只能与可迭代对象一起使用

我建议以下内容:

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

更简化

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

如果使用增强对象属性并且仅在属实的情况下设置属性,例如:

[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'} : {})
};

相当帮助了我。

更好的答案:

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

性能测试

经典方法

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

VS

传播算子方法

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

结果:

经典方法要快得多,因此请考虑语法加糖较慢。

testClassicConditionFulfilled(); //〜234.9毫秒

testClassicConditionNotFulfilled(); //〜493.1毫秒

testSpreadOperatorConditionFulfilled(); //〜2649.4毫秒

testSpreadOperatorConditionNotFulfilled(); //〜2278.0ms

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

如果目标是使对象显示为独立对象并放在一组括号内,则可以尝试以下操作:

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

    if (conditionC)
        this.c = 5;

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

如果您希望在服务器端执行此操作(不使用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));

您可以无条件添加所有未定义的值,然后使用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
// }

长期以来,人们已经回答了这个问题,但是在研究其他想法时,我想到了一些有趣的派生词:

将未定义的值分配给同一属性,然后将其删除

使用匿名构造函数创建对象,并始终将未定义的成员分配给最终要删除的同一虚拟成员。这将为您每个成员提供一行(我希望不太复杂),最后再增加一行。

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 = {
    ...(condition ? {b: 1} : '') // if condition is true 'b' will be added.
}

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

我会这样做

var a = someCondition ? { b: 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)

定义变量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",
      },
    ];
}

现在msg成为

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

我认为这是非常简单容易的解决方案。

我更喜欢使用此代码,您可以运行此代码

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

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

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运算符在适当位置编辑对象。

包装成一个物体

这样的东西比较干净

 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)

包装成阵列

Or if you want to use Jamie Hill's method and have a very long list of conditions then you must write ... syntax multiple times. To make it a bit cleaner, you can just wrap them into an array, then use reduce() to return them as a single object.

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

Or using map() function

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;
// ...

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

var a = _.merge({}, {
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
})
  1. 如果conditionB是false&conditionC是true, then a = { c: 5 }
  2. 如果conditionB和conditionC都为 true, then a = { b: 4, c: 5 }
  3. 如果conditionB和conditionC都为false,则a = {}
本文地址:http://javascript.askforanswer.com/zaijavascriptzhongruheyoutiaojiandijiangchengyuantianjiadaoduixiang.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!