Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

252
Vistas
When named ES6 exports are asynchronously mutated, why is the change picked up by importers?

Consider the following example:

// module.mjs

export let member = "initial"

setTimeout(() => { 
  member = "mutated" 
}, 2000)
// index.mjs

import { member } from "./module.mjs"

setInterval(() => { 
  console.log(member) 
}, 300);

If you run index.mjs it prints "initial" a few times and after the 2-second timeout starts printing "mutated".

This is surprising to me. I expected it to just keep printing "initial" since the reference to member has changed. I wouldn't be surprised if my index.mjs looked like this

// index.mjs

import * as allExports from "./module.mjs"

setInterval(() => { 
  console.log(allExports.member) 
}, 300);

The reference to allExports hasn't changed. So by accessing member as a property I have access to the new reference. And fair enough, this produces the same result.

But why does it also work in the first case? Are import references updated every time the context for a function call is constructed? Well, then it should also work with default-exports. However, after adjusting the code like this:

// module.mjs

let member = "initial"

export default member

setTimeout(() => { 
  member = "mutated" 
}, 2000)
// index.mjs

import member from "./module.mjs"

setInterval(() => { 
  console.log(member) 
}, 300);

index.mjs just keeps printing "initial" according to my intuition. Hmm, maybe there is a fundamental difference between default-exports and named-exports. What if I do this:

// module.mjs

export let member = "initial"

setTimeout(() => { 
  member = "mutated" 
}, 2000)
// index.mjs

import * as allExports from "./module.mjs"

let { member } = allExports

setInterval(() => { 
  console.log(member) 
}, 300);

Wow, it keeps printing "initial". This is where I got really confused. I always assumed that

import { member } from "./module.mjs"

is just short for importing all named-exports as an object and then doing destructuring.

So my question is: what underlying principle justifies this unique behavior of named-exports?

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

The reason for this is because technically ES6 modules export and import bindings and not values. When you do:

export let test = 0

You need to think that you are exporting test not 0. That means any change on the variable will be reflected on their imports.

The reason this keeps printing initial:

// index.mjs

import * as allExports from "./module.mjs"

let { member } = allExports

setInterval(() => { 
  console.log(member) 
}, 300);

Is because allExports is a special object. You are creating a new binding here and the value gets copied but you are losing the imported binding.

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda