Como faço para contornar o comportamento parseInt octal de JavaScript?
-
21-08-2019 - |
Pergunta
Tente executar o seguinte em JavaScript:
parseInt('01'); //equals 1
parseInt('02'); //equals 2
parseInt('03'); //equals 3
parseInt('04'); //equals 4
parseInt('05'); //equals 5
parseInt('06'); //equals 6
parseInt('07'); //equals 7
parseInt('08'); //equals 0 !!
parseInt('09'); //equals 0 !!
Eu só aprendi da maneira mais difícil que o JavaScript pensa o zero indica um octal inteiro , e uma vez que não há nenhuma "8"
ou "9"
em base-8, a função retorna zero. Goste ou não, isso é por design .
Quais são as soluções?
Nota:. Para ser exaustivo, que estou prestes a publicar uma solução, mas é uma solução que eu odeio, então por favor pós outros / as melhores respostas
Update:
A 5ª Edição do padrão JavaScript ( ECMA-262 ) introduz uma alteração de quebra que elimina este comportamento. Mozilla tem um bom write-up .
Solução
Esta é uma pegadinha comum Javascript com uma solução simples:
Apenas especificar a base , ou 'raiz', assim:
parseInt('08',10); // 8
Você também pode usar Número :
Number('08'); // 8
Outras dicas
Se você sabe o seu valor será na faixa de número inteiro de 32 bits assinado, então ~~x
vai fazer a coisa correta em todos os cenários.
~~"08" === 8
~~"foobar" === 0
~~(1.99) === 1
~~(-1.99) === -1
Se você olhar para cima não binário (~
), a especificação exige uma conversão "ToInt32" para o argumento que faz a conversão óbvio para um Int32 e é especificado para valores NaN
coagir a zero.
Sim, isso é incrivelmente hackish, mas é tão conveniente ...
A partir da documentação parseInt , use o argumento raiz opcional para especificar base-10:
parseInt('08', 10); //equals 8
parseInt('09', 10); //equals 9
Esta me parece pedante, confuso e detalhado (na verdade, um argumento extra em cada parseInt?) Por isso estou esperando há uma maneira melhor.
function parseDecimal(s) { return parseInt(s, 10); }
edit: fazer a sua própria função, para fazer o que você realmente quer, é apenas uma opção se você não gosta de adicionar o", 10" todo o tempo para a chamada parseInt (). Ele tem a desvantagem de ser uma função fora do padrão:. Mais conveniente para você, se você usá-lo muito, mas talvez mais confuso para os outros
Especifique a base:
var number = parseInt(s, 10);
Seria muito desobediente para substituir parseInt com uma versão que assume decimal se não tiver segundo parâmetro? (Nota - não testado)
parseIntImpl = parseInt
parseInt = function(str, base){return parseIntImpl(str, base ? base : 10)}
Como sobre isso por decimal:
('09'-0) === 9 // true
('009'-0) === 9 // true
Você também pode, em vez de usar parseFloat ou parseInt, use o operador unário ( + ).
+"01"
// => 1
+"02"
// => 2
+"03"
// => 3
+"04"
// => 4
+"05"
// => 5
+"06"
// => 6
+"07"
// => 7
+"08"
// => 8
+"09"
// => 9
e para uma boa medida
+"09.09"
// => 9.09
O operador mais unário precede seu operando e avalia a seu operando, mas as tentativas de convertê-lo em um número, se não é já. Apesar de negação unário (-). Também é possível converter os não-números, unárias vantagem é a maneira mais rápida e preferenciais de converter algo em um número , porque não realizar quaisquer outras operações no número
Se você já fez um monte de já codificação com parseInt e não quero acrescentar", 10" a tudo, você pode simplesmente substituir a função para fazer base 10 do padrão:
window._oldParseInt = window.parseInt;
window.parseInt = function(str, rad) {
if (! rad) {
return _oldParseInt(str, 10);
}
return _oldParseInt(str, rad);
};
Isso pode confundir um leitor mais tarde, de modo a fazer uma função parseInt10 () pode ser mais auto-explicativo. Pessoalmente eu prefiro usar uma função simples do que ter que adicionar", 10" o tempo todo - apenas cria mais oportunidades para erros
.