Javascript에서 조건부로 객체를 멤버에 추가하는 방법은 무엇입니까?


385

조건부로 추가 된 멤버로 객체를 만들고 싶습니다. 간단한 접근 방식은 다음과 같습니다.

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

이제 더 관용적 인 코드를 작성하고 싶습니다. 나는 노력하고있다 :

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

그러나 지금 ba그 가치가 의 멤버입니다 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),
 };

23
그렇습니다. 코드의 첫 번째 비트
Paolo Bergantino

5
관용적 자바 스크립트와 같은 것이 있는지 잘 모르겠습니다.
Michael Berkowski

실제로 중요합니까? 정의하지 않은 경우 a.b검색 a.b하면 undefined어쨌든 반환 됩니다.
Teemu

5
@Teemu : in운영자가 사용될 때 중요 할 수 있습니다.

1
현재 리터럴 객체에 조건부 속성을 가질 수있는 방법은 없지만 ES7에서 추가하기를 원합니다. 특히 서버 측 프로그래밍에 매우 유용 할 수 있습니다!
Ali

답변:


118

순수한 Javascript에서는 첫 번째 코드 스 니펫보다 관용적 인 것을 생각할 수 없습니다.

그러나 jQuery 라이브러리를 사용하는 것이 문제가 아닌 경우 설명서 에서 다음과 같이 $ .extend () 가 요구 사항을 충족해야합니다.

정의되지 않은 속성은 복사되지 않습니다.

따라서 다음과 같이 작성할 수 있습니다.

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

그리고 (경우에 당신이 기대하는 결과를 얻을 수 conditionB있다 false, 그 다음 b에 존재하지 않습니다 a).


21
jQuery가 필요없는 훨씬 더 좋은 방법이 있습니다. Jamie Hill의 답변을 살펴보십시오.
앤드류 라스무센

13
@Andrew, 그 대답에는 ES6이 필요합니다. ES6은 필자가 작성한 당시에는 존재하지 않았습니다.
프레데릭 하 미디

null도 같은 방식으로 작동합니까? 아니면 정의되어 있지 않아야합니까?
Aous1000

jQuery를 사용하기 때문에 실제로 잘못된 대답입니다.이 삼항 조건은 객체에서 속성을 제거하지 않으며 속성을 정의되지 않은 것으로 설정합니다. 올바른 방법은 @lagistos 답변을 참조하십시오
Alexander Kim

아래의 Jamie의 답변을 확인하십시오. stackoverflow.com/a/40560953/10222449
MadMac

868

@InspiredJW가 ES5로 그렇게했다고 생각합니다. @ trincot이 지적했듯이 es6을 사용하는 것이 더 나은 방법입니다. 그러나 스프레드 연산자와 논리적 AND 단락 평가를 사용하여 설탕을 조금 더 추가 할 수 있습니다.

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

2
이것이 올바른지 잘 모르겠습니다. 제안서에 따르면 무시 Null/Undefined Are Ignored되지 않습니다 false. 트랜스 파일러는 현재이를 통해이를 허용 할 수 있지만 호환됩니까? 다음은 작아야 {...someCondition ? {b: 5} : null}하지만 컴팩트하지는 않습니다.
Benjamin Dobell

23
나는 이것이 스프레드 제안을 한 사람들에게 유효한지 물었고 그들은 이것이 좋다고 말했다. github.com/tc39/proposal-object-rest-spread/issues/45 , cc @BenjaminDobell
김민준

73
@AlanH 스프레드 연산자는 속기 Object.assign및 && 연산자보다 우선 순위가 낮습니다. 속성이없는 값 (부울, null, 정의되지 않은 숫자)을 무시하고 그 ...자리에 객체의 모든 속성을 추가합니다 . &&연산자는 true이면 올바른 값을, 그렇지 않으면 false를 반환한다는 것을 기억하십시오 . 따라서 someConditiontrue 인 경우 연산자에 {b : 5}전달되어 ...속성 bavalue 에 추가합니다 5. 되고 someCondition거짓, false받는 전달 될 ...연산자. 아무것도 추가되지 않았습니다. 영리하다. 나는 그것을 좋아한다.
Félix Brunet

11
큰 대답이지만 조건과 결과 객체를 괄호로 묶으면이 예제의 가독성이 크게 향상됩니다. 모든 사람이 JS 연산자 우선 순위를 기억하는 것은 아닙니다.
신경 전달 물질

6
유일한 다른 문제는 거짓 부울에 사용할 수 없다는 것입니다.
ggb667

92

EcmaScript2015를 사용하면 다음을 사용할 수 있습니다 Object.assign.

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

일부 비고 :

더 간결한

(@Jamie는 지적 아웃이로) falsy 값이 더 자신의 열거 속성이 없기 때문에, (다음과 같이 상기 제 2 지점을 가지고 가서, 당신은 그것을 줄일 수 false, 0, NaN, null, undefined, ''제외 document.all) :

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


1
나는 초기 해결책을 선호한다 : 무슨 일이 일어나고 있는지 쉽게 알 수있다 – (적어도 사양을 보지 않고는) 원시 값으로 어떤 일이 일어나는지 확신 할 수 없다.
Axel Rauschmayer

1
삼항 논리를 단순화하는 속기를 좋아합니다. 이것이 바로 내가 필요한 것입니다. 감사합니다!
theUtherSide

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

라이브 데모 :

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

console.log(obj);


7
이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 귀하의 코드 제안 이유를 모를 수도 있습니다.
Ralf Stubner


cond가 이것보다 일치하지 않으면 undefined를 반환합니다.
Mustkeem K

2
이것은 효과가 있으며 다른 답변 IMO보다 구문이 좋습니다.
Seph 리드

1
"..."spread 연산자는 객체 리터럴을 해체하고이를 "obj"에 추가합니다. 예를 들어이 경우에는 ... (true) && {someprop : 42}입니다. 해체 될 전체 용어는 "(true) && {someprop : 42}",이 경우 부울은 true이고이 용어는 {someprop : 42}를 생성하여 해체되어 obj에 추가됩니다. 부울이 대신 거짓이면, 그 용어는 단지 거짓 일 것이고, 아무것도 해체되어 obj에 추가되지 않을 것입니다.
Qiong Wu

50

부울과 함께 스프레드 구문을 사용하는 것은 (여기에서 제안한대로) 유효한 구문이 아닙니다. 확산은 iterables 에만 사용할 수 있습니다 .

나는 다음을 제안한다.

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

2
@HossamMourad, 제안 된 코드가 이미 2 년 전에 게시 된 답변에 사용되었으므로 그렇게해서는 안됩니다. 그리고 첫 번째 말은 거짓입니다. 이것은 유효한 구문입니다.{...false}
trincot

1
@Itai, 이것은 사실이 아닙니다. 스프레드 구문과 함께 사용하면 기본 값이 줄 바꿈됩니다. {...false}유효한 구문입니다.
trincot

@trincot, 당신은 참조를 제공 할 수 있습니까?
Itai Noam

3
EcmaScript 2018 언어 사양, 섹션 12.2.6 (.8) CopyDataProperties은 값에 대해 수행 되도록 지정합니다 ( false이 경우). 여기에는 프리미티브 복싱이 포함됩니다 (섹션 7.3.23, 7.1.13). MDN에 대한 링크는이 "예외"를 괄호로 언급합니다.
trincot

참고로, 같은 주제로 확장 한이 게시물 도 참조하십시오 .
trincot

26

Enhanced Object Properties를 사용하고 속성이 진실 인 경우에만 설정하는 방법은 다음과 같습니다.

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

따라서 조건이 충족되지 않으면 선호하는 속성이 생성되지 않으므로 버릴 수 있습니다. 보다: http://es6-features.org/#ComputedPropertyNames

업데이트 : 객체 리터럴 및 배열 ( http://2ality.com/2017/04/conditional-literal-entries.html ) 에 조건부로 항목을 추가하는 방법에 대한 블로그 기사에서 Axel Rauschmayer의 접근 방식을 따르는 것이 훨씬 좋습니다 .

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

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

나에게 많은 도움이되었다.


1
거의 작동합니다. 문제는 추가 false키를 추가한다는 것입니다 . 예를 들어, {[true && 'a']: 17, [false && 'b']: 42}{a:17, false: 42}
viebel

3
나는 더 간결한 방법을 발견 : ...isConditionTrue() && { propertyName: 'propertyValue' }
디미트리 Reifschneider에게

더 좋은 방법 : ... (isConditionTrue ()? {key : 'value'} : {})
Dimitri Reifschneider

Axel Rauschmayer 블로그 링크가이 답변을 제공합니다. 기사의 "... insertIf (cond, 'a')"예제는 내가 찾던 것과 정확히 일치합니다. 감사합니다
Joseph Simpson

20

더 단순화

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

5

목표가 객체가 독립적으로 나타나고 한 세트의 중괄호 안에 있도록하는 것이라면 다음과 같이 시도하십시오.

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

    if (conditionC)
        this.c = 5;

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

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

ES6에는 lodash가 필요 없습니다.
Dan Dascalescu

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

조건에 따라 항목을 추가하는 가장 효율적인 방법이기를 바랍니다. 객체 리터럴 내에 조건부로 항목을 추가하는 방법에 대한 자세한 내용은.


3
[...condition?'':['item']]이것은 배열에 문자열 항목을 추가합니다
Wayou

이 답변 은 1 년 전의 Jamie Hill의 답변 보다 나은 점은 무엇입니까?
Dan Dascalescu

1
@ DanDascalescu Jamie Hill의 대답은 내 대답보다 낫습니다. 나는 그런 식으로 생각하지 않았으며 3 원 연산자가 더 많았습니다.
Madhankumar

4

이것은 오랫동안 대답했지만 다른 아이디어를 살펴보면 흥미로운 파생 상품을 생각해 냈습니다.

정의되지 않은 값을 동일한 속성에 할당하고 나중에 삭제

익명 생성자를 사용하여 객체를 만들고 정의되지 않은 멤버를 맨 끝에 제거 하는 동일한 더미 멤버에 항상 할당 하십시오. 이렇게하면 회원 당 한 줄 (너무 복잡하지는 않지만) + 한 줄에 추가 줄이 생깁니다.

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

4

조건없이 정의되지 않은 모든 값을 추가 한 다음이를 사용 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
// }

2

나는 이것을 할 것이다

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

한 줄 코드 버전으로 편집


조건이 거짓이면, a가 정의되지 않은 것입니다.
bingjie2680

@ bingjie2680 그렇지 않은 것이 분명 무슨 A는 경우이어야한다 someCondition은 false입니다. 방금 가정했습니다 a = undefined. 다음과 return { b: undefined };같이 쉽게 변경할 수 있습니다 : /
jwchang

@ bingjie2680는 그 다음이어야 return {};else일부
jwchang

1
그건 당신이 정말로 할 일이 아닙니다. 그렇 습니까? 문자 그대로 전체 리터럴 구문을 조건부로 작성하더라도 조건부 연산자를 사용하지 않는 이유는 무엇입니까? a = condition ? {b:5} : undefined;

3
축하합니다, 당신은 3 개의 데드-간단한 라인을 7- 라인 함수로 바꾸지 않았습니다. 아니요, 익명 기능을 사용하는 것은 이점이 아닙니다.

2

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)

0

조건부로 멤버를 추가하는 첫 번째 방법은 완벽하게 좋습니다. 나는 가치 가있는 회원 b을 원하지 않는다는 것에 동의하지 않습니다 . 연산자 로 루프를 사용 하여 점검 을 추가하는 것은 간단 합니다 . 그러나 어쨌든 멤버 를 필터링하는 함수를 쉽게 작성할 수 있습니다 .aundefinedundefinedforinundefined

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연산자를 사용 하여 객체를 제자리에서 편집 할 수도 있습니다 .


0

객체로 감싸기

이 같은 것은 조금 더 깨끗합니다

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

0

이것은 내가 얻을 수있는 가장 간결한 솔루션입니다.

var a = {};
conditionB && a.b = 5;
conditionC && a.c = 5;
conditionD && a.d = 5;
// ...

-1

lodash 라이브러리를 사용하면 사용할 수 있습니다 _.merge을

var a = _.merge({}, {
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
})
  1. conditionB가 false& conditionC가 true인 경우a = { c: 5 }
  2. 조건 b & conditionC 둘 경우 true, 다음a = { b: 4, c: 5 }
  3. 조건 b & conditionC 둘 경우 false, 다음a = {}

다른 결과가 나옵니다. 을 사용하고 lodash@^4.0.0있습니다. undefined내 경우에 포함됩니다.
JohnnyQ
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.