javascript - funcion - parseInt vs unary plus: cuándo usar qué
parseint javascript (5)
Consulte esta respuesta para obtener un conjunto más completo de casos
Bueno, aquí hay algunas diferencias que conozco:
Una cadena vacía
""
evalúa a0
, mientras queparseInt
evalúa comoNaN
. IMO, una cadena en blanco debe ser unNaN
.+'''' === 0; //true isNaN(parseInt('''',10)); //true
El unario
+
actúa más comoparseFloat
ya que también acepta decimales.parseInt
por otro lado, detiene el análisis cuando ve un carácter no numérico, como el período que está destinado a ser un punto decimal.
.+''2.3'' === 2.3; //true parseInt(''2.3'',10) === 2; //true
parseInt
yparseFloat
analiza y construye la cadena de izquierda a derecha . Si ven un carácter no válido, devuelve lo que se ha analizado (si lo hay) como un número, yNaN
si ninguno se analizó como un número.El unario
+
por otro lado devolveráNaN
si toda la cadena no es convertible a un número.parseInt(''2a'',10) === 2; //true parseFloat(''2a'') === 2; //true isNan(+''2a''); //true
Como se ve en el comentario de @Alex K. ,
parseInt
yparseFloat
analizarán por carácter. Esto significa que las anotaciones de hex y exponente fallarán dado quex
se tratan como componentes no numéricos (al menos en base10).Sin embargo, el unario
+
los convertirá correctamente.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.
¿Cuáles son las diferencias entre esta línea?
var a = parseInt("1", 10); // a === 1
y esta línea
var a = +"1"; // a === 1
Esta prueba jsperf muestra que el operador unario es mucho más rápido en la versión actual de Chrome, suponiendo que es para node.js?
Si intento convertir cadenas que no son números, ambos devuelven NaN
:
var b = parseInt("test" 10); // b === NaN
var b = +"test"; // b === NaN
Entonces, ¿cuándo debería preferir usar parseInt
sobre la ventaja unaria (especialmente en node.js) ???
editar : ¿y cuál es la diferencia para el operador de doble tilde ~~
?
Considera el rendimiento también. Me sorprendió ver que parseInt
beats unary plus en iOS :) Esto es útil para aplicaciones web con un alto consumo de CPU solamente. Como regla general, sugiero a JS opt-guys que consideren a cualquier operador JS sobre otro desde el punto de vista del rendimiento móvil hoy en día.
Por lo tanto, vaya primero al móvil ;)
La última tabla de conversión de cualquier número:
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"'',
''null'',
''[].undef'',
''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) ? wrap(''b'', n) : String(n);
}
var rows = VALUES.map(function (v) {
var x = eval(''('' + v + '')'');
return [v].concat(EXPRS.map(function (e) {
return val(eval(e))
}));
});
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 }
La tabla en la respuesta de thg435 creo que es exhaustiva, sin embargo, podemos resumirla con los siguientes patrones:
- Unario plus no trata todos los valores falsy de la misma manera, pero todos salen falsos.
- Unary plus envía
true
a 1, pero"true"
aNaN
. - Por otro lado,
parseInt
es más liberal para cadenas que no son dígitos puros.parseInt(''123abc'') === 123
, mientras que+
informaNaN
. -
Number
aceptará números decimales válidos, mientras que elparseInt
simplemente deja caer todo más allá del decimal. Por lo tanto,parseInt
imita el comportamiento C, pero quizás no sea ideal para evaluar la entrada del usuario. - Ambos recortan el espacio en blanco en cuerdas.
-
parseInt
, al ser un analizador mal diseñado, acepta entradas octales y hexadecimales. Unario más solo toma hexadecimal.
Los valores Falsy se convierten a Number
siguiendo lo que tendría sentido en C: null
y false
son ambos cero. ""
Ir a 0 no sigue esta convención pero tiene mucho sentido para mí.
Por lo tanto, creo que si valida la entrada del usuario, unario plus tiene un comportamiento correcto para todo, excepto que acepta decimales (pero en mi vida real, estoy más interesado en capturar entradas de correo electrónico en lugar de userId, valor omitido por completo, etc.), ParseInt es demasiado liberal.
Tenga cuidado, parseInt es más rápido que el operador unario en Node.JS, es falso que + o | 0 sean más rápidos, son más rápidos solo para elementos NaN.
Mira esto:
var arg=process.argv[2];
rpt=20000;
mrc=1000;
a=[];
b=1024*1024*1024*1024;
for (var i=0;i<rpt;i++)
a[i]=Math.floor(Math.random()*b)+'' '';
t0=Date.now();
if ((arg==1)||(arg===undefined))
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
c=a[i]-0;
}
t1=Date.now();
if ((arg==2)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
d=a[i]|0;
}
}
t2=Date.now();
if ((arg==3)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
e=parseInt(a[i]);
}
}
t3=Date.now();
if ((arg==3)||(arg===undefined)) {
for (var j=0;j<mrc;j++) for (var i=0;i<rpt;i++) {
f=+a[i];
}
}
t4=Date.now();
console.log(a[i-1],c,d,e,f);
console.log(''Eseguiti: ''+rpt*mrc+'' cicli'');
console.log(''parseInt ''+(t3-t2));
console.log(''|0 ''+(t2-t1));
console.log(''-0 ''+(t1-t0));
console.log(''+ ''+(t4-t3));