Introduction

Note that this information comes from You don't know JS! Also, I might move this introduction section to a blog article in future.

Contrary to a popular myth saying that everything in Javascript is made of object, not all value types are actually an object. We have primitive value types:

  1. string
  2. boolean
  3. number
  4. bigint
  5. undefined
  6. null
  7. symbol

And we have objects and its sub-types:

  1. Plain object
  2. Boxed Primitives
  3. Built in objects
  4. Arrays
  5. Regular expression
  6. Functions

Primitive values are not object. We cannot assign a property on them.

javascript

myName = "Hui Beom";
myName.nickname = "Zerro";
// TypeError: Cannot create property 'nickname' on string 'Hui Beom'

In contrary, all objects have property. Property is made up of key/value, also known as property name and property value.

javascript

person = {
    firstName: "Hui Beom"
    lastName: "Kim"
};

In most case, property name is coerced to string value type. Number value type (or integer looking string value) is only exception to this:

javascript

obj1 = {
    42:       "<-- this property name will be treated as an integer",
    "41":     "<-- ...and so will this one",

    true:     "<-- this property name will be treated as a string",
    [myObj]:  "<-- ...and so will this one"
};

If you have noticed in above code, you can compute the property name when defining object literal:

javascript

obj2 = {
    ["2023-" + (month + 1)]: false
}

Concise Property

When defining a object literal, we can use shorthand known as concise property to omit the property name. So instead of this:

javascript

coolFact = "the first person convicted of speeding was going 8 mph";

obj3 = {
    coolFact: coolFact
};

We can use this:

javascript

coolFact = "the first person convicted of speeding was going 8 mph";

obj3 = {
    coolFact
};

Object Spread

We use object spread to retrieve the properties of object and use them in another object as they are defined:

javascript

obj4 = {
    favoriteNumber: 12,
    ...obj5,
    greeting: "Hello!"
}

Note that object spread is shallow. It simply assign the properties from the source object to target object. So if the property value of source object was a reference to another object, the reference is copied over to target object. Both source and target object will have reference to the same object in memory, instead of creating a new object.

Defining properties of an object happens in order. So in above example, if obj5 contains property name called favoriteNumber and greeting, obj5.favoriteNumber will override the obj4.favoriteNumber while obj4.greeting will override obj5.greeting. In other words, later defined properties will override the earlier properties with same property name.

Deep Copy

Deep copying an object is complicated because of many edge cases such as copying DOM element, function or cases of circular reference. There is no single standard for dealing with these corner cases and opinions differ from person to person.

There are 3 ways of handling a deep copy:

  1. Using library
  2. Using JSON.parse(JSON.stringify(..))
  3. Using structuredClone()

JSON.parse(JSON.stringify(..)) does not work with circular reference and values that can't be serialized to JSON (ex. function). structuredClone is more recent addition to Javascript environments (it is not part of Javascript specification). It can handle circular reference and more types of value than JSON round trip, but it still has limitation for supporting functions and DOM elements.