Skip to content

Commit 6844730

Browse files
committed
Expand side effect part 2 discussion
1 parent 5e581f9 commit 6844730

File tree

1 file changed

+32
-12
lines changed

1 file changed

+32
-12
lines changed

README.md

+32-12
Original file line numberDiff line numberDiff line change
@@ -560,31 +560,51 @@ console.log(newName); // ['Ryan', 'McDermott'];
560560
**[⬆ back to top](#table-of-contents)**
561561

562562
### Avoid Side Effects (part 2)
563-
Side effects could also occur from inside a function. In JavaScript, primitives are
564-
passed by value and objects are passed by reference. In the later case, we should be
565-
careful not to change any of these argument's properties.
566-
567-
A possible solution would be to always clone the variable, edit it and return the
568-
clone. There would be cases where you actually want to modify the input object
569-
and this should not be taken as a silver bullet. Furthermore, cloning big objects can
570-
be very expensive in terms of performance.
563+
In JavaScript, primitives are passed by value and objects/arrays are passed by
564+
reference. In the case of objects and arrays, if our function makes a change
565+
in a shopping cart array, for example, by adding an item to purchase,
566+
then any other function that uses that `cart` array will be affected by this
567+
addition. That may be great, however it can be bad too. Let's imagine a bad
568+
situation:
569+
570+
The user clicks the "Purchase", button which calls a `purchase` function that
571+
spawns a network request and sends the `cart` array to the server. Because
572+
of a bad network connection, the `purchase` function has to keep retrying the
573+
request. Now, what if in the meantime the user accidentally clicks "Add to Cart"
574+
button on an item they don't actually want before the network request begins?
575+
If that happens and the network request begins, then that purchase function
576+
will send the accidentally added item because it has a reference to a shopping
577+
cart array that the `addItemToCart` function modified by adding an unwanted
578+
item.
579+
580+
A great solution would be for the `addItemToCart` to always clone the `cart`,
581+
edit it, and return the clone. This ensures that no other functions that are
582+
holding onto a reference of the shopping cart will be affected by any changes.
583+
584+
Two caveats to mention to this approach:
585+
1. There might be cases where you actually want to modify the input object,
586+
but when you adopt this programming practice you will find that those case
587+
are pretty rare. Most things can be refactored to have no side effects!
588+
2. Cloning big objects can be very expensive in terms of performance. Luckily,
589+
this isn't a big issue in practice because there are
590+
[https://facebook.github.io/immutable-js/](great libraries) that allow
591+
this kind of programming approach to be fast and not as memory intensive as
592+
it would be for you to manually clone objects and arrays.
571593

572594
**Bad:**
573595
```javascript
574596
const addItemToCart = (cart, item) => {
575597
cart.push({ item, date: Date.now() });
576-
577-
return cart;
578598
};
579599
```
580600

581601
**Good:**
582602
```javascript
583603
const addItemToCart = (cart, item) => {
584604
const c = Object.assign({}, cart);
585-
605+
586606
c.push({ item, date: Date.now() });
587-
607+
588608
return c;
589609
};
590610
```

0 commit comments

Comments
 (0)