Constantes Incorporadas do JavaScript

Confira algumas curiosidades sobre null, NaN, undefined e Infinity


Autor: Réulison Silva Publicado em: Agosto 3, 2020

Veremos alguns dos objetos padrão do JavaScript, incluindo seus métodos e propriedades.



O termo “objeto global” (ou objeto padrão interno) aqui não deve ser confundido com os objetos globais. Aqui, “objeto global” se refere a objetos do escopo do JavaScript.

O próprio objeto global pode ser acessado usando o operador this no escopo global. De fato, o escopo global consiste nas propriedades do objeto global, incluindo propriedades herdadas, se houver.

null

null é usado para representar a ausência intencional de um valor de objeto e é considerado um valor primitivo. Ao contrário de undefined, não é uma propriedade do objeto global.

É igual a undefined, mas não é idêntico.

null == undefined;    // true
null === undefined; // false

Otypeof null é 'object'.

Você pode considerar um erro no JavaScript que typeof null seja um objeto. Deveria ser null.

typeof null; // 'object';

Para verificar corretamente se um valor é null, compare-o com o operador de igualdade restrita.

var a = null;
a === null; // true

Testando NaN usando isNaN()

window.isNaN()

Uma função global isNaN() pode ser usada para verificar se um valor determinado ou expressão é avaliado como NaN. Resumindo, esta função primeiro verifica se o valor é um número, se não tenta converter-lo (*) e depois verifica se o valor alterado é NaN. Por esse motivo, esse método de teste pode causar uma certa confusão.

(*) O método de “conversão” não é tão simples. A função isNaN é o objeto intrínseco %isNaN%. Quando a função isNaN é chamada com um número de argumento, são executadas as seguintes etapas:

  • Deixe num ser ToNumber(number).
  • ReturnIfAbrupt(num).
  • Se num for NaN, retorne true.
  • Caso contrário, retorne false.

Uma maneira confiável no ECMAScript para testar se um valor x é um NaN é uma expressão no formato x! == x. O resultado será true se, e somente se x for um NaN.

Estes exemplos ajudarão você a entender melhor o comportamento da função isNaN():

isNaN(NaN);           // true
isNaN(1);             // false: 1 é um número
isNaN(-2e-4);         // false: 2e-4 é um número (-0.0002) em notação científica Infinito é um número
isNaN(Infinity);      // false: Infinity is a number
isNaN(true);          // false: convertido para 1, que é um número
isNaN(false);         // false: convertido para 0, que é um número
isNaN(null);          // false: convertido para 0, que é um número
isNaN("");            // false: convertido para 0, que é um número
isNaN(" ");           // false: convertido para 0, que é um número
isNaN("45.3");        // false: string representando um número, convertido em 45,3
isNaN("1.2e3");       // false: string representando um número, convertido em 1.2e3
isNaN("Infinity");    // false: string representando um número, convertido em Infinity
isNaN(new Date);      // false: objeto Date, convertido em milissegundos desde a época
isNaN("10$");         // true : conversão falhou, o cifrão não é um dígito
isNaN("hello");       // true : conversão falhou, nenhum dígito
isNaN(undefined);     // true : convertido para NaN
isNaN();              // true : convertido em NaN (implicitamente indefinido)
isNaN(function(){});  // true : falha na conversão
isNaN({});            // true : falha na conversão
isNaN([1, 2]);        // true : convertido para "1, 2", que não pode ser convertido em um número

Este último é um pouco complicado: verificar se um Array é NaN. Para fazer isso, o construtor Number() primeiro converte o Array em uma string e depois em um número; esta é a razão pela qual isNaN([ ]) e isNaN ([34]) retornam false, mas isNaN([1, 2]) e isNaN([true]) retornam true: porque eles são convertidos em " ", "34","1, 2" e "true", respectivamente. Em geral, um Array é considerado NaN por isNaN(), a menos que contenha apenas um elemento cuja a string possa ser convertida em um número válido.

// Versão ≥ 6
Number.isNaN()

No ECMAScript 6, a função Number.isNaN() foi implementada principalmente para evitar o problema de window.isNaN() de converter forçadamente um parâmetro em um número. Number.isNaN(), de fato, não tenta converter o valor em um número antes do teste. Isso também significa que apenas valores do tipo número, que também são NaN, retornam true (basicamente significa apenas que Number.isNaN(NaN)).

Quando o Number.isNaN é chamado com um número de argumento, são executadas as seguintes etapas:

  1. Se Type(number) não for Number, retorna false.
  2. Se o Number for NaN, retorna true.
  3. Caso contrário, retorna false.

Alguns exemplos:

// O primeiro e único
Number.isNaN(NaN); 		// true

// Números
Number.isNaN(1);			// false
Number.isNaN(-2e-4); 		// false
Number.isNaN(Infinity); 	// false

// Valores que não são do tipo número
Number.isNaN(true); 		// false
Number.isNaN(false); 		// false
Number.isNaN(null); 		// false
Number.isNaN(""); 		// false
Number.isNaN(" "); 		// false
Number.isNaN("45.3"); 		// false
Number.isNaN("1.2e3"); 		// false
Number.isNaN("Infinity"); 	// false
Number.isNaN(new Date); 	// false
Number.isNaN("10$"); 		// false
Number.isNaN("hello"); 		// false
Number.isNaN(undefined); 	// false
Number.isNaN();				// false
Number.isNaN(function(){}); 	// false
Number.isNaN({}); 		// false
Number.isNaN([]); 		// false
Number.isNaN([1]); 		// false
Number.isNaN([1, 2]); 		// false
Number.isNaN([true]); 		// false

NaN

NaN significa “Não é um número”. Quando uma função ou operação matemática em JavaScript não pode retornar um determinado número, ele retorna o valor NaN.

É uma propriedade do objeto global e uma referência a Number.NaN. Exemplos:

function clean(x) {
  if (x === Number.NaN) {
    // nunca poderá ser true
    return null;
  }
  if (isNaN(x)) {
    return 0;
  }
}

console.log(clean(Number.NaN));
// Retorno: 0

window.hasOwnProperty('NaN'); // true
NaN; // NaN

Talvez seja confuso, mas NaN ainda é considerado um número.

typeof NaN; // 'number' 

Não verifique o NaN usando o operador de igualdade. Em vez disso, use isNaN.

NaN == NaN 	// false
NaN === NaN // false

undefined e null

À primeira vista pode parecer que null e undefined são basicamente a mesma coisa, porém existem diferenças sutis, porém, importantes.

undefined é a ausência de um valor no compilador, porque onde deveria ser um valor, não foi atribuído nenhum, como o caso de uma variável sem valor atribuído.

  • undefined é um valor global que representa a ausência de um valor atribuído.
typeof undefined === 'undefined' 
  • null é um objeto que indica que uma variável foi atribuída explicitamente “sem valor”.
typeof null === 'objeto'

Definir uma variável como undefined significa que a variável efetivamente não existe. Alguns processos, como a serialização em JSON, pode retirar propriedades undefined de objetos. Por outro lado, null indica que essas propriedades serão preservadas, você pode atribuir explicitamente o conceito de uma propriedade “vazia”.

Os exemplos a seguir são avaliados como undefined:

  • Uma variável quando é declarada, mas não é atribuída um valor (ou seja, definida);
let foo;
console.log('É undefined?', foo === undefined);
// É undefined? True
  • Acessando o valor de uma propriedade que não existe;
let foo = { a: 'a' };
console.log('É undefined?', foo.b === undefined);
// É undefined? true
  • O valor de retorno de uma função que não retorna um valor;
function foo() { return; }
console.log('É undefined?', foo() === undefined);
// É undefined? true
  • O valor de um argumento de função declarado, mas que foi omitido da chamada de função;
function foo(param) {
 console.log('É undefined?', param === undefined);
}
foo('a');
foo();
// É undefined? false
// É undefined? true

undefined também é uma propriedade do objeto global window.

// Somente nos browsers
console.log(window.undefined); // undefined
window.hasOwnProperty('undefined'); // true
// Versão < 5

Antes do ECMAScript 5 era possível alterar o valor da propriedade window.undefined para qualquer outro valor, potencialmente quebrando tudo

Infinity e -Infinity

1 / 0; // Infinity
// Espere! Como isso é possível?

Infinity é uma propriedade do objeto global (portanto, uma variável global) que representa o infinito na matemática. É um referência a Number.POSITIVE_INFINITY.

É maior que qualquer outro valor e você pode obtê-lo dividindo por 0 ou avaliando a expressão de um número que seja tão grande que “transborda”. Na verdade, isso significa que a divisão por 0 no JavaScript não retorna um erro, retorna Infinity!

Há também -Infinity, que é infinito negativo na matemática, é menor do que qualquer outro valor.

Para obter -Infinity, você nega o Infinity ou obtém uma referência a ele em Number.NEGATIVE_INFINITY.

- (Infinity);  // -Infinity

Agora vamos nos divertir com alguns exemplos:

Infinity > 123192310293; // true
-Infinity < -123192310293; // true
1 / 0; // Infinity
Math.pow(123123123, 9123192391023); // Infinity
Number.MAX_VALUE * 2; // Infinity
23 / Infinity; // 0
-Infinity; // -Infinity
-Infinity === Number.NEGATIVE_INFINITY; // true
-0; // -0 , sim, existe um 0 negativo no JavaScript
0 === -0; // true
1 / -0; // -Infinity
1 / 0 === 1 / -0; // false
Infinity + Infinity; // Infinity
var a = 0, b = -0;
a === b; // true
1 / a === 1 / b; // false
// Tente você também!

Constantes numéricas

O construtor Number possui algumas constantes internas que podem ser úteis.

Number.MAX_VALUE; // 1.7976931348623157e+308
Number.MAX_SAFE_INTEGER; // 9007199254740991
Number.MIN_VALUE; // 5e-324
Number.MIN_SAFE_INTEGER; // -9007199254740991
Number.EPSILON; // 0.0000000000000002220446049250313
Number.POSITIVE_INFINITY; // Infinity
Number.NEGATIVE_INFINITY; // -Infinity
Number.NaN; // NaN

Em muitos casos, os vários operadores em JavaScript quebram com valores fora do intervalo de (Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)

Observe que Number.EPSILON representa a diferença entre um e o menor Number maior que 1 e portanto, a menor diferença possível entre dois Number com valores diferentes. Um motivo para usar isso é devido a natureza de como os números são armazenados pelo JavaScript. Verifique a igualdade de dois números.

Operações que retornam NaN

Operações matemáticas com valores diferentes de números que retornam NaN. Ou seja, operações que envolvem valores que não são apenas números.

"b" * 3
"cde" - "e"
[1, 2, 3] * 2

Uma exceção: Arrays contendo um único número.

[2] * [3] // Retorna 6

Além disso, lembre-se de que o operador + concatena as strings.

"a" + "b" // Retorna "ab"

Dividir zero por zero retorna NaN.

0 / 0 // NaN

Em matemática geralmente (diferentemente do JavaScript) a divisão por zero não é possível.

Geralmente, funções Math que recebem argumentos não numéricos retornarão NaN.

Math.floor("a")

A raiz quadrada de um número negativo retorna NaN, porque Math.sqrt não suporta números imaginários ou complexos.

Math.sqrt(-1)

É isso aí, espero ter ajudado um pouco sobre as “estranhezas” do JavaScript.