Update article.md

Various minor punctuation and phrasing changes.
This commit is contained in:
Peter Roche 2020-11-24 01:59:50 -07:00 committed by GitHub
parent 1e590d693c
commit 58136cb44f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -1,8 +1,8 @@
# Object references and copying
One of the fundamental differences of objects versus primitives is that objects are stored and copied "by reference", as opposed to primitive values: strings, numbers, booleans, etc -- that are always copied "as a whole value".
One of the fundamental differences of objects versus primitives is that objects are stored and copied "by reference", whereas primitive values: strings, numbers, booleans, etc -- are always copied "as a whole value".
That's easy to understand if we look a bit "under a cover" of what happens when we copy a value.
That's easy to understand if we look a bit under the hood of what happens when we copy a value.
Let's start with a primitive, such as a string.
@ -13,7 +13,7 @@ let message = "Hello!";
let phrase = message;
```
As a result we have two independent variables, each one is storing the string `"Hello!"`.
As a result we have two independent variables, each one storing the string `"Hello!"`.
![](variable-copy-value.svg)
@ -21,9 +21,9 @@ Quite an obvious result, right?
Objects are not like that.
**A variable assigned to an object stores not the object itself, but its "address in memory", in other words "a reference" to it.**
**A variable assigned to an object stores not the object itself, but its "address in memory" -- in other words "a reference" to it.**
Let's look at an example of such variable:
Let's look at an example of such a variable:
```js
let user = {
@ -37,13 +37,13 @@ And here's how it's actually stored in memory:
The object is stored somewhere in memory (at the right of the picture), while the `user` variable (at the left) has a "reference" to it.
We may think of an object variable, such as `user`, as of a sheet of paper with the address.
We may think of an object variable, such as `user`, as like a sheet of paper with the address.
When we perform actions with the object, e.g. take a property `user.name`, JavaScript engine looks into that address and performs the operation on the actual object.
When we perform actions with the object, e.g. take a property `user.name`, JavaScript engine looks at what's at that address and performs the operation on the actual object.
Now here's why it's important.
**When an object variable is copied -- the reference is copied, the object is not duplicated.**
**When an object variable is copied, the reference is copied but the object is not duplicated.**
For instance:
@ -57,7 +57,7 @@ Now we have two variables, each one with the reference to the same object:
![](variable-copy-reference.svg)
As you can see, there's still one object, now with two variables that reference it.
As you can see, there's still one object, but now with two variables that reference it.
We can use any variable to access the object and modify its contents:
@ -73,7 +73,7 @@ admin.name = 'Pete'; // changed by the "admin" reference
alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference
```
It's just as if we had a cabinet with two keys and used one of them (`admin`) to get into it. Then, if we later use another key (`user`) we can see changes.
It's as if we had a cabinet with two keys and used one of them (`admin`) to get into it and make changes. Then, if we later use another key (`user`), we are still opening the same cabinet and can see the changed content.
## Comparison by reference
@ -98,7 +98,7 @@ let b = {}; // two independent objects
alert( a == b ); // false
```
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely, usually they appear as a result of a programming mistake.
For comparisons like `obj1 > obj2` or for a comparison against a primitive `obj == 5`, objects are converted to primitives. We'll study how object conversions work very soon, but to tell the truth, such comparisons are needed very rarely -- usually they appear as a result of a programming mistake.
## Cloning and merging, Object.assign
@ -227,10 +227,10 @@ alert(clone.sizes.width); // 51, see the result from the other one
To fix that, we should use the cloning loop that examines each value of `user[key]` and, if it's an object, then replicate its structure as well. That is called a "deep cloning".
We can use recursion to implement it. Or, not to reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
We can use recursion to implement it. Or, to not reinvent the wheel, take an existing implementation, for instance [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) from the JavaScript library [lodash](https://lodash.com).
````smart header="Const objects can be modified"
An important "side effect" of storing objects as references is that an object declared as `const` *can* be modified.
An important side effect of storing objects as references is that an object declared as `const` *can* be modified.
For instance:
@ -246,16 +246,16 @@ user.name = "Pete"; // (*)
alert(user.name); // Pete
```
It might seem that the line `(*)` would cause an error, but no. The value of `user` is constant, it must always reference the same object. But properties of that object are free to change.
It might seem that the line `(*)` would cause an error, but it does not. The value of `user` is constant, it must always reference the same object. But properties of that object are free to change.
In other words, the `const user` gives an error only if we try to set `user=...` as a whole, and that's all.
That said, if we really need to make constant object properties, it's also possible, but using totally different methods, we'll mention that in the chapter <info:property-descriptors>.
That said, if we really need to make constant object properties, it's also possible, but using totally different methods. We'll mention that in the chapter <info:property-descriptors>.
````
## Summary
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object.
Objects are assigned and copied by reference. In other words, a variable stores not the "object value", but a "reference" (address in memory) for the value. So copying such a variable or passing it as a function argument copies that reference, not the object itself.
All operations via copied references (like adding/removing properties) are performed on the same single object.