简体   繁体   中英

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM