Selective object destructuring with assignment in JavaScript?

870 views Asked by At

I've stumbled several times already upon the following problem:

Let's assume we have the following object:

const book = {
  "title" : "The Pillars of the Earth",
  "author" : "Ken Follet",
  "year" : 1989,
  "genres" : ["fiction", "historical"]
}

I would like to extract on-the-fly only part of the information from the object. Obviously, I cannot use the Object.assign because it's going to copy all the properties. The fastest, but not very elegant way of doing it I've found so far is destructuring and then the concise syntax for creating an object, for example:

let {title, author} = book;
let displayInfo = {title, author};

It works, though it's not very elegant, mostly because as a side-effect I've just created the title and author variables, which I probably don't really need.

Is there a smarter, more concise syntax for this operation? Like a secret one-liner?

Thank you in advance!

3

There are 3 answers

0
T.J. Crowder On BEST ANSWER

In terms of destructuring, it doesn't get a lot better:

let displayInfo = {};
({title: displayInfo.title, author: displayInfo.author} = book);

Live Example:

const book = {
  "title" : "The Pillars of the Earth",
  "author" : "Ken Follet",
  "year" : 1989,
  "genres" : ["fiction", "historical"]
};

let displayInfo = {};
({title: displayInfo.title, author: displayInfo.author} = book);

console.log(displayInfo);

But you can give yourself a helper function:

function pick(source, ...props) {
    const obj = {};
    for (const prop of props) {
        obj[prop] = source[prop];
    }
    return obj;
}

then it's:

let displayInfo = pick(book, "title", "author");

Live Example:

const book = {
  "title" : "The Pillars of the Earth",
  "author" : "Ken Follet",
  "year" : 1989,
  "genres" : ["fiction", "historical"]
};

function pick(source, ...props) {
    const obj = {};
    for (const prop of props) {
        obj[prop] = source[prop];
    }
    return obj;
}

let displayInfo = pick(book, "title", "author");

console.log(displayInfo);

5
Nick On

One option is to combine the rest operator with destructuring to pluck out the properties you don't want, leaving the rest of them in your new object.

const book = {
  "title" : "The Pillars of the Earth",
  "author" : "Ken Follet",
  "year" : 1989,
  "genres" : ["fiction", "historical"]
}

const { year, genres, ...displayInfo } = book;

console.log(displayInfo);

0
GiorgiosJames On

A handy one-liner function using Array.prototype.reduce.

const cherryPick = (obj, attrToPick) => attrToPick.reduce((a, e) => ((a[e] = obj[e]), a), {});

Usage

const book = {
  "title" : "The Pillars of the Earth",
  "author" : "Ken Follet",
  "year" : 1989,
  "genres" : ["fiction", "historical"]
}

const attrToPick = ['title', 'author'];

cherryPick(book, attrToPick);

// result
// {
//   "title": "The Pillars of the Earth",
//   "author": "Ken Follet"
// }