source

JavaScript에서 오브젝트에 구성원을 조건부로 추가하는 방법은 무엇입니까?

nicesource 2022. 11. 24. 20:43
반응형

JavaScript에서 오브젝트에 구성원을 조건부로 추가하는 방법은 무엇입니까?

조건부로 멤버를 추가한 오브젝트를 만들고 싶습니다.간단한 접근법은 다음과 같습니다.

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

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

const a = {
   ...(someCondition && {b: 5})
}
const obj = {
   ...(condition) && {someprop: propvalue},
   ...otherprops
}

라이브 데모:

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

console.log(obj);

순수 자바스크립트에서는 당신의 첫 코드 스니펫보다 더 관용적인 것은 생각할 수 없습니다.

단, jQuery 라이브러리를 사용하는 것이 불가능하지 않은 경우 $.extend()는 문서에서 설명한 바와 같이 요건을 충족해야 합니다.

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

따라서 다음과 같이 쓸 수 있습니다.

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

기대한 (만일, 만일의 경우).conditionBfalse , , , 「 」b에는 존재하지 .a를 참조해 주세요.

다음을 권장합니다.

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

EcmaScript2015에서는 다음을 사용할 수 있습니다.

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

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

비고:

  • Object.assign는 첫 번째 인수를 in-place로 변경하지만 갱신된 오브젝트도 반환합니다.따라서 이 메서드를 더 큰 식에서 사용하여 오브젝트를 더 조작할 수 있습니다.
  • null할 수 undefined ★★★★★★★★★★★★★★★★★」{} 같은 당신은 심지어 제공할 수 있다.0대신, 원시 값은 랩되어 있고 자체 열거 가능한 속성이 없기 때문입니다.

더욱 간결하게

단축할 수Jamie가 한 바와 에는 자체 가능한 없기 때문입니다(@Jamie가 지적한 대로).가변값에는 자체 열거형 속성이 없기 때문입니다).false,0,NaN,null,undefined,''( 제외):

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

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

오브젝트에 멤버를 조건부로 추가하다

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

// { student: 10 }

성능 테스트

클래식한 어프로치

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

확산 연산자 접근법

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

결과:

기존의 어프로치가 훨씬 빠르기 때문에, 구문이 느린 것을 고려해 주세요.

Classic Condition test Classic Condition(클래식 조건) ~(); // ~234.9밀리초
Classic Condition Not Fullfuled1 mstest Classic Condition Not Fulled(); // 493.1 ms
Spread Operator Condition test 확산 연산자 " ~"); // ~2649.4ms
~0msstSpreadOperatorConditionNotFuled() // ~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

보다 심플하게

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

확장 개체 속성을 사용하여 속성을 truthy인 경우에만 설정하는 방법은 다음과 같습니다.

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

따라서 조건이 충족되지 않으면 기본 속성이 생성되지 않으므로 삭제할 수 있습니다.참조: http://es6-features.org/ #Computed Property Names

업데이트: Axel Rauschmayer의 블로그 기사에서 오브젝트 리터럴과 어레이 내에 엔트리를 조건부로 추가하는 방법을 따르는 것이 좋습니다(http://2ality.com/2017/04/conditional-literal-entries.html):

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

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

많은 도움이 되었습니다.

이것이 ES6에서 가장 짧은 솔루션일 것입니다.

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

나는 이렇게 할 것이다.

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

되지 않은 모든 후 " "를 사용할 수 .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 () {
    if (conditionB)
        this.b = 5;

    if (conditionC)
        this.c = 5;

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

이것은 오랫동안 해답이 되어 왔지만, 다른 아이디어를 검토하면서, 나는 몇 가지 흥미로운 파생상품을 생각해 냈다.

동일한 속성에 정의되지 않은 값 할당 후 삭제

익명 생성자를 사용하여 개체를 만들고 맨 마지막에 제거한 동일한 더미 멤버에 정의되지 않은 멤버를 항상 할당합니다.이것에 의해, 멤버 마다 1 행(너무 복잡하지 않은 것을 희망)+ 마지막에 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;
};

나는 다른 하나의 옵션을 가지고 작은 벤치마크를 만들었다.나는 어떤 물건에서 "사체 무게"를 제거하는 것을 좋아한다.보통 거짓된 값입니다.

여기 있습니다.benny★★★★

깨끗한

const clean = o => {
    for (const prop in o) if (!o) delete o[prop];
}

clean({ value });

퍼지다

let a = {
    ...(value && {b: value})
};

한다면

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

이 서버측(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));

다음 코드 조각이 작동합니다.

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

이 방법으로 조건에 따라 엔트리를 추가할 수 있으면 좋겠습니다.오브젝트 리터럴 내에 엔트리를 조건부로 추가하는 방법에 대한 자세한 내용을 참조하십시오.

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)

이것이 내가 생각해 낼 수 있는 가장 간결한 해결책이다.

var a = {};
conditionB && a.b = 5;
conditionC && a.c = 5;
conditionD && a.d = 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);

조건부로 멤버를 추가하는 당신의 첫 번째 접근법은 완벽하다고 생각합니다.가 되고 않은 것에 별로 하지 않습니다.b- 아, 아, 아, 아! - 아, 아, 아!a 「」으로undefined 를될 정도로 간단합니다.undefined사용법을 확인하다for로 루프하다.in교환입니다.하지만 어쨌든, 여러분은 쉽게 필터링을 할 수 있는 함수를 쓸 수 있습니다.undefined회원들.

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

또,deleteoperator를 사용하여 개체를 편집합니다.

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

var a = _.merge({}, {
    b: conditionB ? 4 : undefined,
    c: conditionC ? 5 : undefined,
})
  1. 조건 B가false& conditionC는true,그리고나서a = { c: 5 }
  2. conditionB와 conditionC가 모두true,그리고나서a = { b: 4, c: 5 }
  3. conditionB와 conditionC가 모두false,그리고나서a = {}

개체로 줄 바꿈

이런 게 좀 더 깔끔하고

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

변수 정의 기준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",
      },
    ]
}

내 생각에 이것은 매우 간단하고 쉬운 해결책이다.

디스크립터를 추가하는 경우는, 완전하게 하기 위해서 를 사용할 수 있습니다.주의: 일부러 추가했습니다.enumerable: true그렇지 않으면 그 부동산은 에 표시되지 않을 것이다.console.log()이 접근법의 장점은 여러 개의 새로운 속성을 추가할 경우에도 사용할 수 있다는 것입니다(다만, 모든 속성은 같은 조건에 의존합니다).

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>

언급URL : https://stackoverflow.com/questions/11704267/in-javascript-how-to-conditionally-add-a-member-to-an-object

반응형