Update article.md
Various minor punctuation and phrasing changes.
This commit is contained in:
parent
1e590d693c
commit
58136cb44f
1 changed files with 16 additions and 16 deletions
|
@ -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!"`.
|
||||
|
||||

|
||||
|
||||
|
@ -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:
|
|||
|
||||

|
||||
|
||||
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.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue