You have to differentiate between the object and the reference to that object. Variables obj
and otherObj
just hold a reference to the object, a pointer pointing to it in memory. They are not copies of the object, and they are not the same object. They point to the same object.
To illustrate this more clearly, I'll explain this line-by-line. When you do:
let obj = {
prop: 'one'
}
You're creating a new reference, like this:

obj
just points to a spot in memory where the object resides, called a reference. Next, you do:
let otherObj = obj
Which is equivalent to this:

Here, you assign the reference of obj
to otherObj
. They now both refer to the same object in memory, though they are completely independent of each other. otherObj
is a shallow copy of obj
's reference, so they both refer to the same object but are separate. Per the link:
In that case a new object B is created, and the fields values of A are copied over to B.
[...]
If the field value is a reference to an object (e.g., a memory address) it copies the reference, hence referring to the same object as A does
Finally you do this:
obj = null
Which is like this:

The reference from obj
to the object in memory is essentially severed and obj
now points to null
, or nothing. Since obj
and otherObj
were independent of each other, nothing happens to otherObj
and it still points to the object in memory. obj
and otherObj
are separate references themselves, but refer to the same object. When you modify the object in memory, it's reflected on both references, but when you modify a reference by breaking the reference to the memory location, nothing happens to the other.