Alternatives to Mutating Objects
A common problematic coding practice is mutating objects that the namespace doesn’t own. When you mutate an object, you add or remove properties of the object or change values of properties. You change the "shape" of the object. When you mutate an object in a component that’s running in LWS, that change isn’t propagated outside the namespace sandbox, which leads to errors.
Mutations can cause values to be undefined
. For more information, see Properties Evaluate as undefined in LWS.
This section discusses alternatives to mutations on these properties.
- Function arguments
- Class instance properties
- Objects received in events
In this example, a function foo()
mutates the argument obj
by adding a property with value foo
. Then foo()
calls otherFunction
, which expects that prop = foo
is defined on obj
.
This mutation is problematic because foo()
can receive obj
from different callers. Then foo()
can send obj
to different consumers that expect obj
to be differently shaped. Mutating obj
introduces uncertainty and inconsistency. A change could unknowingly break other code, especially when the code base is large and complex.
Instead of adding a property to an object, create a shallow clone with relevant properties of the object. In the example code, refactor foo()
to create a clone of the object and add prop
to the clone.
Here’s a single-line change that removes the mutation by using a cloned object.
For classes, we recommend exposing getters and setters for properties that can be mutated. Avoid directly mutating class properties that are used for computations.
JavaScript now supports private class fields. A best practice in any object-oriented programming language is to define all internal state properties as private, and expose getters and setters only for the properties that external code can mutate.
For events, there’s no easy workaround because events propagate through the DOM.
Possible solutions are:
- Clone the event data, mutate it, and redispatch the same event but with the new data.
- Clone the event data, mutate it, and dispatch a new event with a different name.
See Also