O que exatamente é a coerção de tipo em Javascript?

122

O que exatamente é coerção de tipo em Javascript?

Por exemplo, no uso de em ==vez de ===?

gespinha
fonte
21
(true == 1) => true/ (true === 1) => false.
VisioN
5
@VisioN seu comentário não ajuda em nada, estou perguntando: "por que" isso acontece?
gespinha 11/11/2013
3
Isso acontece porque o JavaScript foi desenvolvido dessa forma. Meu comentário deve responder à sua pergunta principal: O que exatamente é coerção de tipo em Javascript?
VisioN
6
Via YDJS: "A conversão de um valor de um tipo para outro geralmente é chamada de" conversão de tipo ", quando feita explicitamente, e" coerção "quando feita implicitamente (forçada pelas regras de como um valor é usado)." - github.com/getify/You-Dont-Know-JS/blob/master/…
mattLummus

Respostas:

177

A coerção de tipo significa que quando os operandos de um operador são de tipos diferentes, um deles será convertido em um valor "equivalente" do tipo do outro operando. Por exemplo, se você:

boolean == integer

o operando booleano será convertido em um inteiro: falsetorna - se 0, truetorna-se 1. Em seguida, os dois valores são comparados.

No entanto, se você usar o operador de comparação ===sem conversão, essa conversão não ocorrerá. Quando os operandos são de tipos diferentes, esse operador retorna falsee só compara os valores quando são do mesmo tipo.

Barmar
fonte
1
Como posso colocar isso em uma situação prática? Não devo sempre usar ===quando quero comparar se um valor é igual a outro?
gespinha 11/11/2013
1
Depende do que você está fazendo. Veja a pergunta vinculada.
Barmar
8
@GEspinha bem, essa é a "arte" de usar uma linguagem de digitação livre. Algumas pessoas pensam assim e, em geral, pensam que as linguagens de digitação livre são o flagelo do mundo da programação. No entanto, se você souber o que está fazendo, isso pode tornar um código mais curto e flexível.
Crayon Violent
2
@Barmar Isso também se aplica a > , <?
Royi Namir
2
Uma excelente referência e explicação sobre coerção: github.com/getify/You-Dont-Know-JS/blob/master/…
Greg Bell
56

Vamos começar com uma breve introdução aos sistemas de tipos que acho que irão ajudá-lo a entender a ideia geral de coerção de tipo.

O sistema de tipos de uma linguagem define regras que nos dizem quais tipos de dados existem nessa linguagem e como eles podem ser combinados usando diferentes operadores. Por exemplo, uma dessas regras pode especificar que o operador de mais (+) atua apenas em números. Essas regras existem principalmente para evitar que você dê um tiro no próprio pé. Mas o que acontece quando o programador quebra essa regra no programa? Não há nada que impeça o programador de digitar {} + {}ou“hello” + 5 em um programa, mesmo que a linguagem não ache que essas expressões façam sentido.

O que acontece nessas situações depende de quão estrita a linguagem é sobre suas regras de tipo.

Um sistema de tipos de linguagens costuma ter uma das duas posições sobre você quebrar suas regras:

  1. Diga "Ei, isso não é legal!" e imediatamente travar seu programa.
  2. Diga “Não consigo fazer nada com {} ... mas posso fazer algo com números” e tente converter {} em um número.

As linguagens com sistemas de tipos que assumem a primeira posição sobre suas regras são coloquialmente chamadas de linguagens de “tipo forte”. Eles são rigorosos em não permitir que você quebre suas regras. Aqueles que seguem a segunda abordagem (como JavaScript) são chamados de linguagens “fracamente digitadas” ou “fracamente digitadas”. Claro, você pode quebrar as regras, mas não se surpreenda quando ele converter à força o tipo de dados que você descreveu em seu programa para cumprir suas regras. Esse comportamento é conhecido como ... (rufar os tambores) ... tipo de coerção .

Agora vamos ver alguns exemplos em JavaScript. Primeiro, vamos começar com uma expressão que não leva à coerção de tipo.

5 + 5

Usando o operador + com dois números que é perfeitamente válido. O programa tratará + como significando “somar” e, felizmente, somará os dois números. Nenhuma conversão necessária.

Mas e quanto ...

[] + 5

Uh oh. Em JavaScript,+ pode significar adicionar dois números ou concatenar duas strings. Nesse caso, não temos dois números nem duas strings. Temos apenas um número e um objeto. De acordo com as regras de tipo do JavaScript, isso não faz sentido lógico. Já que ele perdoa por você quebrar as regras, em vez de quebrar, ele tenta entender de qualquer maneira. Então, o que o JavaScript faz? Bem, ele sabe como concatenar strings, então converte tanto [] e 5 em strings e o resultado é o valor de string “5”.

Qual é o problema com os operadores de comparação ==e ===? Por que existem dois operadores de comparação?

==não é imune ao comportamento de conversão de tipo do JavaScript. Expressões como 5 == “5”serão avaliadas como verdadeiras porque o JavaScript tentará converter um deles para que compare o mesmo tipo de dados.

Em muitos casos, isso não é desejável porque você provavelmente deseja saber se alguns dados com os quais está comparando são de um tipo diferente para que você possa decidir o que fazer a respeito. É aí ===que entra o operador. Quando você usa ===, nenhuma conversão de tipo ocorrerá. Portanto, a expressão 5 === “5”será avaliada como falsa.

linstantnoodles
fonte
4
obrigado pela boa explicação, especialmente por "Um sistema de tipo de linguagem geralmente ocupa uma de duas posições"
Humoyun Ahmad
1
Esta deve ser a resposta aceita, pois mostra coerção de tipo automática em múltiplas facetas, não apenas no exemplo de comparação ==. Essa resposta faz um trabalho geral muito melhor de responder à pergunta e remover toda ambiguidade. Obrigado por dedicar seu tempo para escrevê-lo.
o chad
6

Em Python, se você tentar adicionar, digamos, strings e inteiros, obterá um erro:

>>> "hi" + 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects

No entanto, em JavaScript, você não precisa. O 10é convertido em uma string:

> "hi" + 10
"hi10"

"Tipo de coerção" é apenas um termo extravagante para o que está acima. Na verdade, nenhuma das linguagens tem "tipos" no sentido de Java ou C ou outras linguagens com sistemas de tipos estáticos. Como as linguagens tratam as interações entre os vários valores não tipificados estaticamente é uma questão de escolha e convenção.

Claudiu
fonte
1
Acho que há um certo problema com o exemplo que você deu. O que você sugeriu como exemplo para JS funciona perfeitamente com Java e C #. Portanto, de acordo com esta resposta, se alguém concluir que Java e C # suportam coerção de tipo, isso não será totalmente verdadeiro ...
Romeo Sierra
3

deixe-me explicar a coerção de tipo com o seguinte exemplo

Coerção de tipo significa que o Javascript automaticamente (em tempo real) converte uma variável de um tipo de dados para outro

Ex: 123 + "4"geralmente gera um erro, mas em Javascript, devido à coerção de tipo, resulta em 1234uma string

if(23 == "23"){
    console.log(" this line is inside the loop and is executed ");
}

No código acima, por causa da coerção de tipo - JavaScript pensa que 23(número) e "23"(string) são a mesma coisa. isso torna a condição verdadeira e imprime o console.log

No outro caso

if(23 === "23"){
   console.log(" this line is inside the loop and is NOT executed");
}

Em ===caso Javascript não faz Tipo de coerção, e uma vez que 23é um número e "23"é String e por ===estes dois tipos de dados são diferentes e que leva ao falso em condição. Não imprime o console.log

Em palavras simples

Neste caso =, é um operador de atribuição - que atribui valores como var a = 3;, etc

(os operadores abaixo são para comparação)

Neste caso, o ==Javascript converte / coage o tipo de dados para outro e então o compara.

Neste caso, o === Javascript não converte / força o tipo de dados

Para evitar bugs e para fins de depuração, ===é usado principalmente

Informe-me sobre a exatidão das informações acima.

PRagh
fonte
2

O que é coerção:

A coerção de tipo em javascript ocorre quando o mecanismo Javascript precisa realizar uma determinada operação para a qual precisa que os dados estejam em um determinado tipo. Quando o mecanismo encontra dados em um determinado tipo que não é aplicável para a operação, ele coage os dados em um determinado tipo. Isso é necessário porque as variáveis ​​em javascript são digitadas dinamicamente, o que significa que uma determinada variável pode receber um valor de qualquer tipo.

Exemplo:


if(1){
  // 1 gets coerced to true
}


if(4 > '3') {
  // 3 gets coerced into a number
}


44 == "44"  // true, the string 44 gets converted to a nr

Coerção booleana:

Na coerção javascript, todos os valores são convertidos para, trueexceto os seguintes valores que são forçados para false:

console.log(!!"");         // false
console.log(!!0);          // false
console.log(!!null);       // false
console.log(!!undefined);  // false
console.log(!!NaN);        // false
console.log(!!false);      // false

Observe também que no exemplo acima o duplo! operador é usado. O ! O operador de marca força um valor em um booleano com o valor oposto. Podemos usar esse operador duas vezes para converter qualquer valor em um booleano.

Willem van der Veen
fonte
1

a == bsignifica que o javascript será avaliado acom bbase em se os valores podem ser avaliados igualmente. Por exemplo, false == 0será avaliado como verdadeiro porque 0 também é o valor de falso booleano. No entanto, false === 0será avaliado como falso porque comparando estritamente, 0 não é o mesmo valor físico que falso. Outro exemplo é false == ''comparação basicamente livre vs. comparação estrita, porque javascript é uma linguagem de digitação livre. Ou seja, o javascript tentará converter a variável com base no contexto do código, e isso tem o efeito de tornar as coisas iguais se não forem estritamente comparadas. php também tem esse comportamento.

Crayon Violent
fonte
0 is not the same physical value as false. IMO fisicamente falseestá exatamente 0na memória. Eu prefiro dizer que eles são diferentes por tipo, já que falseé booleano, enquanto 0é inteiro.
VisioN
1

A coerção de tipo é o processo de conversão de valor de um tipo em outro (como string em número, objeto em booleano e assim por diante). Qualquer tipo, seja ele primitivo ou um objeto, é um sujeito válido para coerção de tipo. Para relembrar, as primitivas são: número, string, booleano, nulo, indefinido + Símbolo (adicionado no ES6).

Coerção implícita x explícita A coerção do tipo pode ser explícita e implícita.

Quando um desenvolvedor expressa a intenção de converter entre tipos, escrevendo o código apropriado, como Number(value) , isso é chamado de coerção de tipo explícita (ou conversão de tipo).

Como o JavaScript é uma linguagem fracamente tipada, os valores também podem ser convertidos entre diferentes tipos automaticamente e isso é chamado de coerção de tipo implícita. Isso geralmente acontece quando você aplica aos operadores valores de diferentes tipos, como 1 == null, 2/’5', null + new Date(), ou pode ser desencadeada pelo contexto circundante, como com if (value) {…}, onde o valor é coagido para booleano.

Um operador que não aciona a coerção de tipo implícita é ===, que é chamado de operador de igualdade estrita. O operador de igualdade flexível, ==por outro lado, faz comparação e coerção de tipo, se necessário.

A coerção de tipo implícita é uma espada de dois gumes: é uma grande fonte de frustração e defeitos, mas também um mecanismo útil que nos permite escrever menos código sem perder a legibilidade.

Três tipos de conversão A primeira regra a saber é que existem apenas três tipos de conversão em JavaScript:

  • para sequenciar
  • para booleano
  • enumerar

Em segundo lugar, a lógica de conversão para primitivos e objetos funciona de maneira diferente, mas tanto os primitivos quanto os objetos só podem ser convertidos dessas três maneiras.

Vamos começar com os primitivos primeiro.

Conversão de string

Para converter valores explicitamente em uma string, aplique a função String (). A coerção implícita é acionada pelo operador binário +, quando qualquer operando é uma string:

String(123) // explicit
123 + ''    // implicit

Todos os valores primitivos são convertidos em strings naturalmente, como você pode esperar:

String(123)                   // '123'
String(-12.3)                 // '-12.3'
String(null)                  // 'null'
String(undefined)             // 'undefined'
String(true)                  // 'true'
String(false)                 // 'false'

A conversão de símbolos é um pouco complicada, porque só pode ser convertida explicitamente, mas não implicitamente.

String(Symbol('my symbol'))   // 'Symbol(my symbol)'
'' + Symbol('my symbol')      // TypeError is thrown

Conversão booleana

Para converter explicitamente um valor em booleano, aplique a Boolean()função. A conversão implícita ocorre no contexto lógico ou é acionada por operadores lógicos ( || && !).

Boolean(2)          // explicit
if (2) { ... }      // implicit due to logical context
!!2                 // implicit due to logical operator
2 || 'hello'        // implicit due to logical operator

Nota: Operadores lógicos como || and &&fazem conversões booleanas internamente, mas na verdade retornam o valor dos operandos originais, mesmo se eles não forem booleanos.

// returns number 123, instead of returning true
// 'hello' and 123 are still coerced to boolean internally to calculate the expression
let x = 'hello' && 123;   // x === 123

Assim que houver apenas 2 resultados possíveis da conversão booleana: verdadeiro ou falso, é mais fácil lembrar a lista de valores falsos.

Boolean('')           // false
Boolean(0)            // false     
Boolean(-0)           // false
Boolean(NaN)          // false
Boolean(null)         // false
Boolean(undefined)    // false
Boolean(false)        // false

Qualquer valor que não está na lista é convertida true, incluindo object, function, Array, Date, tipo definido pelo usuário, e assim por diante. Os símbolos são valores verdadeiros. Objetos vazios e matrizes também são valores verdadeiros:

Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
!!Symbol()              // true
Boolean(function() {})  // true

Conversão numérica

Para uma conversão explícita, basta aplicar a Number()função, da mesma forma que você fez com Boolean()e String().

A conversão implícita é complicada, porque é acionada em mais casos:

  • operadores de comparação (>, <, <=,> =)

  • operadores bit a bit (| & ^ ~)

  • operadores aritméticos (- + * /%). Observe que o binário + não aciona a conversão numérica, quando qualquer operando é uma string.

  • operador + unário

  • operador de igualdade livre == (incl.! =).

    Observe que == não dispara a conversão numérica quando ambos os operandos são strings.

    Número ('123') // explícito + '123' // 123 implícito! = '456' // 4 implícito> '5' // 5 implícito / nulo // verdadeiro implícito | 0 // implícito

Aqui está como os valores primitivos são convertidos em números:

Number(null)                   // 0
Number(undefined)              // NaN
Number(true)                   // 1
Number(false)                  // 0
Number(" 12 ")                 // 12
Number("-12.34")               // -12.34
Number("\n")                   // 0
Number(" 12s ")                // NaN
Number(123)                    // 123
Tejas Savaliya
fonte
0
var str = 'dude';
console.log(typeof str); // "string"
console.log(!str); // false
console.log(typeof !str); // "boolean"

Exemplo de uma variável que é inicialmente declarada como uma string sendo forçada a um valor booleano com o! operador

Senhor P
fonte
3
Elabore sua resposta. Respostas apenas em código não são realmente úteis.
cezar
3
pessoalmente acho exemplos de código apenas sucintos, autoexplicativos e muito úteis, acho que é uma questão de opinião pessoal
Senhor P
0

A coerção de tipo é o processo de conversão de valor de um tipo em outro (como string em número, objeto em booleano e assim por diante). Qualquer tipo, seja ele primitivo ou um objeto, é um sujeito válido para coerção de tipo. Para relembrar, as primitivas são: número, string, booleano, nulo, indefinido + Símbolo (adicionado no ES6).

A coerção de tipo pode ser explícita e implícita.

Quando um desenvolvedor expressa a intenção de converter entre tipos escrevendo o código apropriado, como Número (valor), isso é chamado de coerção de tipo explícita (ou conversão de tipo).

Como o JavaScript é uma linguagem fracamente tipada, os valores também podem ser convertidos entre diferentes tipos automaticamente e isso é chamado de coerção de tipo implícita. Geralmente acontece quando você aplica operadores a valores de tipos diferentes, como 1 == null, 2 / '5', null + new Date (), ou pode ser acionado pelo contexto circundante, como com if (value) {... }, onde o valor é forçado para booleano.

aqui está algum exemplo de coerção de tipo implícita:

true + false
12 / "6"
"number" + 15 + 3
15 + 3 + "number"
[1] > null
"foo" + + "bar"
'true' == true
false == 'false'
null == ''
!!"false" == !!"true"
[‘x’] == x
[] + null + 1
[1,2,3] == [1,2,3]
{}+[]+{}+[1]
!+[]+[]+![]
new Date(0) - 0
new Date(0) + 0

leia mais: https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/

Mahdi Salehian
fonte
-2

Se os tipos de dados não forem iguais entre si, então Coercion Happen. como 3 == "3" ou boolen == inteiro

ASAbir
fonte