Did you know you can attach a key to a JavaScript object that is actually a callable?

For example:


const data = await response.json()

Object.defineProperty(data, 'magic', {
  get: () => {
    return Math.random()
  },
})

console.log({magic: data.magic})

will print:

{ magic: 0.6778944803790492 }

And suppose you want it memoized, you can use this:


const data = await response.json()

let magic
Object.defineProperty(data, 'magic', {
  get: () => {
    return magic ??= Math.random()
  },
})

console.log({magic: data.magic})
console.log({magic: data.magic})
console.log({magic: data.magic})

will print:

{ magic: 0.21367035961590308 }
{ magic: 0.21367035961590308 }
{ magic: 0.21367035961590308 }

Note that it doesn't allow setting. If you do this:


Object.defineProperty(data, 'magic', {
  get: () => {
    return Math.random())
  },
  set: () => {
    throw new Error('Nope!')
  },
})

data.magic = 42

it will print:

Error: Nope!

One thing that bit me today, and much the reason why I'm writing this, is that I had this:


async function getData() {
  const response = await get()
  const data = await response.json()

  Object.defineProperty(data, 'magic', {
    get: () => {
      return Math.random()
    },
  })

  return {...data}
}


// Example use:

const {userName, magic} = await getData()
console.log({userName, magic})

// Will print
// { userName: 'peter', magic: undefined }

This does not work because the magic property is not enumerable. To fix that, make this edit:


  Object.defineProperty(data, 'magic', {
    get: () => {
      return Math.random()
    },
+   enumerable: true,
  })

Now, the same code as above, when you run console.log({userName, magic}) it will print:

{ userName: 'peter', magic: 0.23560450431932733 }

Comments

Your email will never ever be published.

Previous:
Wouter + Vite is the new create-react-app, and I love it August 16, 2024 Node, React, Bun
Next:
swr compared to @tanstack/react-query August 30, 2024 JavaScript
Related by category:
Switching from Next.js to Vite + wouter July 28, 2023 JavaScript
How to SSG a Vite SPA April 26, 2025 JavaScript
An ideal pattern to combine React Router with TanStack Query November 18, 2024 JavaScript
get in JavaScript is the same as property in Python February 13, 2025 JavaScript
Related by keyword:
How to simulate slow lazy chunk-loading in React March 25, 2021 React, JavaScript
React 16.6 with Suspense and lazy loading components with react-router-dom October 26, 2018 Web development, React, JavaScript
Using lazy loading images on Air Mozilla April 23, 2015 Mozilla, JavaScript