¿Por qué ("foo" === new String ("foo")) se evalúa como falso en JavaScript?

98

Iba a comenzar a usar === (triple igual, comparación estricta) todo el tiempo al comparar valores de cadena, pero ahora encuentro que

"foo" === new String("foo")

es falso, y lo mismo con esto:

var f = "foo", g = new String("foo");
f === g; // false

Por supuesto:

f == g; // true

Entonces, ¿se recomienda usar siempre == para la comparación de cadenas, o convertir siempre las variables en cadenas antes de comparar?

Michael Butler
fuente
6
Tal vez porque fooes la cadena pura y new String("foo")es la cadena del objeto
Danilo Valente
6
Se recomienda no crear cadenas con new String(Completamente inútil) en lugar de usar==
Esailija
2
¿Por qué alguien querría usar construir como new String("foo")en Javascript en primer lugar? Nunca he visto tal código en código, es decir, jQuery ...
Robert Koritnik
2
Puede usar String(obj)para convertir una cadena en caja a la primitiva una vez que haya recibido su parámetro "cadena". ("foo" === String(new String("foo"))) === true
OrangeDog

Respuestas:

126

"foo"es una cadena primitiva . (este concepto no existe en C # o Java)

new String("foo") es un objeto de cadena en caja.

El ===operador se comporta de manera diferente en primitivas y objetos .
Al comparar primitivas (del mismo tipo), ===devolverá verdadero si ambas tienen el mismo valor.

Al comparar objetos, ===devolverá verdadero solo si se refieren al mismo objeto (comparando por referencia). Por lo tanto, new String("a") !== new String("a").

En su caso, ===devuelve falso porque los operandos son de diferentes tipos (uno es un primitivo y el otro es un objeto).


Los primitivos no son objetos en absoluto.
El typeofoperador no regresará "object"por primitivas.

Cuando intentas acceder a una propiedad de una primitiva (usándola como un objeto), el lenguaje Javascript la encajará en un objeto, creando un nuevo objeto cada vez. Esto se describe en la especificación .

Es por eso que no puede asignar propiedades a las primitivas:

var x = "a";
x.property = 2;
alert(x.property) //undefined

Cada vez que escribe x.property, se crea un objeto en caja diferenteString .

SLaks
fuente
33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Sampson
1
Interesante, pensé que las cadenas eran objetos en JS.
Cameron Martin
1
@Sarfraz: Casi todo. No te olvides de nully undefined.
2
if( Object(a) !== a ) { //it's a primitive }
Esailija
1
Java tiene primitivas / .Net no
Marcelo De Zen
34

Usando ===,

  • un Objeto nunca es igual a nada excepto a otra referencia a sí mismo.

  • una primitiva es igual en comparación con otra primitiva si su tipo y valor son los mismos.


fuente
3
new String("foo") === new String("foo")es false:-P
Rocket Hazmat
10

La newpalabra es un criminal aquí ( como de costumbre , puedo decir) ...

Cuando lo usa new, expresa explícitamente su deseo de trabajar con el objeto . Puede que te sorprenda, pero esto:

var x = new String('foo');
var y = new String('foo');
x === y; 

... te dará un poderoso false. Es simple: comparados no son el interior de los objetos, sino las referencias de los objetos. Y, por supuesto, no son iguales, ya que se crearon dos objetos diferentes.

Lo que probablemente quieras usar es la conversión :

var x = String('foo');
var y = String('foo');
x === y;

... y eso te dará, como se esperaba, truecomo resultado, para que puedas regocijarte y prosperar con tu igual foospara siempre. )

raina77ow
fuente
2
pregunta rápida sobre el uso de esto. Estás llamando a String (¿un constructor?) Sin la palabra clave 'nueva'. ¿No significa esto que contaminará el alcance con cualquier propiedad asignada dentro del constructor String? ¿O eso no sucede porque el constructor es código nativo? En otras palabras, suponga que la función String contiene "this.a = 1;" - eso significa que su función / objeto ahora tendría una propiedad a = 1.
Michael Butler
Supongo (pero no puedo decirlo con certeza) que cada una de las funciones de 'constructor de boxeo' primero verifica su contexto, y si no es una 'nueva' (es decir, un objeto prototipo), cambia al método de conversión de inmediato. En el caso de String, ese sería el toString()método, por ejemplo.
raina77ow
4

fooes la cadena pura y new String("foo")es la cadena del objeto

Danilo Valente
fuente
2

Desde el REPL de node.js ("nodo" en la línea de comandos si está instalado):

> "foo" === (new String("foo")).valueOf()
true
> "foo" === new String("foo")
false
> typeof("foo")
'string'
> typeof(new String("foo"))
'object'
> typeof((new String("foo")).valueOf())
'string'
mda
fuente