อะไรคือข้อแตกต่างระหว่าง“ โยนข้อผิดพลาดใหม่” และ“ โยนข้อผิดพลาดบางอย่าง”


378

ฉันต้องการที่จะเขียนตัวจัดการข้อผิดพลาดทั่วไปซึ่งจะจับข้อผิดพลาดที่กำหนดเองที่เกิดขึ้นกับจุดประสงค์ที่โค้ดใด ๆ

เมื่อฉันไม่throw new Error('sample')ชอบในรหัสต่อไปนี้

try {
    throw new Error({'hehe':'haha'});
    // throw new Error('hehe');
} catch(e) {
    alert(e);
    console.log(e);
}

เข้าสู่ระบบแสดงใน Firefox เป็นError: [object Object]และฉันไม่สามารถแยกวัตถุ

สำหรับบันทึกที่สองthrowแสดงเป็น:Error: hehe

ในขณะที่ฉันทำ

try {
    throw ({'hehe':'haha'});
} catch(e) {
    alert(e);
    console.log(e);
}

คอนโซลแสดงเป็น: Object { hehe="haha"}ซึ่งฉันสามารถเข้าถึงคุณสมบัติข้อผิดพลาด

อะไรคือความแตกต่าง?

ความแตกต่างที่เห็นในรหัสคืออะไร? เช่นเดียวกับสตริงจะถูกส่งผ่านเป็นสตริงและวัตถุเป็นวัตถุ แต่ไวยากรณ์จะแตกต่างกันอย่างไร

ฉันไม่ได้สำรวจวัตถุข้อผิดพลาดในการขว้างปา ... ฉันทำแค่โยนสาย

มีวิธีอื่นนอกเหนือจากสองวิธีที่กล่าวมาข้างต้นหรือไม่?


6
ปัญหาของการโยน Error ใหม่ ({prop: val}) ไม่ใช่การสร้าง Error ที่ถูกต้อง ข้อผิดพลาดได้รู้จักคุณสมบัติตามที่ Hemant อธิบายไว้
grantwparks

เกี่ยวข้อง: การขว้างสตริงแทนErrors
Bergi

คำตอบ:


216

นี่คือคำอธิบายที่ดีเกี่ยวกับวัตถุข้อผิดพลาดและโยนข้อผิดพลาดของคุณเอง

วัตถุข้อผิดพลาด

สิ่งที่เราสามารถดึงออกมาจากมันในกรณีที่มีข้อผิดพลาด? วัตถุข้อผิดพลาดในเบราว์เซอร์ทั้งหมดสนับสนุนคุณสมบัติสองประการต่อไปนี้:

  • ชื่อ: ชื่อของข้อผิดพลาดหรือเฉพาะเจาะจงมากขึ้นชื่อของฟังก์ชั่นการสร้างข้อผิดพลาดเป็นของ

  • ข้อความ: คำอธิบายของข้อผิดพลาดโดยคำอธิบายนี้จะแตกต่างกันไปตามเบราว์เซอร์

ค่าที่เป็นไปได้หกค่าสามารถส่งคืนได้โดยคุณสมบัติชื่อซึ่งตามที่กล่าวถึงสอดคล้องกับชื่อของตัวสร้างข้อผิดพลาด พวกเขาคือ:

Error Name          Description

EvalError           An error in the eval() function has occurred.

RangeError          Out of range number value has occurred.

ReferenceError      An illegal reference has occurred.

SyntaxError         A syntax error within code inside the eval() function has occurred.
                    All other syntax errors are not caught by try/catch/finally, and will
                    trigger the default browser error message associated with the error. 
                    To catch actual syntax errors, you may use the onerror event.

TypeError           An error in the expected variable type has occurred.

URIError            An error when encoding or decoding the URI has occurred 
                   (ie: when calling encodeURI()).

โยนข้อผิดพลาดของคุณเอง (ข้อยกเว้น)

แทนที่จะรอให้เกิดข้อผิดพลาดหนึ่งใน 6 ประเภทก่อนที่การควบคุมจะถูกถ่ายโอนโดยอัตโนมัติจากบล็อกลองไปยังบล็อก catch คุณยังสามารถโยนข้อยกเว้นของคุณเองอย่างชัดเจนเพื่อบังคับให้สิ่งนั้นเกิดขึ้นตามความต้องการ นี่เป็นสิ่งที่ยอดเยี่ยมสำหรับการสร้างคำจำกัดความของคุณเองว่าเกิดข้อผิดพลาดอะไรและเมื่อใดที่การควบคุมควรจะถูกถ่ายโอน


4
โอ้ใช่. นี่เป็นสิ่งที่ดีอย่างหนึ่งที่ฉันพลาดไปก่อนถามคำถามนี้ อย่างไรก็ตามผู้ใช้ที่ค้นหาข้อมูลที่เกี่ยวข้องกับเรื่องนี้จะถูกล้างออก ตอนนี้ฉันชัดเจนในสิ่งที่เป็นอะไร :) ขอบคุณ. ฉันจะกลับไปลงคะแนนในอีกไม่กี่วัน
Jayapal Chandran

184
ยังไม่ได้ตอบคำถาม แต่เป็นคำตอบที่ upvoted ที่สุด?
user9993

@ user9993 User ho คำถามที่ถามคือมองหาความเข้าใจโดยละเอียดตามการแชทในเวลานั้นดังนั้นคำตอบจึงได้รับการตอบสนองและเป็นประโยชน์ต่อผู้ใช้ นั่นคือเหตุผลในการยอมรับและโหวตมากที่สุด
Hemant Metalia

5
@HemantMetalia แต่เขาพูดถูกคำตอบไม่ได้แม้แต่ความพยายามเพียงเล็กน้อยในการตอบคำถาม OPs ตามที่ระบุไว้ หากคำตอบที่แตกต่างกันมากในการแชทได้รับคำตอบที่ควรจะอยู่ในการแชทคำถามและคำตอบที่นี่ไม่มีการเชื่อมต่อทางตรรกะใด ๆ
Mörre

และเพื่อตอบคำถามเดิมมันไม่สำคัญกับ Javascript อย่างไรก็ตามError(และคลาสย่อย) ถูกใช้โดยการประชุม โดยค่าเริ่มต้นยังมีคุณสมบัติสแต็กแม้ว่าสามารถเพิ่มได้ด้วยตนเอง ดังนั้นมันจริงๆส่วนใหญ่การประชุมการไหลของโปรแกรมจะไม่ได้รับผลกระทบจากสิ่งที่คุณโยนเพียงว่าคุณthrowในทุกเรื่อง คุณสามารถทำได้throw "grandmother down the stairs";และมันจะทำงานได้เหมือนกันยกเว้นว่าจะไม่มีฟังก์ชั่นการติดตามสแต็กและการจัดการข้อผิดพลาดนักข่าวเดบั๊กที่คาดหวังErrorหรือคุณสมบัติที่มาพร้อมกับเพื่อให้แม่นยำยิ่งขึ้น
Mörre

104

โยน "ฉันชั่ว"

throwจะยุติการดำเนินการเพิ่มเติม & เปิดเผยสตริงข้อความเมื่อ พบข้อผิดพลาด

try {
  throw "I'm Evil"
  console.log("You'll never reach to me", 123465)
} catch (e) {
  console.log(e); //I'm Evil
}

คอนโซลหลังจากโยนจะไม่ถึงสาเหตุของการยกเลิก


โยนข้อผิดพลาดใหม่ ("ฉันน่ารักมาก")

throw new Errorแสดงเหตุการณ์ข้อผิดพลาดพร้อมชื่อและข้อความสองรายการ นอกจากนี้ยังยุติการดำเนินการต่อไป

try {
  throw new Error("I'm Evil")
  console.log("You'll never reach to me", 123465)
} catch (e) {
  console.log(e.name, e.message); //Error, I'm Evil
}


16
สิ่งที่เกี่ยวกับความแตกต่างระหว่าง "การโยนข้อผิดพลาด ('อะไรก็ตาม')" และ "การโยนข้อผิดพลาดใหม่ ('อะไรก็ตาม')" - ทั้งสองทำงาน
joedotnot

9
ข้อผิดพลาดทำงานได้ข้อผิดพลาดใหม่เป็นตัวสร้าง ทั้งทำงานเหมือนกัน developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
......

5
@NishchitDhanani ฉันคิดว่ามันแปลกที่ความคิดเห็นที่อ่านไม่ออกและไม่ถูกต้องจะได้รับการอัปเดต ทั้ง "ข้อผิดพลาดทำงานได้" และ "ข้อผิดพลาดใหม่เป็นตัวสร้าง" ไม่สมเหตุสมผลเลยและ / หรือผิด ในบริบทนั้นมันไม่ชัดเจนว่าลิงค์ควรจะ "พิสูจน์" เป็นหน้า MDN ใช่Errorไหมการเชื่อมต่อกับความคิดเห็นอยู่ที่ไหน ครึ่งหนึ่งของผู้คนที่แสดงความคิดเห็นและตอบคำถาม OP ควรน่าจะนิ่งเงียบ
Mörre

@ Mörreดูส่วนนี้Used as a functionจากลิงก์นี้ ... developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nishchit Dhanani

โอเคฉันเข้าใจแล้ว มันเป็นฟังก์ชั่น
Nishchit Dhanani

73

บทความต่อไปนี้อาจกล่าวถึงรายละเอียดเพิ่มเติมซึ่งเป็นตัวเลือกที่ดีกว่า throw 'An error'หรือthrow new Error('An error'):

http://www.nczonline.net/blog/2009/03/10/the-art-of-throwing-javascript-errors-part-2/

มันแสดงให้เห็นว่าหลัง ( new Error()) มีความน่าเชื่อถือมากกว่าเนื่องจากเบราว์เซอร์เช่น Internet Explorer และ Safari (ไม่แน่ใจรุ่น) ไม่ได้รายงานข้อความอย่างถูกต้องเมื่อใช้อดีต

การทำเช่นนั้นจะทำให้เกิดข้อผิดพลาด แต่เบราว์เซอร์บางตัวไม่ตอบสนองตามที่คุณคาดหวัง แต่ละ Firefox, Opera และ Chrome แสดงข้อความ“ ข้อยกเว้นที่ไม่ได้ตรวจสอบ” จากนั้นรวมสตริงข้อความ Safari และ Internet Explorer เพียงแค่โยนข้อผิดพลาด“ ข้อยกเว้น uncaught” และไม่ได้ให้สตริงข้อความเลย เห็นได้ชัดว่านี่เป็นสิ่งที่ไม่ดีจากมุมมองการดีบั๊ก


36

คุณพูดถึงรหัสนี้ก่อน:

throw new Error('sample')

และจากตัวอย่างแรกของคุณคุณเขียน:

throw new Error({'hehe':'haha'}) 

วัตถุข้อผิดพลาดแรกจะใช้งานได้จริงเนื่องจากคาดหวังว่าค่าสตริงในกรณีนี้ 'ตัวอย่าง' อันที่สองจะไม่เป็นเพราะคุณพยายามส่งผ่านวัตถุและคาดว่าจะเป็นสตริง

วัตถุข้อผิดพลาดจะมีคุณสมบัติ "ข้อความ" ซึ่งจะเป็น 'ตัวอย่าง'


12
ส่วนที่สองใช้งานได้ แต่ไม่ได้มีประโยชน์มาก มันดำเนินการtoString()วิธีการกับวัตถุที่ผ่านเข้ามาส่งผลให้เกิด[object Object]ข้อผิดพลาด (ตามที่ Op เขียน)
cjn


15

คุณสามารถthrowเป็นวัตถุ

throw ({message: 'This Failed'})

ยกตัวอย่างเช่นในของคุณ try/catch

try {
//
} catch(e) {
    console.log(e); //{message: 'This Failed'}
    console.log(e.message); //This Failed
}

หรือเพียงแค่โยนข้อผิดพลาดสตริง

throw ('Your error')

try {
//
} catch(e) {
    console.log(e); //Your error
}

throw new Error //only accept a string

15

ตัวErrorสร้างใช้ในการสร้างวัตถุข้อผิดพลาด โยนวัตถุข้อผิดพลาดเมื่อเกิดข้อผิดพลาดรันไทม์ วัตถุข้อผิดพลาดสามารถใช้เป็นวัตถุพื้นฐานสำหรับข้อยกเว้นที่ผู้ใช้กำหนด

ข้อผิดพลาดที่ผู้ใช้กำหนดถูกโยนผ่านthrowคำสั่ง การควบคุมโปรแกรมจะถูกส่งไปยังcatchบล็อกแรกในสแตกการโทร

ความแตกต่างระหว่างการโยนข้อผิดพลาดที่มีและไม่มีวัตถุข้อผิดพลาด:


throw {'hehe':'haha'};

ใน Chrome devtools มีลักษณะดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

Chrome บอกเราว่าเรามีข้อผิดพลาดที่ไม่สามารถตรวจจับได้ซึ่งเป็นเพียงวัตถุ JS วัตถุนั้นอาจมีข้อมูลเกี่ยวกับข้อผิดพลาด แต่เรายังไม่ทราบทันทีว่ามาจากไหน ไม่มีประโยชน์มากเมื่อเราทำงานกับโค้ดของเราและทำการดีบั๊ก


throw new Error({'hehe':'haha'}); 

ใน Chrome devtools มีลักษณะดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ข้อผิดพลาดที่เกิดขึ้นกับวัตถุ Error ทำให้เราสามารถติดตามสแต็กได้เมื่อเราขยาย สิ่งนี้ให้ข้อมูลที่มีค่าแก่เราเมื่อเกิดข้อผิดพลาดซึ่งมักเป็นข้อมูลที่มีค่าเมื่อทำการดีบั๊กโค้ดของคุณ โปรดทราบเพิ่มเติมว่าข้อผิดพลาดระบุว่า [object Object]เป็นเพราะตัวErrorสร้างต้องการสตริงข้อความเป็นอาร์กิวเมนต์แรก เมื่อได้รับวัตถุมันจะบีบบังคับมันให้เป็นสตริง


2

พฤติกรรมตอบสนอง

นอกเหนือจากคำตอบที่เหลือฉันต้องการแสดงความแตกต่างใน React

ถ้าฉันขว้าง a new Error()และฉันอยู่ในโหมดการพัฒนาฉันจะได้รับหน้าจอข้อผิดพลาดและบันทึกของคอนโซล ถ้าฉันโยนตัวอักษรสตริงฉันจะเห็นมันในคอนโซลและอาจพลาดถ้าฉันไม่ได้ดูบันทึกคอนโซล

ตัวอย่าง

การโยนข้อผิดพลาดเข้าสู่คอนโซลและแสดงหน้าจอข้อผิดพลาดขณะอยู่ในโหมดการพัฒนา (หน้าจอจะไม่ปรากฏในการผลิต)

throw new Error("The application could not authenticate.");

หน้าจอข้อผิดพลาดในการตอบสนอง

ในขณะที่รหัสต่อไปนี้เข้าสู่คอนโซลเท่านั้น:

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