วิธีเปลี่ยน NaN จาก parseInt เป็น 0 สำหรับสตริงว่าง


298

เป็นไปได้ที่จะคืนค่า 0 แทนที่จะเป็นNaNเมื่อแยกวิเคราะห์ค่าใน JavaScript หรือไม่?

ในกรณีที่สตริงว่างparseIntกลับNaNมา

เป็นไปได้ไหมที่จะทำเช่นนั้นใน JavaScript เพื่อตรวจสอบNaN?

var value = parseInt(tbb) == NaN ? 0 : parseInt(tbb)

หรืออาจมีฟังก์ชั่นอื่นหรือปลั๊กอิน jQuery ซึ่งอาจทำสิ่งที่คล้ายกัน?


72
NaN != NaNFYI, isNaN(value)คุณจะต้อง
pimvdb

28
ใช่ไม่มีพี่เลี้ยงสองคนเหมือนกัน;)
เจมส์พี

3
ฟังก์ชั่นการโทรparseInt()สองครั้ง (ในNaNกรณีปกติ / ไม่สำเร็จ) ไม่ใช่ความคิดที่ดี นอกเหนือจากความไร้ประสิทธิภาพสำหรับคนที่ไม่ระวังหากสิ่งที่ผ่านไปtbbนั้นเป็นการเรียกฟังก์ชั่นที่มีผลข้างเคียงมันก็แย่มาก ฉันจะไม่ใช้วิธีแก้ปัญหาใด ๆ ที่นี่ที่ฉันเห็นparseInt()สองครั้ง
JonBrave

คำตอบ:


756
var s = '';

var num = parseInt(s) || 0;

เมื่อไม่ได้ใช้กับค่าบูลีนตัวดำเนินการเชิงตรรกะ OR ( ||) จะส่งกลับนิพจน์แรก ( parseInt(s)) หากสามารถประเมินเป็นจริงได้มิฉะนั้นจะส่งคืนนิพจน์ที่สอง (0) ค่าส่งคืนของparseInt('')คือ NaN NaN ประเมินว่าเป็นเท็จดังนั้นnumสิ้นสุดการตั้งค่าเป็น 0


6
สิ่งนี้จะไม่ทำงานหาก s = "4s"; (มันคืนค่า 4 ... ซึ่งไม่ถูกต้อง ... )
markzzz

1
ฟังก์ชัน parseInt ใน js แจงตัวเลขใด ๆ ในสตริง
ali youhannaei

26
@markzzz อ่านคำถามอีกครั้ง OP ถามว่า: " เป็นไปได้ไหมที่จะส่งคืน 0 แทน NaN " OP ไม่ต้องการตรวจสอบว่าสตริงเฉพาะสามารถแยกวิเคราะห์เป็น int ได้หรือไม่ OP ต้องการที่จะได้รับแทน0 NaNนี่แก้ไขได้ด้วยโค้ดของ Matt อย่างสมบูรณ์แบบ
trejder

2
@markzzzvar nextIphone = parseInt("4S") + 1; // wow it works!
ศูนย์การเบี่ยงเบนความสนใจ

2
@ Matthew กรุณาใช้คำว่า"falsy"หรือ"truthy" เพราะ NaN === false เป็น false! แต่บูลีน (NaN) === บูลีน (เท็จ) เป็นจริง ตรรกะหรือส่งกลับนิพจน์แรกหากสามารถประเมินเป็น"ความจริง"
Pablo Recalde

51

คุณยังสามารถใช้isNaN()ฟังก์ชัน:

var s = ''
var num = isNaN(parseInt(s)) ? 0 : parseInt(s)

12
ทำไมต้องโทรparseInt(s)สองครั้ง นอกจากนี้ควรเป็นparseInt(s, 10)
Dexygen

2
@GeorgeJempty รัศมีของ "10" เป็นค่าเริ่มต้น พารามิเตอร์นั้นเป็นทางเลือก จุดดีในการโทรparseInt()สองครั้งแม้ว่า
Autumn Leonard

8
@AutumnLeonard นี่เป็นเรื่องจริงเท่านั้น หากสตริงของคุณเริ่มต้นด้วย 0 จะถือว่าตัวเลขอยู่ในรูปแบบฐานแปดดังนั้น parseInt ('077') จะให้ 63 ซึ่งอาจทำให้เกิดข้อผิดพลาดในการค้นหาข้อบกพร่องดังนั้นคุณควรระบุพารามิเตอร์ที่สองเสมอ ดูตัวอย่างstackoverflow.com/questions/8763396/…
chuck258

22

Number()ฉันรู้สึกประหลาดใจที่จะไม่เห็นใครพูดถึงการใช้ ได้รับมันจะแยกทศนิยมถ้าให้ดังนั้นจะทำหน้าที่แตกต่างกว่าparseInt()อย่างไรก็ตามมันจะถือว่าฐาน 10 และจะเปลี่ยน "" หรือแม้กระทั่ง "" ในการ 0


1
ใช่มีประโยชน์มากสำหรับการอ่านจาก localStorage: Number (localStorage.getItem ('appBanner.count')) + 1
Philip Murphy

ในขณะที่ใช้งานได้กับคำถามตามที่ถูกถามมันยังคงส่งคืน NaN สำหรับอักขระที่ไม่ใช่ช่องว่างที่ไม่ใช่หมายเลข
Kyle Delaney

9

สำหรับผู้ที่ไม่ได้ถูก จำกัดparseIntคุณสามารถใช้ตัวดำเนินการระดับบิตหรือ OR (ซึ่งเรียกToInt32ไปยังตัวถูกดำเนินการโดยปริยาย)

var value = s | 0;

// NaN | 0     ==>> 0
// ''  | 0     ==>> 0
// '5' | 0     ==>> 5
// '33Ab' | 0  ==>> 0
// '0x23' | 0  ==>> 35
// 113 | 0     ==>> 113
// -12 | 0     ==>> -12
// 3.9 | 0     ==>> 3

หมายเหตุ: ความแตกต่างจากToInt32 parseInt(เช่นparseInt('33Ab') === 33)


แต่: '10000000000' | 0 === 1410065408.
trincot

@trincot ใช่ค่าใด ๆ > = Math.pow(2, 31)จะล้น
Ahmad Ibrahim

8

ปัญหา

คำตอบอื่น ๆ ไม่ได้คำนึงถึงว่า0เป็นเท็จดังนั้นจึงจะเป็น 20 ต่อไปนี้แทน 0:

const myNumber = parseInt('0') || 20; // 20

การแก้ไขปัญหา

ฉันเสนอฟังก์ชันตัวช่วยซึ่งแก้ปัญหาส่วนใหญ่ได้:

function getNumber({ value, defaultValue }) {
  const num = parseInt(value, 10);
  return isNaN(num) ? defaultValue : num;
}

ฟังก์ชันตัวช่วยจะให้ผลลัพธ์ดังนี้:

getNumber({ value: "0", defaultValue: 20 }); // 0
getNumber({ value: "2", defaultValue: 20 }); // 2
getNumber({ value: "2.2", defaultValue: 20 }); // 2
getNumber({ value: "any string", defaultValue: 20 }); // 20
getNumber({ value: undefined, defaultValue: 20 }); // 20
getNumber({ value: null, defaultValue: 20 }); // 20
getNumber({ value: NaN, defaultValue: 20 }); // 20
getNumber({ value: false, defaultValue: 20 }); // 20
getNumber({ value: true, defaultValue: 20 }); // 20

2
โปรดส่ง radix ไปที่ parseInt: parseInt(string, radix)พิจารณาสิ่งนี้: parseInt("0x10") === 16นอกจากนี้ยังparseInt("010")สามารถให้ผล8ในบางเบราว์เซอร์
andlrc

2
หากคุณกำลังอยู่แล้วขึ้นอยู่กับ lodash สำหรับสิ่งอื่น ๆ ที่มีประโยชน์defaultToฟังก์ชั่นที่ไม่เพียงแค่นี้: _.defaultTo(NaN, -1)ผลตอบแทน-1แต่ผลตอบแทน_.defaultTo(0, -1); 0
วาลดีริอัส

นี่เป็นจุดที่ยอดเยี่ยม! คุณสามารถพึ่งพา || ในตอนท้ายเพื่อให้ค่าเริ่มต้นที่ถูกต้องเมื่อค่าเริ่มต้นที่คุณต้องการคือ ZERO (ให้สิทธิ์นี่คือสิ่งที่ OP ต้องการ) ตามที่คุณได้กล่าวถึงเนื่องจากลักษณะเท็จของอินพุต '0' จะถือว่าเป็นอินพุตที่ไม่ถูกต้องในกรณีนี้และคำสั่งจะส่งคืนค่าเริ่มต้นแทน (อาจไม่ใช่สิ่งที่คาดหวัง!)
JonathanDavidArndt

แน่นอนคุณควรใช้ const แทนการโทรparseIntสองครั้ง
Kyle Delaney

4

งานของคุณสะอาดกว่าการแยกวิเคราะห์ในความคิดของฉันหรือไม่ใช้ตัวดำเนินการ +

var s = '';
console.log(+s);

var s = '1024'
+s
1024

s = 0
+s
0

s = -1
+s
-1

s = 2.456
+s
2.456

s = ''
+s
0

s = 'wtf'
+s
NaN

1
กะทัดรัดมาก ช่างน่าละอายที่คุณไม่ได้รับคะแนนมากขึ้น ฉันโหวตให้คุณ โปรดตอบกลับให้ลองจับ -2 ของฉันที่ได้รับในวันนี้โดยโทรลล์แบบปิดเสียง ... (ดูคำตอบของฉันที่ท้ายหน้านี้) ขอบคุณ.
Fabien Haddadi


1

ทำการตรวจสอบแยกต่างหากสำหรับสตริงที่ว่างเปล่า (เนื่องจากเป็นกรณีเฉพาะ) และตั้งค่าเป็นศูนย์ในกรณีนี้

คุณสามารถต่อท้าย "0" เพื่อเริ่มต้น แต่แล้วคุณต้องเพิ่มคำนำหน้าเพื่อระบุว่ามันเป็นทศนิยมและไม่ใช่เลขฐานแปด


คุณคิดว่ามันจะเป็นการดีกว่าถ้าใส่ 0 ต่อท้าย?
Joper

1
ไม่ - นั่นเป็นวิธีที่ฉันใช้ ในกรณีนี้การตรวจสอบแยกต่างหากจะดีกว่า อย่างไรก็ตามหากวิธีการแก้ปัญหา Matts ทำงานได้ดีกว่า
Schroedingers Cat

1

ทำไมไม่แทนที่ฟังก์ชั่น? ในกรณีนั้นคุณสามารถมั่นใจได้ว่ามันจะกลับมา0ในกรณีของNaN:

(function(original) {
    parseInt = function() {
        return original.apply(window, arguments) || 0;
    };
})(parseInt);

ตอนนี้ที่ใดก็ได้ในรหัสของคุณ:

parseInt('') === 0

15
การเอาชนะฟังก์ชั่นเช่นนี้อาจทำให้โปรแกรมเมอร์ JavaScript ผู้เชี่ยวชาญสับสนซึ่งอาจเห็นว่าเป็นจุดบกพร่อง ฟังก์ชั่นที่ถูกแทนที่ของคุณน่าจะถูกฝังไว้ที่ไหนสักแห่งที่ไม่น่าจะเห็น นี่คือความคิดสร้างสรรค์ แต่ฉันไม่แน่ใจว่าฉันจะแนะนำเป็นการส่วนตัวโดยพิจารณาว่าการเพิ่ม|| 0คำตอบของ Matt ทำได้ง่ายเพียงใด ฉันเห็นว่าการเอาชนะวัตถุที่คุณไม่ได้เป็นทางเลือกสุดท้ายหรือเมื่อไม่ทำเช่นนั้นจะมีราคาสูงขึ้นอย่างมากในแง่ของเวลาและความซับซ้อน
jmort253

2
ฉันเห็นด้วยกับ @ jmort253 ... มันอันตรายเพราะฟังก์ชั่นนี้ฉลาดเกินไป มันจะดีกว่าที่จะทำหน้าที่เดียวกัน แต่มีชื่อเช่น getSafeNumberValue หรืออะไรทำนองนั้น
ซามูเอล

1

ฉันมีปัญหาที่คล้ายกัน (firefox v34) กับสตริงง่ายๆเช่น:

var myInt = parseInt("b4");

ดังนั้นฉันจึงได้แฮ็คอย่างรวดเร็วของ:

var intVal = ("" + val).replace(/[^0-9]/gi, "");

และจากนั้นก็มีความซับซ้อนที่โง่ที่จะจัดการกับ floats + ints สำหรับสิ่งที่ไม่ง่าย:

var myval = "12.34";

function slowParseNumber(val, asInt){
    var ret = Number( ("" + val).replace(/[^0-9\.]/gi, "") );
    return asInt ? Math.floor(ret) : ret;
}
var floatVal = slowParseNumber(myval);

var intVal = slowParseNumber(myval, true);
console.log(floatVal, intVal);

มันจะคืนค่า 0 สำหรับสิ่งต่าง ๆ เช่น:

var intVal = slowParseNumber("b"); // yeilds 0

1
//////////////////////////////////////////////////////
function ToInt(x){x=parseInt(x);return isNaN(x)?0:x;}
//////////////////////////////////////////////////////
var x = ToInt('');   //->  x=0
    x = ToInt('abc') //->  x=0
    x = ToInt('0.1') //->  x=0
    x = ToInt('5.9') //->  x=5
    x = ToInt(5.9)   //->  x=5
    x = ToInt(5)     //->  x=5

คุณช่วยอธิบายวิธีนี้ได้ไหม
RamenChef

ถ้าคุณต้องการแปลงหมายเลขใด ๆ (เช่น '123 'หรือ 123) เป็นจำนวนเต็มถ้าคุณจะใช้ parseInt (' abc '),
AbdulRahman AlShamiri

ถ้าคุณจะใช้ parseInt ('abc') คุณจะไปที่ NaN แต่ฟังก์ชั่นนี้จะแปลง NaN เป็น 0
AbdulRahman AlShamiri

บิงโกเป็นทางเลือกที่ชัดเจนในการ||เข้าใกล้ ฉันรู้ว่านี่เป็นคำถามและคำตอบเก่า แต่คำตอบนี้หลีกเลี่ยงการโทรหา parseInt สองครั้งและใช้ isNaN อย่างถูกต้อง มันแค่ต้องการ Radix parseInt(x, 10)ให้ละเอียด (ตั้งค่าของฉันเป็นตัวแปรภายในแยกต่างหากแทนการนำx.)
goodeye

1

ฉันสร้างต้นแบบ 2 ตัวเพื่อจัดการเรื่องนี้ให้ฉันหนึ่งตัวสำหรับตัวเลขและอีกตัวหนึ่งสำหรับสตริง

// This is a safety check to make sure the prototype is not already defined.
Function.prototype.method = function (name, func) {
    if (!this.prototype[name]) {
        this.prototype[name] = func;
        return this;
    }
};

// returns the int value or -1 by default if it fails
Number.method('tryParseInt', function (defaultValue) {
    return parseInt(this) == this ? parseInt(this) : (defaultValue === undefined ? -1 : defaultValue);
});

// returns the int value or -1 by default if it fails
String.method('tryParseInt', function (defaultValue) {
    return parseInt(this) == this ? parseInt(this) : (defaultValue === undefined ? -1 : defaultValue);
});

หากคุณไม่ต้องการใช้การตรวจสอบความปลอดภัยให้ใช้

String.prototype.tryParseInt = function(){
    /*Method body here*/
};
Number.prototype.tryParseInt = function(){
     /*Method body here*/
};

ตัวอย่างการใช้งาน:

var test = 1;
console.log(test.tryParseInt()); // returns 1

var test2 = '1';
console.log(test2.tryParseInt()); // returns 1

var test3 = '1a';
console.log(test3.tryParseInt()); // returns -1 as that is the default

var test4 = '1a';
console.log(test4.tryParseInt(0));// returns 0, the specified default value

1
// implicit cast
var value = parseInt(tbb*1); // see original question

คำอธิบายสำหรับผู้ที่ไม่พบว่ามันเล็กน้อย:

การคูณด้วยวิธีการที่เรียกว่า "การส่งโดยนัย" พยายามที่จะเปลี่ยนชนิดของตัวดำเนินการที่ไม่รู้จักเป็น 'หมายเลข' ชนิดดั้งเดิม โดยเฉพาะอย่างยิ่งสตริงว่างจะกลายเป็นหมายเลข 0 ทำให้มันเป็นประเภทที่มีสิทธิ์สำหรับ parseInt () ...

ตัวอย่างที่ดีมากที่ได้รับข้างต้นโดย PirateApp ผู้แนะนำให้ใส่เครื่องหมายบวกเพื่อบังคับให้ JavaScript ใช้การส่งแบบตัวเลขโดยนัย


มันเป็นคำตอบโดยตรงกับคำถามเดิมที่รักของฉัน
Fabien Haddadi

สิ่งนี้จะไม่เกิดขึ้นparseInt('str'*1)
Rodion Baskakov

ทำไมต้องโทรหาparseIntบางสิ่งที่มีหมายเลขอยู่แล้ว? ที่จะเกิดขึ้นอีกการแปลงกลับไปที่สตริงเท่านั้นที่จะแปลงเป็นจำนวนอีกครั้ง
trincot

0

ด้วยวิธีนี้ทำไมไม่เขียนฟังก์ชั่นและเรียกมันว่าเคยต้องการ ฉันสมมติว่ามันเป็นรายการในเขตข้อมูลฟอร์มเพื่อทำการคำนวณ

var Nanprocessor = function (entry) {
    if(entry=="NaN") {
        return 0;
    } else {
        return entry;
    }
}

 outputfield.value = Nanprocessor(x); 

// where x is a value that is collected from a from field
// i.e say x =parseInt(formfield1.value); 

มีอะไรผิดปกติในการทำเช่นนี้?


สวัสดีวัดหยุดเราจากวิธีการดังกล่าวข้างต้น ต้องการทราบและเรียนรู้
Naresh

3
คุณควรใช้isNaNNaNการทดสอบ
Matthew

2
ขอบคุณ Matt :) ฉันไม่รู้ว่ามีฟังก์ชันที่เรียกว่า isNaN () ใน javascrip! ขอบคุณสำหรับการให้ฉันรู้ว่า...!
Naresh

0

นี่เป็นวิธี tryParseInt ที่ฉันใช้นี่ใช้ค่าเริ่มต้นเป็นพารามิเตอร์ที่สองเพื่อให้เป็นสิ่งที่คุณต้องการ

function tryParseInt(str, defaultValue) {
    return parseInt(str) == str ? parseInt(str) : defaultValue;
}

tryParseInt("", 0);//0 
tryParseInt("string", 0);//0 
tryParseInt("558", 0);//558

0

ฟังก์ชั่นตัวช่วยซึ่งยังอนุญาตให้ใช้ radix

function parseIntWithFallback(s, fallback, radix) {
    var parsed = parseInt(s, radix);
    return isNaN(parsed) ? fallback : parsed;
}

0

คุณสามารถมีรหัสที่สะอาดมากฉันมีปัญหาที่คล้ายกันและฉันแก้ไขได้โดยใช้:

var a="bcd";
~~parseInt(a);

0

สำหรับคนอื่นที่กำลังมองหาวิธีแก้ปัญหานี้เพียงใช้: ~~โดยไม่ต้องแยกวิเคราะห์มันเป็นโหมดที่สะอาดที่สุด

var a = 'hello';
var b = ~~a;

ถ้า NaN มันจะคืนค่า 0 แทน

OBS วิธีนี้ใช้ได้เฉพาะจำนวนเต็มเท่านั้น

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.