javascript - parseInt vs plus unar, când să folosești care?
Care sunt diferențele dintre această linie:
var a = parseInt("1", 10); // a === 1
și această linie
var a = +"1"; // a === 1
Acest test jsperf arată că operatorul unar este mult mai rapid în versiunea actuală de Chrome, presupunând că este pentru node.js!?
Dacă încerc să convertesc șiruri care nu sunt numere, ambele returnează NaN:
var b = parseInt("test", 10); // b === NaN
var b = +"test"; // b === NaN
Deci când ar trebui să prefer folosirea parseInt în locul semnului plus unar (în special în node.js)???
editare: și care este diferența față de operatorul dublu tilde ~~?
Răspuns #1
Tabelul final de conversie orice-la-număr:
EXPRS = [
'parseInt(x)',
'parseFloat(x)',
'Number(x)',
'+x',
'~~x',
'x>>>0',
'isNaN(x)'
];
VALUES = [
'"123"',
'"+123"',
'"-123"',
'"123.45"',
'"-123.45"',
'"12e5"',
'"12e-5"',
'"0123"',
'"0000123"',
'"0b111"',
'"0o10"',
'"0xBABE"',
'"4294967295"',
'"123456789012345678"',
'"12e999"',
'""',
'"123foo"',
'"123.45foo"',
'" 123 "',
'"foo"',
'"12e"',
'"0b567"',
'"0o999"',
'"0xFUZZ"',
'"+0"',
'"-0"',
'"Infinity"',
'"+Infinity"',
'"-Infinity"',
'BigInt(1)',
'null',
'undefined',
'true',
'false',
'Infinity',
'NaN',
'{}',
'{valueOf: function(){return 42}}',
'{toString: function(){return "56"}}',
];
//////
function wrap(tag, s) {
if (s && s.join)
s = s.join('');
return '<' + tag + '>' + String(s) + '</' + tag + '>';
}
function table(head, rows) {
return wrap('table', [
wrap('thead', tr(head)),
wrap('tbody', rows.map(tr))
]);
}
function tr(row) {
return wrap('tr', row.map(function (s) {
return wrap('td', s)
}));
}
function val(n) {
return n === true || Number.isNaN(n) || n === "Error" ? wrap('b', n) : String(n);
}
var rows = VALUES.map(function (v) {
var x = eval('(' + v + ')');
return [v].concat(EXPRS.map(function (e) {
try {
return val(eval(e));
} catch {
return val("Error");
}
}));
});
document.body.innerHTML = table(["x"].concat(EXPRS), rows);table { border-collapse: collapse }
tr:nth-child(odd) { background: #fafafa }
td { border: 1px solid #e0e0e0; padding: 5px; font: 12px monospace }
td:not(:first-child) { text-align: right }
thead td { background: #3663AE; color: white }
b { color: red }Răspunsul #2
Ei bine, iată câteva diferențe pe care le cunosc:
Un șir gol
""se evaluează ca0, în timp ceparseIntîl evaluează caNaN. În opinia mea, un șir gol ar trebui să fieNaN.+'' === 0; //true isNaN(parseInt('',10)); //trueOperatorul unar
+se comportă mai mult caparseFloat, deoarece acceptă și zecimale.parseInt, pe de altă parte, se oprește din analizare atunci când întâlnește un caracter nenumeric, cum ar fi punctul care este menit să fie un punct zecimal..+'2.3' === 2.3; //true parseInt('2.3',10) === 2; //trueparseIntșiparseFloatanalizează și construiesc șirul de caractere de la stânga la dreapta. Dacă întâlnesc un caracter nevalid, returnează ceea ce a fost analizat (dacă există) ca număr șiNaNdacă nu a fost analizat niciun număr.Operatorul unar
+, pe de altă parte, va returnaNaNdacă întregul șir nu poate fi convertit într-un număr.parseInt('2a',10) === 2; //true parseFloat('2a') === 2; //true isNaN(+'2a'); //trueDupă cum se vede în comentariul lui @Alex K.,
parseIntșiparseFloatvor analiza caracterele. Aceasta înseamnă că notațiile hex și exponentiale vor eșua deoarecexșiesunt tratate ca componente nenumerice (cel puțin în baza 10).Operatorul unar
+îi va converti totuși corect.parseInt('2e3',10) === 2; //true. This is supposed to be 2000 +'2e3' === 2000; //true. This one's correct. parseInt("0xf", 10) === 0; //true. This is supposed to be 15 +'0xf' === 15; //true. This one's correct.
Răspunsul #3
Tabelul din răspunsul lui thg435 cred că este cuprinzător, totuși putem rezuma cu următoarele tipare:
- Operatorul unar plus nu tratează toate valorile false în același mod, dar toate ies ca false.
- Operatorul unar plus transformă
trueîn 1, dar"true"înNaN. - Pe de altă parte,
parseInteste mai liberal pentru șiruri care nu sunt doar cifre.parseInt('123abc') === 123, în timp ce+raporteazăNaN. Numberva accepta numere zecimale valide, în timp ceparseIntpur și simplu ignoră tot ce urmează după virgulă. Astfel,parseIntimită comportamentul din C, dar poate nu este ideal pentru evaluarea inputului utilizatorului.- Ambele elimină spațiile albe din șiruri.
parseInt, fiind un parser prost conceput, acceptă input octal și hexadecimal. Plusul unar ia doar hexadecimal.
Valorile false se convertesc la Number urmând ceea ce ar avea sens în C: null și false sunt ambele zero. "" devenind 0 nu urmează tocmai această convenție, dar are suficient sens pentru mine.
Prin urmare, cred că dacă validați inputul utilizatorului, operatorul unar plus are un comportament corect pentru tot, cu excepția faptului că acceptă zecimale (dar în cazurile mele reale sunt mai interesat să detectez inputul de tip email în loc de userId, valoarea omisă complet, etc.), în timp ce parseInt este prea liberal.
