Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 Modules - why named const exports are not read only

I've been reading about ES modules and experimenting and stumbled upon a case I couldn't explain:

// settings.js
export const FOO = 42;
export const BAR= 5;

// main1.js
import * as settings from './settings';
settings.FOO = 1;

//main2.js
import {FOO, BAR} from './settings'
FOO = 1;

In main1.js I'm able to override the const value through the settings variable, but in main2.js I can't (as expected).

The (theoretical) question is why in the first case it's possible to override the const value? Does creating a "read only view" simply creates properties on a regular object and breaks the original structure?

The practical question would be what's the most effective way to return a collection of constants (or read only properties) from a module? What I had in mind is this:

// settings.js
export default Object.freeze({
  FOO: 42,
  BAR: 5
});

Any thoughts?

EDIT: I'm using Babel.

like image 504
krulik Avatar asked Aug 22 '17 12:08

krulik


People also ask

Can you export Const in JavaScript?

After the export keyword, you can use let , const , and var declarations, as well as function or class declarations. You can also use the export { name1, name2 } syntax to export a list of names declared elsewhere.

Does not provide an export named ES6?

The error "The requested module does not provide an export named" occurs when mixing up default and named ES6 module imports and exports. To solve the error make sure to import default exports without using curly braces and import named exports with curly braces.

How many default exports can a ES6 JS file have?

So the functions and variables defined in the file are private to each file and can't be accessed outside the file until we export them. There are two types of exports: Named Exports: There can be multiple named exports in a single file. Default Exports: There can be only one default export in a single file.

Does not provide an export named default react?

To solve the error "The requested module does not provide an export named 'default'", use the default keyword when exporting a value from a file and don't wrap the corresponding import in curly braces. You can only have a single default export per file.


Video Answer


2 Answers

The other answer is incorrect.

The (theoretical) question is why in the first case it's possible to override the const value?

This is actually entirely independent of const. With ES6 module syntax, you are not allowed to reassign the exported value of a module, from outside the module. The same would be true with export let FOO; or export var FOO;. Code inside the module is the only thing that is allowed to change exports.

Doing settings.FOO = 1 technically should throw an exception, but most compilers don't handle this particular edge case currently.

As an example, you could do

export var FOO;

export function setFoo(value){
  FOO = value;
}

and given this, this is when const becomes useful because it's the same as any other normal JS code. FOO = value would fail if it was declared as export const FOO, so if your module is exporting a bunch of constants, doing export const FOO = 1, FOO2 = 2; is a good way to export constants, it's just that Babel doesn't actually make them immutable.

like image 69
loganfsmyth Avatar answered Oct 06 '22 09:10

loganfsmyth


In this code

import * as settings from './settings';
settings.FOO = 1;

In the above code, you are not assigning directly to the constant variable but a cloned copy in settings.

import * as settings from './settings';
         ^^^^^^^^^^^^
settings.FOO = 1;

But it is not the case in the next code

import {FOO, BAR} from './settings'
FOO = 1;

Here FOO and BAR are constants and you can't assign to it.

like image 30
Sagar V Avatar answered Oct 06 '22 09:10

Sagar V