ES 6의 객체에서 일부 속성을 가져 오는 원 라이너


153

ES6에서 가장 작은 방식으로 속성을 거의 사용하지 않는 함수를 작성하는 방법은 무엇입니까?

destructuring + 단순화 된 객체 리터럴을 사용하여 솔루션을 생각해 냈지만 해당 필드 목록이 코드에서 반복되는 것을 좋아하지 않습니다.

더 얇은 솔루션이 있습니까?

(v) => {
    let { id, title } = v;
    return { id, title };
}

답변:


124

필드 목록을 반복하지는 않지만 더 얇은 것이 있습니다. 매개 변수의 필요성을 피하기 위해 "매개 변수 파괴"를 사용합니다 v.

({id, title}) => ({id, title})

(이 다른 답변 의 실행 가능한 예제를 참조하십시오 ).

@EthanBrown의 솔루션이 더 일반적입니다. 다음은 Object.assign, 및 계산 된 속성 ( [p]부분) 을 사용하는보다 관용적 인 버전입니다 .

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

configurable열거 할 수없는 속성을 생략하면서 getter 및 setter와 같은 속성의 특성을 유지하려면 다음을 수행하십시오.

function pick(o, ...props) {
    var has = p => o.propertyIsEnumerable(p),
        get = p => Object.getOwnPropertyDescriptor(o, p);

    return Object.defineProperties({},
        Object.assign({}, ...props
            .filter(prop => has(prop))
            .map(prop => ({prop: get(props)})))
    );
}

10
+1 좋은 답변, 토라 자부로; 나를 알게 해 주셔서 감사합니다 Object.assign. es6는 선물이 너무 많은 크리스마스 트리와 같습니다. 휴가가 끝나고 몇 달이 지난 지금도 선물을 찾고 있습니다
Ethan Brown

오류가 발생했습니다 : 속성 설명은 정의되지 않은 개체 여야합니다. 그렇지 filter(...).map(prop => ({[prop]: get(prop)})))않습니까?
끝없는

첫 번째의 경우 pick()구현 당신은 또한 같은 것을 할 수return props.reduce((r, prop) => (r[prop] = o[prop], r), {})
패트릭 로버츠

불행히도 해당 버전의 픽은 흐름이나 타이프 스크립트에서 유형 안전하지 않습니다. 타입 안전을 원한다면 원래 객체의 구조 지정 할당을 해제 한 다음 새로운 객체에 할당하는 방법이 없습니다.
duhseekoh

속성이 객체에 존재하지 않으면 얻을 수 undefined있습니다. 때로는 중요합니다. 그 외에는 좋은 생각입니다.
x-yuri

43

나는 당신의 대답 (또는 torazburo)보다 훨씬 작게 만들 수있는 방법이 없다고 생각하지만 본질적으로 당신이하려는 것은 Underscore의 pick작업을 에뮬레이트하는 것입니다 . ES6에서 다시 구현하기가 충분히 쉽습니다.

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

그런 다음 편리한 재사용 기능이 있습니다.

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');

감사. 이것은 내 질문에 대한 답변이 아니지만 매우 좋은 추가 기능입니다.
kirilloid

7
(어깨를 으쓱는) 그것과 같은 I의 느낌 입니다 솔루션에 대한 답; 더 일반적인 솔루션 은 없습니다 (torazaburo의 솔루션은 추가 동사에서 제거되지만 모든 속성 이름을 두 번 작성해야한다는 근본적인 문제는 솔루션보다 확장 성이 뛰어나다는 것을 의미합니다). 내 솔루션은 적어도 잘 확장됩니다 ... pick기능을 한 번만하면 원하는 많은 속성을 선택할 수 있으며 두 배가되지 않습니다.
Ethan Brown

1
왜 사용 hasOwnProperty합니까? 필드를 직접 선택하면 in더 적절한 것으로 보입니다. 확인을 완전히 생략하고 기본값을으로 설정했습니다 undefined.
Bergi

Bergi, 그것은 합리적인 포인트입니다 ... 프로토 그램 체인의 속성 (메소드가 아닌)이 이상하고 "취약한"것으로 생각하고 (코드 냄새처럼) 기본적으로 필터링하는 것을 선호합니다. 프로토 타입 속성이 필요한 응용 프로그램이 있다면 그 옵션이있을 수 있습니다.
Ethan Brown

json 배열은 어떻습니까!
Rizwan Patel

19

이것을 하나의 라이너로 해결하는 요령은 취해진 접근법을 뒤집는 것입니다. 원래 객체에서 시작하는 대신 orig추출하려는 키에서 시작할 수 있습니다.

Array#reduce하나를 사용하면 각각의 필요한 키를 빈 initialValue함수 에 저장할 수 있습니다.이 객체는 for 함수 로 전달됩니다 .

이렇게 :

const orig = {
  id: 123456789,
  name: 'test',
  description: '…',
  url: 'https://…',
};

const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});

console.log(filtered); // Object {id: 123456789, name: "test"}


11

쉼표 연산자를 사용하는 조금 더 짧은 솔루션 :

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})

console.log(
  pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
)  


이것을 사용하는 방법? 예를 들어 줄 수 있습니까?
Tomas M

1
pick이 스레드 의 다른 기능 과 동일하게 작동 합니다.pick({ name: 'John', age: 29, height: 198 }, 'name', 'age')
shesek


3

객체 해체를 사용하여 기존 객체에서 속성을 언 패킹하고 이름이 다른 변수 ( 처음에는 비어있는 새 객체의 필드)에 변수를 할당 할 수 있습니다.

const person = {
  fname: 'tom',
  lname: 'jerry',
  aage: 100,
}

let newPerson = {};

({fname: newPerson.fname, lname: newPerson.lname} = person);

console.log(newPerson);


(index) : 36 Uncaught SyntaxError : 잘못된 구조 지정 할당 대상
Remzes

@Remzes는 어디서 어떻게 실행하는지 알지 못하지만 SO 코드 편집기와 크롬 개발자 도구에서 잘 작동합니다.
Saksham

나는 jsfiddle을 사용했다
Remzes

귀하의 답변을 약간 개선했지만 OP가 요청한 것보다 여전히 너무 장황합니다. 필드 이름뿐만 아니라 새 개체 이름도 반복합니다.
Dan Dascalescu 5

3

ES6은 질문이 작성된 당시의 최신 사양이었습니다. 이 답변 에서 설명한 것처럼 ES2019에서 ES6보다 키 선택이 상당히 짧습니다.

Object.fromEntries(
  Object.entries(obj)
  .filter(([key]) => ['foo', 'bar'].includes(key))
)

2

현재 자바 스크립트의 객체 속기 구문을 개선 하기 위한 짚맨 제안 이 있는데 ,이를 반복하지 않고 명명 된 속성을 "선택"할 수 있습니다.

const source = {id: "68646", genre: "crime", title: "Scarface"};
const target = {};
Object.assign(target, {source.title, source.id});

console.log(picked);
// {id: "68646", title: "Scarface"}

안타깝게도이 제안은 언제 어디서나 진행되지 않는 것 같습니다. 2017 년 7 월에 마지막으로 편집되었으며 여전히 0 단계 에서 초안을 작성 하여 저자가 도둑질하거나 잊었을 수 있음을 나타냅니다.

ES5 이하 (엄격하지 않은 모드)

내가 생각할 수있는 가장 간결한 속기 는 아무도 더 이상 사용하지 않는 고대 언어 기능 과 관련이 있습니다 .

Object.assign(target, {...(o => {
    with(o) return { id, title };
})(source)});

with명령문은 엄격 모드에서 금지되므로이 방법은 최신 JavaScript의 99.999 %에 쓸모가 없습니다. 이 with기능에 대해 내가 찾은 유일한 중간 정도의 사용이기 때문에 부끄러운 일 입니다. 😀


1

Ethan Brown의 솔루션과 비슷하지만 pick기능이 짧습니다 . 다른 함수 pick2는 조금 길지만 느리지 만 ES6 방식과 비슷한 방식으로 속성 이름을 바꿀 수 있습니다.

const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})

const pick2 = (o, ...props) => props.reduce((r, expr) => {
  const [p, np] = expr.split(":").map( e => e.trim() )
  return p in o ? {...r, [np || p]: o[p]} : r
}, {}) 

사용법 예는 다음과 같습니다.

const d = { a: "1", c: "2" }

console.log(pick(d, "a", "b", "c"))        // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }

1
downvote의 이유는 무엇입니까? 당신을 위해 작동하지 않습니까?
Alexandr Priezzhev 2016 년

0

이 해결 방법이 필요했지만 제안 된 키가 있는지 알 수 없었습니다. 그래서 @torazaburo 답변을 받아 유스 케이스가 향상되었습니다.

function pick(o, ...props) {
  return Object.assign({}, ...props.map(prop => {
    if (o[prop]) return {[prop]: o[prop]};
  }));
}

// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }

0

https://stackoverflow.com/users/865693/shesek 의 감소 접근 방식에서 영감을 얻었습니다 .

const pick = (orig, ...keys) => keys.reduce((acc, key) => ({...acc, [key]: orig[key]}), {})

용법:

pick({ model : 'F40', manufacturer: 'Ferrari', productionYear: 1987 }, 'model', 'productionYear') 결과 : {model: "F40", productionYear: 1987}

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.