vie*_*bel 294 javascript
我想创建一个有条件添加成员的对象.简单的方法是:
var a = {};
if (someCondition)
a.b = 5;
Run Code Online (Sandbox Code Playgroud)
现在,我想写一个更惯用的代码.我在尝试:
a = {
b: (someCondition? 5 : undefined)
};
Run Code Online (Sandbox Code Playgroud)
但现在,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),
};
Run Code Online (Sandbox Code Playgroud)
小智 674
我认为@InspiredJW是用ES5做的,正如@trincot指出的那样,使用es6是一种更好的方法.但是我们可以通过使用扩展运算符和逻辑AND短路评估来添加更多的糖:
const a = {
...(someCondition && {b: 5})
}
Run Code Online (Sandbox Code Playgroud)
Fré*_*idi 99
在纯Javascript中,我想不出比你的第一个代码片段更惯用的东西.
但是,如果使用jQuery库并不是不可能的,那么$ .extend()应该满足您的要求,因为文档说:
未复制未定义的属性.
因此,你可以写:
var a = $.extend({}, {
b: conditionB ? 5 : undefined,
c: conditionC ? 5 : undefined,
// and so on...
});
Run Code Online (Sandbox Code Playgroud)
并获得您期望的结果(如果conditionB是false,那么b将不存在a).
tri*_*cot 82
使用EcmaScript2015,您可以使用Object.assign:
Object.assign(a, conditionB ? { b: 1 } : null,
conditionC ? { c: 2 } : null,
conditionD ? { d: 3 } : null);
Run Code Online (Sandbox Code Playgroud)
var a, conditionB, conditionC, conditionD;
conditionC = true;
a = {};
Object.assign(a, conditionB ? { b: 1 } : null,
conditionC ? { c: 2 } : null,
conditionD ? { d: 3 } : null);
console.log(a);Run Code Online (Sandbox Code Playgroud)
一些评论:
Object.assign 修改第一个就地参数,但它也返回更新的对象:因此您可以在更大的表达式中使用此方法来进一步操作对象.null你可以传递undefined或{},具有相同的结果.您甚至可以提供0,因为原始值被包装,并且Number没有自己的可枚举属性.以第二点进一步,可以缩短如下(@Jamie指出),作为falsy值没有自己的枚举的属性(false,0,NaN,null,undefined,'',除外document.all):
Object.assign(a, conditionB && { b: 1 },
conditionC && { c: 2 },
conditionD && { d: 3 });
Run Code Online (Sandbox Code Playgroud)
var a, conditionB, conditionC, conditionD;
conditionC = "this is truthy";
conditionD = NaN; // falsy
a = {};
Object.assign(a, conditionB && { b: 1 },
conditionC && { c: 2 },
conditionD && { d: 3 });
console.log(a);Run Code Online (Sandbox Code Playgroud)
San*_*ath 59
简单的 ES6 解决方案
带 (&) 的单一条件 -if condition
const didIPassExam = true
const study = {
monday : 'writing',
tuesday : 'reading',
/* check conditionally and if true, then add wednesday to study */
...(didIPassExam && {wednesday : 'sleep happily'})
}
console.log(study)Run Code Online (Sandbox Code Playgroud)
双重条件 (?:) -if-else condition
const score = 110
//const score = 10
const storage = {
a:10,
b:20,
...(score > 100 ? {c: 30} : {d:40})
}
console.log(storage)Run Code Online (Sandbox Code Playgroud)
解释
假设你有storage这样的对象
const storage = {
a : 10,
b : 20,
}
Run Code Online (Sandbox Code Playgroud)
并且您想根据条件添加一个道具score
const score = 90
Run Code Online (Sandbox Code Playgroud)
您现在想要添加 propc:30到storageifscore大于100。
如果分数小于100,那么您要添加 d:40到storage。你可以这样做
const score = 110
const storage = {
a:10,
b:20,
...(score > 100 ? {c: 30} : {d:40})
}
Run Code Online (Sandbox Code Playgroud)
上面的代码给出storage如下
{
a: 10,
b: 20,
c: 30
}
Run Code Online (Sandbox Code Playgroud)
如果score = 90
然后你storage得到
{
a: 10,
b: 20,
d: 40
}
Run Code Online (Sandbox Code Playgroud)
小智 39
更简化,
const a = {
...(condition && {b: 1}) // if condition is true 'b' will be added.
}
Run Code Online (Sandbox Code Playgroud)
Ita*_*oam 37
将扩展语法与布尔值一起使用(如此处建议的那样)是无效的语法。价差只能与可迭代对象一起使用。
我建议以下内容:
const a = {
...(someCondition? {b: 5}: {} )
}
Run Code Online (Sandbox Code Playgroud)
小智 35
性能测试
经典方法
const a = {};
if (someCondition)
a.b = 5;
Run Code Online (Sandbox Code Playgroud)
VS
传播算子方法
const a2 = {
...(someCondition && {b: 5})
}
Run Code Online (Sandbox Code Playgroud)
结果:
经典方法要快得多,因此请注意语法加糖速度较慢。
testClassicConditionFulfilled(); // ~ 234.9ms
testClassicConditionNotFulfilled(); // ~493.1ms
testSpreadOperatorConditionFulfilled(); // ~2649.4ms
testSpreadOperatorConditionNotFulfilled(); // ~2278.0ms
const a = {};
if (someCondition)
a.b = 5;
Run Code Online (Sandbox Code Playgroud)
Lag*_*tos 32
const obj = {
...(condition) && {someprop: propvalue},
...otherprops
}
Run Code Online (Sandbox Code Playgroud)
Dim*_*der 24
如何使用增强对象属性并仅在属性真实时设置属性,例如:
[isConditionTrue() && 'propertyName']: 'propertyValue'
Run Code Online (Sandbox Code Playgroud)
因此,如果不满足条件,它不会创建首选属性,因此您可以丢弃它.请参阅: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'} : {})
};
Run Code Online (Sandbox Code Playgroud)
对我帮助很大.
Nor*_*Lin 16
更好的答案:
const a = {
...(someCondition ? {b: 5} : {})
}
Run Code Online (Sandbox Code Playgroud)
San*_*ath 15
有条件地向对象添加成员
const trueCondition = true;
const falseCondition = false;
const obj = {
...(trueCondition && { student: 10 }),
...(falseCondition && { teacher: 2 }),
};
// { student: 10 }
Run Code Online (Sandbox Code Playgroud)
ice*_*tbr 13
我用另一种选择做了一个小基准。我喜欢消除某些物体的“自重”。通常是虚假值。
\n结果如下benny:
const clean = o => {\n for (const prop in o) if (!o) delete o[prop];\n}\n\nclean({ value });\nRun Code Online (Sandbox Code Playgroud)\nlet a = {\n ...(value && {b: value})\n};\nRun Code Online (Sandbox Code Playgroud)\nlet a = {};\nif (value) {\n a.b = value;\n}\nRun Code Online (Sandbox Code Playgroud)\nclean : 84 918 483 ops/s, \xc2\xb11.16% | 51.58% slower \nspread : 20 188 291 ops/s, \xc2\xb10.92% | slowest, 88.49% slower \nif : 175 368 197 ops/s, \xc2\xb10.50% | fastest\nRun Code Online (Sandbox Code Playgroud)\n
This is probably the shortest solution with ES6
console.log({
...true && {foo: 'bar'}
})
// Output: {foo:'bar'}
Run Code Online (Sandbox Code Playgroud)
console.log({
...false && {foo: 'bar'}
})
// Output: {}
Run Code Online (Sandbox Code Playgroud)
您可以无条件添加所有未定义的值,然后使用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
// }
Run Code Online (Sandbox Code Playgroud)
如果目标是使对象看起来是自包含的并且在一组大括号内,您可以尝试这样做:
var a = new function () {
if (conditionB)
this.b = 5;
if (conditionC)
this.c = 5;
if (conditionD)
this.d = 5;
};
Run Code Online (Sandbox Code Playgroud)
早就有人回答了这个问题,但是查看其他想法我想出了一些有趣的派生:
使用匿名构造函数创建您的对象,并始终将未定义的成员分配给您在最后删除的同一个虚拟成员。这将为每个成员提供一行(我希望不要太复杂)+最后的 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;
};
Run Code Online (Sandbox Code Playgroud)
如果你想做这个服务器端(没有jquery),你可以使用lodash 4.3.0:
a = _.pickBy({ b: (someCondition? 5 : undefined) }, _.negate(_.isUndefined));
Run Code Online (Sandbox Code Playgroud)
这使用lodash 3.10.1
a = _.pick({ b: (someCondition? 5 : undefined) }, _.negate(_.isUndefined));
Run Code Online (Sandbox Code Playgroud)