Search code examples
javascriptnode.jses6-modulescommonjs

difference between import and require


// test.js file;
let k = 0;
let set = () => {
    k = 1;
};
export { k, set };
// test1.js
import { k, set } from './test.js';

set();
console.log(k); // --> k = 1;

but

// test.js
let k = 0;
let set = () => {
    k = 1;
};
module.exports = { k, set };
// test1.js
let { k, set } = require('./test.js');

set();
console.log(k); // --> k = 0;

What is the reason for this behavior?

Functionally, shouldn't the k value be 1?

(tested by node v21.7.3)


Solution

  • The modern export/import declaration give you an actual reference to the variable. An imported binding just gives you an alias for the same underlying binding in the module that's exporting it. This binding can be mutable, if created with var, let, class or function, but you should do your best not to modify it, this leads to confusing behaviour.

    The older commonjs module system creates module objects that are just plain old objects. You can see the object literal in module.exports = { k, set };, and also module.exports.k = k; would have created a new property on the object that is unrelated to the variable from which it was initialised. Then on import, you again create two entirely new variables with the let { k, set } declaration, they just get initialised once from the module object. There is no live reference to the variables in the other module, and assigning k = 1 has no effect on exports.k or the other k.