Por que (“foo” === new String (“foo”)) é avaliado como falso em JavaScript?

98

Eu ia começar a usar === (triplo igual, comparação estrita) o tempo todo ao comparar valores de string, mas agora acho que

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

é falso e o mesmo com este:

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

Claro:

f == g; // true

Portanto, é recomendado sempre usar == para comparação de strings ou sempre converter variáveis ​​em strings antes de comparar?

Michael Butler
fonte
6
Talvez porque fooseja a string pura e new String("foo")seja a String Object
Danilo Valente
6
É recomendado não criar strings com new String(Completamente inútil) em vez de usar==
Esailija
2
Por que alguém iria querer usar construção como new String("foo")em Javascript em primeiro lugar? Nunca vi esse código em código, ou seja, jQuery ...
Robert Koritnik
2
Você pode usar String(obj)para converter uma string em caixa para a primitiva assim que receber o parâmetro "string". ("foo" === String(new String("foo"))) === true
OrangeDog

Respostas:

126

"foo"é uma string primitiva . (este conceito não existe em C # ou Java)

new String("foo") é um objeto de string em caixa.

O ===operador se comporta de maneira diferente em primitivos e objetos .
Ao comparar primitivas (do mesmo tipo), ===retornará verdadeiro se ambas tiverem o mesmo valor.

Ao comparar objetos, ===retornará verdadeiro somente se eles se referirem ao mesmo objeto (comparação por referência). Assim new String("a") !== new String("a"),.

No seu caso, ===retorna falso porque os operandos são de tipos diferentes (um é primitivo e o outro é um objeto).


Os primitivos não são objetos de forma alguma.
O typeofoperador não retornará "object"para primitivas.

Quando você tenta acessar uma propriedade de um primitivo (usando-o como um objeto), a linguagem Javascript irá encaixotá-lo em um objeto, criando um novo objeto a cada vez. Isso é descrito na especificação .

É por isso que você não pode colocar propriedades em primitivos:

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

Cada vez que você escreve x.property, um objeto de caixa diferenteString é criado.

SLaks
fonte
33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Sampson
1
Interessante, pensei que strings eram objetos em JS.
Cameron Martin
1
@Sarfraz: Quase tudo. Não se esqueça de nulle undefined.
2
if( Object(a) !== a ) { //it's a primitive }
Esailija
1
Java tem primitivos / .Net não
Marcelo De Zen
34

Usando ===,

  • um objeto nunca é igual a nada, exceto outra referência a si mesmo.

  • uma primitiva é igual quando comparada a outra primitiva se seu tipo e valor forem iguais.


fonte
3
new String("foo") === new String("foo")é false:-P
Rocket Hazmat
10

A newpalavra é criminosa aqui ( como sempre , posso dizer) ...

Ao usar new, você expressa explicitamente seu desejo de trabalhar com objeto . Pode ser surpreendente para você, mas isso:

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

... lhe dará um poderoso false. É simples: comparados não são os interiores dos objetos, mas as referências dos objetos. E eles, é claro, não são iguais, pois dois objetos diferentes foram criados.

O que você provavelmente deseja usar é a conversão :

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

... e isso lhe dará, como esperado, truecomo resultado, para que você possa se alegrar e prosperar com seu igual foospara sempre. )

Raina77ow
fonte
2
pergunta rápida sobre como usar isso. Você está chamando String (um construtor?) Sem a palavra-chave 'novo'. Isso não significa que você poluirá o escopo com quaisquer propriedades atribuídas no construtor String? Ou isso não acontece porque o construtor é um código nativo? Em outras palavras, suponha que a função String contenha "this.a = 1;" - isso significa que sua função / objeto agora teria uma propriedade a = 1.
Michael Butler
Suponho (mas não posso dizer com certeza) cada uma das funções do 'construtor de boxing' primeiro verifica seu contexto - e se não for um 'mais novo' (ou seja, um objeto de protótipo), muda para o método de conversão imediatamente. No caso de String seria o toString()método, por exemplo.
raina77ow
4

fooé a string pura e new String("foo")é a String do objeto

Danilo Valente
fonte
2

No REPL node.js ("node" na linha de comando, se 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
fonte