getify / You-Dont-Know-JS

A book series on JavaScript. @YDKJS on twitter.
Other
178.28k stars 33.42k forks source link

Values vs References appendix #1655

Closed morgvanny closed 4 years ago

morgvanny commented 4 years ago

Please type "I already searched for this issue": I already searched for this issue Edition: (1st or 2nd) 2nd Book Title: Get Started Chapter: Appendix A Section Title: Values vs. References Question: I could be incorrect on this, but it seems just a bit misleading to me to say that a variable "holds" its own copy of a value. Isn't part of the purpose of strings being immutable primitives that there doesn't need to be multiple copies of duplicate strings? It would seem to me that variables do nothing but point to a location in memory, so if you were to do this:

var myName = "Kyle";

var yourName = myName;

myName = "Frank";

Then you would first create a copy of the pointer (for lack of a better word) so that both myName and yourName independently point to the same exact "Kyle" string in memory. And thus, re-assigning yourName to "Frank" is just stopping that variable from pointing at that string, and instead pointing at another. As far as I know, there is no point in which literally the value "Kyle" is represented in memory twice. So this demo would not actually prove that each variable holds its own entire copy of the value, unless the "value" we're talking about is this sort of invisible behind-the-scenes pointer, rather than the string itself. If that's the case, I think more clarification is needed.

Another example of explaining this I think is here

Primitive Values: Some value types are “primitive”. They include numbers, strings, and a few other types. One peculiar thing about primitive values is that you can’t create more of them, or change them in any way. For example, every time you write 2, you get the same value 2. You can’t “create” another 2 in your program, or make the 2 value “become” 3. This is also true for strings.

This suggests to me that primitive values are never truly "copied," but rather independently referred to. That source is not authoritative - just what I've found to be an approachable explanation (that hopefully is correct).

I'd like to disclaim this again, and say that I could be off here or seeing a contradiction where there isn't a meaningful one - this is just based on my incomplete understanding of how it works, and why it's even beneficial for strings to be immutable. But if I'm understanding the concept incorrectly, I'd appreciate if you could help me see why.

getify commented 4 years ago

You may (or may not?) be correct in asserting an implementation detail (that the engines don't actually copy/duplicate values like strings or numbers). I don't know if all engines do that in all cases, or if there's some nuance in when they do and don't, or if some engines don't do it at all.

But the description in the book is from the perspective of the ergonomics in the code, and the observable behavior. It's simpler to explain that the value was "copied" than to try to layer in an implementation detail like a pointer to some centralized/shared value. In the latter explanation complexity, you have to be also explain why an object that's held by reference can be mutated but a string that's held by pointer cannot.

I don't think that kind of detail is useful to most programmers, and it's especially not a helpful way to present it to those just getting started in JS (which is who the book is for).

morgvanny commented 4 years ago

I see your point. To me, if I'm framing my thinking around primitives vs objects, and always thinking of variables as only being able to point towards either a primitive or an object, it really just becomes a matter of - is this value a primitive or not? - when thinking about if mutation is possible. And then for variables (and object keys as well), the only thing I have to think about is if they can be reassigned or not (var and let vs const).

I don't think it's particularly useful to get to extreme levels of detail either - but there have been some times when I've taught things to beginners which I'm sure were initially helpful - but my mental model was not totally accurate which led to me saying things that weren't correct, even though they may have helped convey a principle that actually was correct and important. Still, when I realized this, I have tried to strip that away, without going deeply into why, or getting stuck in the details. I would think saying something like this, would be both approachable and useful information: Variables always point to values, through assignment. The value they point to can be one of 7 data types - Undefined, Null, Boolean, String, Symbol, Number, and Object. The first 6 are primitives, and thus cannot be mutated. If a variable's value is primitive, the only way to make a change would be to reassign that variable to another value. Objects are a special case, because they can actually be mutated. Objects can get new keys or have them removed, keys can point to new values, or if a key points to an object value, that object can be mutated as well, and so on. This means that if a variable points to an object, that variable can be reassigned, or the object itself can be mutated, while the variable still points to it.

I would add that if this is fully accurate, (I'm reading the specs and the part on primitives seems to imply that it is) this also simplifies "referential equality" because it would mean that always - whether comparing objects or primitives - both sides of the comparison operator literally resolve to/refer to the same thing - not just 2 things that appear equal to each other - otherwise they are not equal.

getify commented 4 years ago

Thanks for your feedback!