I recently read the following in Kyle Simpson's You Don't Know JS: ES6
"[ES6 modules export] actual bindings (almost like pointers) to the identifiers in your inner module definition."
My confusion is how these bindings differ from references...
I understand that a reference in JS is only applicable to non-primitive types (like objects), so that given
let object1 = {a: 1};
let object2 = object1;
object1
and object2
now refer to (they are both references to) the same object.
If I add a property to object2
, I am also adding a property to object1
object2.b = 2;
console.log(object1.b); // 2
And I can see that a binding can apply to both primitive types and non-primitive types
// foo.js
export let count = 1;
export function incrementCount() { count++; }
// bar.js
import {count, incrementCount} from foo;
console.log(count); // 1
incrementCount();
console.log(count); // 2
Is a binding just like a reference, except that primitive values can also share a binding (while references are limited to non-primitive types)?
I feel like I'm missing something here...
A binding is a very generic term for "what a name refers to". Every identifier in a scope is bound to something. Usually they resolve to variables in a variable environment (storage slots in an environment record), but there are exceptions (e.g. with
or the global object).
A reference is a term for a pointer to some kind of structure. For example, objects are known as "reference values" because they reference the container of mutable properties with an identity.
ES6 modules are now introducing a new type of binding, one that was unknown before. It is not a usual variable, but literally a reference to another variable - the one exported from the other module. If the module variable changes, this will be reflected by the import - they both point to the same environment record slot.
An export
declaration adds a mapping from a local name to a name in the module interface, while an import
declaration adds a mapping from a name in the respective module interface to a local name. When a module is instantiated, an indirect binding is created that points to the same environment as the local binding in the exporting module.