0

I have a module defaultSettingsDefs which defines and exports an object defaultSettings:

/* defaultSettingsDefs.js */

const defaultSettings = {
    theme: 'light',
}

export { defaultSettings }

And I have a class Settings (which handles app settings' changes) which is fed defaultSettings in the constructor like so:

/* index.js */

import { Settings } from './classes/Settings'

import { defaultSettings } from './defs/defaultSettingsDefs'

const settings = new Settings(defaultSettings)

Since defaultSettings is imported from defaultSettingsDefs also in many other places within the app, I tried to make it completely immutable in order to avoid accidental overwrites. So in order to take care of the properties I froze the object within the definition itself:

/* defaultSettingsDefs.js */

const defaultSettings = Object.freeze({
    theme: 'light',
})

export { defaultSettings }

which works fine and doesn't allow overwriting defaultSettings's properties neither from index.js nor, for example, from Settings itself;

Furthermore, overwriting defaultSettings itself (not its properties) from index.js correctly throws an error as expected and desired, since defaultSettings is a module import:

import { Settings } from './classes/Settings'

import { defaultSettings } from './defs/defaultSettingsDefs'

defaultSettings = 1

// throws "Uncaught TypeError: Cannot set property defaultSettings of #<Object> which has only a getter"

however, defaultSettings itself can still be overwritten, e.g., from Settings in the constructor:

/* Settings.js */

constructor(defaultSettings) {
    defaultSettings = 1
}

// doesn't throw any error and messes up my app

First off, I don't quite understand why this happens. Shouldn't defaultSettings's immutability persist when it's passed down to a class?

And secondly, how do I go about fixing this?

Thanks a lot!

8
  • 3
    defaultSettings = 1 is not a mutation of defaultSettings, it is a reassignment of the local variable defaultSettings in the constructor function. Commented Jul 13, 2022 at 20:50
  • @Mulan Yeah I think I'm getting confused here. I don't quite understand the difference between doing that within the class and doing that within index.js though. It would be great if you could shed some light... I'm learning javascript along with react, and I think I'm just confusing the use of references and values here. Commented Jul 13, 2022 at 21:08
  • @kos It's different variables. Maybe it helps to use a different name and write constructor(mySettings) { mySettings = 1; } instead - calling new Settings(defaultSettings) will not try to assign 1 to the global defaultSettings variable. Commented Jul 13, 2022 at 23:20
  • 1
    @Mulan It does, thanks, and as to how Javascript works in that regard - I guess I got the whole pass by value / reference wrong since the start. Thanks a lot for taking the time to draw an illustration for that, I appreciate it! Commented Jul 14, 2022 at 5:08
  • 1
    @kos It's like void* mySettings = defaultSettings in C. You can do either mySettings.theme = 'dark' which parallels mySettings->theme = 'dark' (writing into the pointed-at memory), or mySettings = 1 which parallels mySettings = &(1) (putting a different pointer in the local variable). Commented Jul 14, 2022 at 7:32

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.