Because $a and $b refer to the same object. In this particular case you are creating a dynamic object in memory when you use New-Object. You then assign to the variable $a that object. You can now access the object using $a. A little while later you assign $a to $b. You now have 2 variables referring to the same object in memory. Any changes you make to one variable's object will be seen by the other because they both refer to the same object. This is formally known as reference semantics and is a consequence of PS using .NET to work with these objects.
Note that this only applies to non-primitive types and a few others. For example numbers, strings and date-time values do not follow reference semantics and behave how you might expect.
$x = 10
$y = $x
In the above example $x and $y both have a copy of the same value but are otherwise independent. If you know the underlying type of the value then you can determine if it follows value or reference semantics by looking at the type definition.
$a.GetType().IsValueType
Except for perhaps strings and arrays, if it is a value type then it follows value semantics otherwise it follows reference semantics.