Desafio JavaScript

Comparação com Object.is e coerção

Enunciado

Crie uma função comparar(a, b) que retorna um objeto com três propriedades: frouxa (resultado de a == b), estrita (resultado de a === b) e objectIs (resultado de Object.is(a, b)). Teste com pares de valores que evidenciem as diferenças: NaN e NaN, -0 e 0, '1' e 1, null e undefined, [] e [].

Requisitos

  • A função deve retornar um objeto com as chaves frouxa, estrita e objectIs.
  • Imprima os resultados para cada par no formato a, b => { frouxa: ..., estrita: ..., objectIs: ... }.
  • Use Object.is corretamente, sem implementar manualmente.

Código inicial

// Complete a função comparar
function comparar(a, b) {
  // retorne um objeto com frouxa, estrita e objectIs
}

// Teste com os pares

Saída esperada

NaN, NaN => { frouxa: false, estrita: false, objectIs: true }
-0, 0 => { frouxa: true, estrita: true, objectIs: false }
'1', 1 => { frouxa: true, estrita: false, objectIs: false }
null, undefined => { frouxa: true, estrita: false, objectIs: false }
[], [] => { frouxa: false, estrita: false, objectIs: false }
Ver dica

Para representar os valores na saída, use uma função auxiliar que trate NaN, -0, arrays e strings de forma legível.

Mostrar solução
// Função que compara dois valores de três formas
function comparar(a, b) {
  return {
    frouxa: a == b,       // igualdade frouxa (com coerção)
    estrita: a === b,     // igualdade estrita (sem coerção)
    objectIs: Object.is(a, b) // igualdade SameValue
  };
}

// Função auxiliar para representar valores na saída
function representar(v) {
  if (typeof v === 'string') return `'${v}'`;
  if (Array.isArray(v)) return '[]';
  if (Object.is(v, -0)) return '-0';
  if (Number.isNaN(v)) return 'NaN';
  if (v === null) return 'null';
  if (v === undefined) return 'undefined';
  return String(v);
}

// Pares de valores para testar
const pares = [
  [NaN, NaN],
  [-0, 0],
  ['1', 1],
  [null, undefined],
  [[], []]
];

// Itera sobre os pares e imprime os resultados
for (const [a, b] of pares) {
  const r = comparar(a, b);
  console.log(`${representar(a)}, ${representar(b)} => { frouxa: ${r.frouxa}, estrita: ${r.estrita}, objectIs: ${r.objectIs} }`);
}

Passo a passo

  1. A função comparar recebe dois valores e retorna um objeto com três propriedades: frouxa, estrita e objectIs.
  2. frouxa usa ==, que aplica coerção de tipos antes de comparar.
  3. estrita usa ===, que compara tipo e valor sem conversão.
  4. objectIs usa Object.is, que é como === mas trata NaN como igual a si mesmo e diferencia -0 de 0.
  5. A função representar formata valores para a saída: strings entre aspas, arrays como [], -0 como '-0', NaN como 'NaN', etc.
  6. O array pares contém os cinco pares pedidos.
  7. Usamos for...of com desestruturação [a, b] para percorrer os pares.
  8. Para cada par, chamamos comparar e imprimimos o resultado formatado.

Por que funciona

Object.is é uma operação de igualdade SameValue, definida na especificação ECMAScript. Ela se comporta como === para a maioria dos casos, mas duas diferenças importantes: Object.is(NaN, NaN) é true (enquanto NaN === NaN é false) e Object.is(-0, 0) é false (enquanto -0 === 0 é true). Isso torna Object.is útil para comparar valores de forma mais precisa, especialmente ao lidar com NaN e zeros com sinal.

Erros comuns

  • Achar que Object.is é sempre igual a ===. Ele difere para NaN e -0.
  • Usar == para comparar null e undefined e achar que é um erro. Na verdade, null == undefined é true por definição, mas null === undefined é false.
  • Esquecer que arrays e objetos são comparados por referência. [] === [] é false porque são objetos diferentes, mesmo que vazios. Object.is([], []) também é false.
  • Tentar representar -0 com String(-0), que retorna '0'. Use Object.is(v, -0) para detectar.

Outra forma de resolver

Você pode usar Number.isNaN e Object.is para detectar casos especiais, mas a função representar já cobre isso. Para comparar arrays por conteúdo, seria necessário uma função de comparação profunda, mas isso foge do escopo deste exercício.

Saída esperada

NaN, NaN => { frouxa: false, estrita: false, objectIs: true }
-0, 0 => { frouxa: true, estrita: true, objectIs: false }
'1', 1 => { frouxa: true, estrita: false, objectIs: false }
null, undefined => { frouxa: true, estrita: false, objectIs: false }
[], [] => { frouxa: false, estrita: false, objectIs: false }