Перетворити NaN в 0 в JavaScript


238

Чи є спосіб перетворити значення NaN в 0 без заяви if:

if (isNaN(a)) a = 0;

Дуже прикро перевіряти мої змінні щоразу.


4
Хіба ви не можете просто урну це зробити на фуніціоні?
the_drow

Це лише як 20 символів, у чому проблема?
Расті Фаусак

1
function noNaN( n ) { return isNaN( n ) ? 0 : n; }а потім простоnoNaN( a )
Šime Vidas

1
@rfausak Ви, як правило, не хочете повторювати себе (див. DRY ). Якщо певна функціональність потрібна кілька разів, надається спеціальна функція.
Šime Vidas

Відповіді:


575

Ви можете зробити це:

a = a || 0

... який перетворить значення з будь-якого значення "фальси" в 0.

Значення "фальси":

  • false
  • null
  • undefined
  • 0
  • "" (порожній рядок)
  • NaN (Не число)

Або це, якщо ви віддаєте перевагу:

a = a ? a : 0;

... що матиме той же ефект, що і вище.


Якщо наміром було тестувати більше, ніж просто NaN, то ви можете зробити те ж саме, але спершу зробіть конверсію toNumber .

a = +a || 0

Для цього використовується оператор unary + для спроби перетворення a число. Це має додаткову перевагу перетворення таких речей, як числові рядки, '123'у число.

Єдине несподіване може бути, якщо хтось передає масив, який можна успішно перетворити на число:

+['123']  // 123

Тут ми маємо масив, який містить один член, який є числовим рядком. Він буде успішно перетворений у число.


Ідея перетворити перевірку у функцію хороша, але ця є більш елегантною.
Tamás Pap

1
@Bakudan: Добре. Я думав, що ОП хвилює лише конкретне NaNзначення. Це не працюватиме як тест для всіх значень, що не мають числа. Хоча ми можемо спробувати спершу перетворення вNUMBER. Я оновлю.
користувач113716

... ах, це через назву "Перетворити NaN в 0" . У будь-якому випадку, охоплені обидва шляхи зараз.
користувач113716

2
Спасибі товаришу, вибрав і трохи змінив це для себе a = a * 1 || 0
хтось

Дивовижно. Спасибі
Апіт Джон Ісмаїл

32

Використання подвійного тильду (подвійний біт НЕ) - ~~- робить деякі цікаві речі в JavaScript. Наприклад, ви можете використовувати його замість Math.floorабо навіть як альтернативу parseInt("123", 10)! Про це багато обговорювалося в Інтернеті, тому я не буду вказувати, чому він працює тут, але якщо ви зацікавлені: що таке "подвійний тильд" (~~) в JavaScript?

Ми можемо скористатись цією властивістю подвійного тильду для перетворення NaNна число, і щасливо це число дорівнює нулю!

console.log(~~NaN); // 0


1
Спасибі, я не знав про це ~~взагалі, я просто використав його поряд з parseFloat()приблизно так: ~~parseFloat($variable);. Дуже акуратно :) +1
Rens Tillmann

23

Напишіть власний метод та використовуйте його скрізь, де потрібно значення числа:

function getNum(val) {
   if (isNaN(val)) {
     return 0;
   }
   return val;
}

1
Якщо я пройду, nullто це не дає мені очікуваного результату 0. Більше про мою думку тут: stackoverflow.com/questions/115548/why-is-isnannull-false-in-js
Андрій Базанов

2
На додаток до мого коментаря вище, я в кінцевому підсумку використовував, Number(val)як він повертається, 0коли він не може це зрозуміти.
Андрій Базанов

4

Щось більш просте та ефективне для будь-якого:

function getNum(val) {
   val = +val || 0
   return val;
}

... який перетворить значення з будь-якого значення "фальси" в 0.

Значення "фальси":

  • false
  • null
  • undefined
  • 0
  • "" (порожній рядок)
  • NaN (Не число)

1
Цікаво! Цікаво, як він реагує, коли val може мати негативне значення. Наскільки я тестував, в цьому немає нічого поганого, але про всяк випадок ...
Лучано,

2

Замість того, щоб збивати це, щоб ви могли продовжувати, чому б не створити резервну копію і не замислюватися, чому ви в першу чергу натрапляєте на NaN?

Якщо будь-який з числових входів для операції є NaN, вихід також буде NaN. Так працює нинішній стандарт IEEE з плаваючою точкою (це не лише Javascript). Така поведінка є поважною причиною : основний намір полягає в тому, щоб утримати вас від використання хибного результату, не розуміючи, що це неправда.

Те, як працює NaN - якщо щось піде не так, як в якійсь під-під-операції (виробляючи NaN на тому нижньому рівні), то також буде і кінцевий результат NaN, який ви відразу визнаєте помилкою, навіть якщо ваш Логіка керування помилками (можливо, кидати / ловити?) ще не завершена.

NaN як результат арифметичного обчислення завжди вказує, що в деталях арифметики щось пішло не так. Це спосіб комп’ютеру сказати "тут потрібна налагодження". Замість того, щоб знайти якийсь спосіб продовжити все одно з якоюсь цифрою, яка навряд чи колись вірна (це 0 дійсно те, що ви хочете?), Чому б не знайти проблему та виправити її.

Поширена проблема Javascript полягає в тому, що обидва parseInt(...)і parseFloat(...)повернуть NaN, якщо йому дадуть безглуздий аргумент ( null,'' , і т.д.). Виправте проблему на найнижчому рівні, а не на більш високому рівні. Тоді результат загального обчислення має хороші шанси на те, що ви маєте сенс, і ви не замінюєте якогось магічного числа (0 або 1 або будь-якого іншого) на результат усього обчислення. (Трюк (parseInt (foo.value) || 0) працює лише для сум, а не для продуктів - для продуктів, для яких потрібно, щоб значення за замовчуванням було 1, а не 0, але не якщо вказане значення дійсно дорівнює 0.)

Можливо, для зручності кодування ви хочете, щоб функція отримувала у користувача значення, очищала його та при необхідності надавала значення за замовчуванням:

function getFoobarFromUser(elementid) {
        var foobar = parseFloat(document.getElementById(elementid).innerHTML)
        if (isNaN(foobar)) foobar = 3.21;       // default value
        return(foobar.toFixed(2));
}

2

Як щодо регексу ?

function getNum(str) {
  return /[-+]?[0-9]*\.?[0-9]+/.test(str)?parseFloat(str):0;
}

Код нижче буде ігнорувати NaN, щоб дозволити обчислення правильно введених чисел


2

Методи, які використовують isNaN, не працюють, якщо ви намагаєтесь використовувати parseInt, наприклад:

parseInt("abc"); // NaN
parseInt(""); // NaN
parseInt("14px"); // 14

Але у другому випадку isNaN видає false (тобто нульовий рядок - це число)

n="abc"; isNaN(n) ? 0 : parseInt(n); // 0
n=""; isNaN(n) ? 0: parseInt(n); // NaN
n="14px"; isNaN(n) ? 0 : parseInt(n); // 14

Підсумовуючи, нульовий рядок вважається дійсним числом за isNaN, але не для parseInt. Перевірено з Safari, Firefox та Chrome на OSX Mojave.


1
Одне очевидне рішення - трохи громіздкий, перевірити наявність NaN після розбору, а не раніше: isNaN (parseInt (n))? parseInt (n): 0; // Аналіз викликів два рази :(
Девід Кроу

1
що коментар повинен бути (на початку) вашою відповіддю!
frandroid

Більш ефективне рішення передбачає, що нульовий рядок є єдиною аномалією: n == "" || isNaN (n)? 0: parseInt (n); (але що робити, якщо є інші рядки?)
Девід Кроу


0

використовуючи користувальницьке рішення 113716, що, до речі, чудово уникати всіх тих, що не знаю, я реалізував це таким чином, щоб обчислити мою підточну текстову скриньку з одиниці текстової скриньки та кількості текстових скриньок.

Під час написання нечислових номерів у текстових полях одиниць та кількості їхні значення замінюються нулем, тому остаточне розміщення даних користувача не має жодних чисел.

     <script src="/common/tools/jquery-1.10.2.js"></script>
     <script src="/common/tools/jquery-ui.js"></script>

     <!----------------- link above 2 lines to your jquery files ------>





    <script type="text/javascript" >
    function calculate_subtotal(){

    $('#quantity').val((+$('#quantity').val() || 0));
    $('#unit').val((+$('#unit').val() || 0));

    var  calculated = $('#quantity').val() * $('#unit').val() ;
    $('#subtotal').val(calculated);


    }
    </script>


      <input type = "text" onChange ="calculate_subtotal();" id = "quantity"/>
      <input type = "text" onChange ="calculate_subtotal();" id = "unit"/>
      <input type = "text" id = "subtotal"/>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.