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.