It is relatively easy to start writing Javascript code, but it is hard to write it well. If you are a junior developer who wants to level up your JS skills, it is essential to understand subtle differences and choose the right approach for a task. In this article, I’ll explore three subtle but important aspects of working with objects in JS.
1. Shallow copy vs Deep copy
Cloning an array in Javascript is pretty simple. You just have to use the slice function, and you can get a clone of an array. On the other hand, cloning an object in Javascript is a little bit more complicated. In order to shallow copy an object, you can use either Object.assign()
or the spread operator (See below for more details). As you can see from this example, the category
property is unchanged in all cases. However, the item
property is changed when you clone an object using the spread operator, but not when you clone it using the deep copy methods.
Many people use JSON.parse(JSON.stringify())
to deep clone an object. However, the solution is not perfect. This approach loses the properties whose values are undefined. There are more cases where the approach does not correctly copy properties. You can find the full list here. The easiest way to deep clone an object correctly is to use a third-party library like lodash in my opinion. If you are writing JavaScript in Node.js, then you can implement deep cloning using native functions like: v8.deserialize(v8.serialize(obj))
, but you cannot use this in a browser.
2. Take advantage of inline caching
The above two sets of code essentially do the same thing. The only difference is that the first example changes the shape of the object dynamically and the second example initializes the shape of the object at the beginning. These two approaches have different effects on compiler performance. In short, the first example creates lots of intermediate shapes of an object as you add more properties to the object. This makes it harder for JS compilers to apply inline caching. Especially if you are writing server-side code that frequently modifies the shape of the request object, then the effect on performance is not negligible. Whenever you find yourself adding a property dynamically, think about whether you can initialize the shape of an object. If you want to know more details about compiler optimization, you should read up on these resources:
- JavaScript engine fundamentals: Shapes and Inline Caches
- How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code
3. Object.assign() vs Object spread operator
The differences between Object.assign()
and the spread operator is really subtle, and I’m pretty sure there are senior developers who are not aware of the exact differences. The biggest difference is that the spread operator defines properties, and Object.assign()
invokes the set operator. This statement is not really helpful to understand when you should use one and not the other. If you want to just shallow copy an object, just use the spread operator all the time. If one of the properties of an object is read-only, then Object.assign()
does not let you shallow copy the object, but the spread operator does let you. If you want to learn more about the details, you should check out this blog post.
Objects are the basic component of Javascript because everything is an object in Javascript. Understanding the subtle nuances of handling objects in Javascript will help to bring you to the next level. If you have any questions or requests on what I should cover, feel free to leave a comment.
Happy Coding!
Top comments (0)