Vamos dar uma olhada no que está acontecendo:
var abc = { a: 10, b: 20};
Um novo objeto é criado na memória e atribuído à variável abc.
var def = [];
Um novo array é criado na memória e atribuído à variável def.
def.push(abc);
Dentro da matriz, agora há um ponteiro para o objeto criado anteriormente.
abc.a = 100;
def[0].a; // outputs 100!
Obviamente certo. Estamos modificando o objeto, que também é referenciado pelo array.
abc = { a: 10000, b: 20000 };
Novamente, um novo objeto é criado e uma referência a ele é armazenada em abc. Agora temos dois objetos (e um array) na memória.
def[0].a; // still 100, no change this time
Claro, isso ainda é 100. O ponteiro do array ainda faz referência ao primeiro objeto criado e não ao segundo.