Nota: Esto es un laboratorio donde llevo a cabo investigaciones sobre temas que no acabo de entender relacionados con la tecnología, por tanto, puede que haya algún error semántico, si hay algo que te chirría déjame un tweet. ¡Merci!

Quiero ver por qué se dice que todo en Javascript es un objeto

Parecer ser que en Javascript hay 9 tipos de objetos nativos, son:

Number()
String() 
Boolean()
Error()
RegExp()
Date()
Array()
Function()
Object()

De estos 9 objetos 3 de ellos tienen algo que los otros 6 no. Es lo que se denomina primitivo literal que en teoría esto dota a ciertos datos a ser objetos y usar los métodos de su objeto nativo, son Number(), String() y Boolean().

Para crear un literal basta con asignarle a una variable un valor de tipo number, string o booleano.

var miString = "hola";

También podemos asignar a una variable la instancia de ese objeto nativo:

var miStringNativo = new String("hola");

La diferencia en sintaxis es enorme pero ¿qué sucede por debajo?

Si comparamos ambas varibles vemos que tienen el mismo contenido, pero no tienen el mismo tipo (typeof) esto se consigue comparando ambas varialbes con el doble operador == y con el triple === que también tendrá en cuenta el tipo a la hora de evaluar.

console.log( miString == miStringNativo ) 
//--> true

console.log( miString === miStringNativo )
//---> false

Ahora vamos a ver el tipo de uno y de otro:

console.log( typeof( miString ) ) 
//--> string

console.log( typeof( miStringNativo ) ) 
//---> object

Aha! aquí vemos que el tipo del nativo es un objeto mientras que el literal no es un objeto es un string pero ¿no era todo en Javascript objetos?

Seguimos, vamos a sacar por consola el valor de cada variable.

console.log( miString ) 
//--> hola

console.log( miStringNativo ) 
//---> String {0: "h", 1: "o", 2: "l", 3: "a", length: 4, [[PrimitiveValue]]: "hola"}

Hmm! En este caso el “literal” me ha pintado lo que esperaba pero, espera un momento, mira la información que nos trae el nativo.

[[PrimitiveValue]]: "hola"

Parece que para determinados objetos nativos tenemos algo de información adicional. Vamos a ver si esto funciona para otros tipos de objetos nativos, por ejemplo, Error().

var error = new Error();

console.log( error );
/*--> Error {stack: (...)}stack: (...)
     get stack: function () { [native code] }
     set stack: function () { [native code] }
     __proto__: ...
*/

¡Nada que ver!

Y si probamos con Number() y Boolean()?

var miNumero = new Number(3);
var miBool = new Boolean(true);

console.log(miNumero);
//--> Number {[[PrimitiveValue]]: 4} 

console.log(miBool);
//--> Boolean {[[PrimitiveValue]]: true}

Así que para estos 3 objetos nativos tenemos una información adicional que se refiere a los valores primitivos. Supongo que aunque sean literales podré usar los métodos del objeto nativo, vamos a verlo.

var miString = "hola";
console.log( miString.indexOf('h') );
//--> 0

var miNumero = 13.3714;
console.log( miNumero.toPrecision(2)  ) 
//--> 13 

var miBool = true;
console.log( miBool.toSource() )
//--> true

¡Efectiviwonder! Se puede usar los métodos de su objeto nativo.

Conclusión

Así que hay 3 tipos de objetos que pueden ser declarados de forma literal, estos son los Number(), String() y los Boolean(). Esto nos facilita a la hora de trabajar con ellos y supongo que a nivel de rendimiento de Javascript también será importante ya que estas variables no serán objetos a no ser que se necesite alguno de los métodos y entonces sí Javascript los transforma en objetos. Así que según esto que he visto y sin tenerlo del todo claro, si un primitivo literal no es considerado un objeto a no ser que necesitemos que sea, todo en javascript puede ser un objeto pero hay cosas que pueden no serlo, al menos por un tiempo.

¡Feliz código!