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
How to handle success and failure in @tanstack/react-query useQuery hook September 16, 2024 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