Desculpe por responder a uma pergunta mais antiga, mas a razão pela qual você precisa de indefinido e nulo é simples: em uma linguagem de digitação de pato baseada em protótipo, é absolutamente necessário diferenciar entre "este objeto não define um valor para X" e "este objeto diz que X é nada / nulo / vazio ".
Sem essa capacidade, não há como percorrer a cadeia de protótipos e, portanto, a herança não pode funcionar; você deve ser capaz de determinar que obj.someProp é indefinido, para que possa olhar para obj.prototype.someProp e prosseguir na cadeia até encontrar um valor. Se obj.someProp retornasse nulo, não haveria como saber se realmente era nulo ou apenas significava "olhar para o meu protótipo". A única maneira de contornar isso é injetar alguma magia esfarrapada nos bastidores, o que interrompe sua capacidade de mexer nas cadeias de protótipos e fazer vários outros pedaços de magia negra JS.
Como grande parte do Javascript, a ideia de indefinido e nulo parece instável e estúpida no começo, depois absolutamente brilhante depois (depois volta ao instável e estúpida, mas com uma explicação razoável).
Um idioma como C # não será compilado se você acessar uma propriedade que não existe e outros idiomas dinâmicos geralmente lançam exceções em tempo de execução quando você toca em uma propriedade que não existe, o que significa que você deve usar construções especiais para testá-las. Classes Plus significa que quando um objeto é instanciado, você já conhece sua cadeia de herança e todas as propriedades que ele possui - em JS, eu posso modificar um protótipo 15 passos acima da cadeia e essas alterações aparecerão nos objetos existentes.
undefined
e quando usarnull