4 ms·
It doesn't help that many variables are objects, and const means that you cannot reassign the variable, not that you cannot modify it. e.g. const x = {};
by riquito 10y ago
It doesn't help that many variables are objects, and const means that you cannot reassign the variable, not that you cannot modify it.
e.g.
const x = {};
x.foo = 'it works!'
- ggregoire 10y agoMaybe in ES9 we will have immut x = {}; x.foo = 'it doesn't work! :)' At the moment, we can use these libs to achieve it - https://github.com/rtfeldman/seamless-immutable https://github.com/rtfeldman/seamless-immutable - https://github.com/facebook/immutable-js https://github.com/facebook/immutable-js
- BinaryIdiot 10y agoWe don't need any libraries to solve this issue (please don't bring in libraries to do weird stuff like this; that's a dependency that you'll be stuck with forever over your entire codebase for essentially zero reason IMO). Just use `const` + `Object.freeze()`; it'll get you 99.9995% of exactly what you want.
- RussianCow 10y agoI'll give you two reasons: performance and ease of use. When you need a copy of a large object with a small change, performing the copy with native JS is going to be slower than doing it with a specialized data structure like a hash mapped trie[0] (which is what Immutable.js uses). Also, if you're trying to keep your data truly immutable, that copy operation is going to be a pain to write with the built-in tools, whereas it's super easy to return a copy of an object with a change to a single, deeply nested property with Immutable.js. I agree that it's premature to reach for a library before you need it, but let's not pretend there aren't rather large drawbacks to using Object.freeze and Object.assign. [0]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie https://en.wikipedia.org/wiki/Hash_array_mapped_trie
- BinaryIdiot 10y ago> When you need a copy of a large object with a small change, performing the copy with native JS is going to be slower than doing it with a specialized data structure like a hash mapped trie[0] (which is what Immutable.js uses) Fair enough though I'm not convinced you should be hitting this type of use case in your code (kinda inefficient and sounds awkward to make a small change to a large object and yet need both objects to continue to be in memory, separated). At least not typically / frequently. > if you're trying to keep your data truly immutable, that copy operation is going to be a pain to write with the built-in tools, whereas it's super easy to return a copy of an object with a change to a single, deeply nested property with Immutable.js. While it is a little bit of a pain almost every framework and probably half of the libraries in existence on npm have a copy function. I'd like to think it's a rare use case but when it's needed you likely don't have to install a new library to handle a copy operation. > I agree that it's premature to reach for a library before you need it, but let's not pretend there aren't rather large drawbacks to using Object.freeze and Object.assign. I'm not sure anyone was pretending anything of the sort here and I don't understand the assumption of such. There are plenty of drawbacks but I'm also not convinced it doesn't fit the 95% use case.
- RussianCow 10y agoSorry, that might have come off a bit harsh. I was just trying to make the point that Object.freeze doesn't give you nearly 99.9995%, nor even 95%, of what immutable data structures give you. I don't think the apps I'm working on are particularly complex, but if you're using a Flux architecture with something like React/Redux, this is a very common pattern, and it doesn't take long to get to a point where the gains in performance and usability far outweigh the cost of having a dependency. > While it is a little bit of a pain almost every framework and probably half of the libraries in existence on npm have a copy function. The problem isn't just the usability of the copy operation (and even if it were, you still have the performance issue); there is also the problem of JavaScript not enforcing immutability of nested objects with Object.freeze. So if you want to enforce that, you're going to have to call Object.freeze on every child object, which becomes a nightmare to write and maintain.
- dsp1234 10y agoconst x = Object.freeze({ y: { foo: 'bar' } }); x.y.foo = 'baz' console.log(x.y.foo) //baz immutablejs might be overkill, but not having, and using, a recursive freeze is going to bite a lot of people if the advice is just 'const + Object.freeze'.
- BinaryIdiot 10y ago> immutablejs might be overkill, but not having, and using, a recursive freeze is going to bite a lot of people if the advice is just 'const + Object.freeze'. No one should be trying to use a recursive freeze (if they are I would argue their data structure is poorly suited to be immutable). I'm not saying `const` + `Object.freeze()` gets you Immutablejs I'm saying it gets you, likely, what you want / need.
- dsp1234 10y agoOur team was just hit with this: const x = Object.freeze([ {id: 1, value: 'foo'}, {id: 2, value: 'bar'}, {id: 3, value: 'baz'}, ]) ... //Bug in the code x[0].value = 'test' First comment on the bug report was: 'This shouldn't be possible as the array is const and frozen'. their data structure is poorly suited to be immutable An array of object seems completely reasonable. Even an array of objects, where those objects themselves have keys which are objects/arrays doesn't seem unreasonable. We'll just have to agree to disagree.
- BinaryIdiot 10y ago> First comment on the bug report was: > 'This shouldn't be possible as the array is const and frozen'. Yeah const and Object.freeze() are not exactly the most intuitive depending on your level of JavaScript internals knowledge (and even then I don't think const is very intuitive but I digress). > We'll just have to agree to disagree. Fair enough! I would just caution trying to make complex objects immutable; it can be handy if you're developing a library and don't trust the dev on the other side (to a degree, copying may be preferable depending on the context) but it can complicate things and lead to some performance and development pattern issues.
- zbjornson 10y agoThis is the same as a const ptr in C: the pointer can't change but the value it points to can. While it may seem broken it has its uses. Doing deep watches to disallow object mutation would be impossibly expensive (I think?).
- netule 10y agoNot sure if this is valid C syntax, but in C++ you can do something like: type const * const Which is a const pointer to a const type, making both the pointer and the data immutable.
- paradite 10y agoOh I didn't realize that. I assumed that const means immutable. Now I am going back to change all the object declarations to const.
- AgentME 10y ago`const` means that the variable binding itself is immutable. It only affects the variable binding, not the value it points to. If it affected the value it pointed to, what would happen in this type of situation? let x = {}; const y = x; x.a = 5;
- deleted 10y ago[deleted]
- Normal_gaussian 10y agoThis is trivially testable in most browsers inspection tools. The answer is it works fine. x.a === y.a === 5 This is because you are simply declaring the binding of y to the object bound to x constant. This does not impact your ability to rebind x or to alter the contents of the object, it simply prevents you from rebinding y. let x = {a:5} x = {} console.log(x.a) // undefined --- const y = {a:5} y = {} // Uncaught TypeError: Assignment to a constant variable. --- let x = {a:2} const y = x x.b = 12 x = {} x.b = 13 console.log(y) // {a: 2, b:12} console.log(x) // {b: 13}
- AgentME 10y agoThe question was rhetorical to try to demonstrate that it might result in surprising behavior if const just manipulated its values to make them become immutable. If adding the `const y = x;` line made the object referenced in `x` be immutable, then the 3rd line would fail, which I don't is a consequence desired even by people who thought const made things immutable. I guess one alternative idea for how const would work could be an implementation where `x.a = 5` worked but `y.a = 5` failed. But then what happens if you pass `y` into a function which then tries to assign the `a` property on it? Is the const-ness part of the value passed into the function, or is it a property on variable bindings, and you could only pass `y` to functions that accepted a const variable? That kind of function type checking isn't something usual to javascript currently. And then is the const-ness deep? Is `y.foo.a = 5;` blocked? Mutable DOM elements are a big part of javascript. If the object happened to contain a reference to an element that needed to be manipulated, then you won't be able to do something like `y.foo.element.textContent = "new foo content";`. Going down this road it's now getting to be a pretty big feature that doesn't cleanly fit with the rest of the language or common tasks. Maybe the naming is a little unfortunate: Javascript's `const` has more in common with Java's `final` than C's `const`.