iT邦幫忙

2023 iThome 鐵人賽

DAY 3
0
自我挑戰組

Jr 前端工程師面試題目檢討賽系列 第 3

【2023 挑戰賽 Day3】 #JS catch()的陷阱

  • 分享至 

  • xImage
  •  

只剩下最後一部,今天我們終於要把一個題目給解決了~
寫到第三天,各位會不會覺得自己每天只討論這麼小的部分,三天才解完一題,幫助好像不大呢?
前陣子看到一篇前輩的就職半年心得 (剛剛本來想找原文,但臨時遍尋不到QAQ,找到之後一定來分享)
裡面就有提到一個讓我印象最深刻的地方:

她們公司主管每一陣子就會安排一個小小的技術題目,讓大家深入探討與解答,
「每天要遇到的技術規格很龐大,讓人忘記了,每一個複雜技術的背後,都是由這些小小的疑問所累積起來的。」

對我來說,寫一篇鐵人賽文章要花費的時間頂多是一到一個半小時,專注在一個看似超小的細節,
但光是用我覺得最白話、最易懂的方式搞懂一個觀念,加深自己的印象,未來就更能朝向複雜的問題去克服了。

(老實跟大家說,我現在連 LeetCode easy 一題都解不出來,還是找到了一份 junior 前端的工作XD)
(代表 LeetCode Easy 還是太難了)(誤)

閒聊結束了,那就讓我們把這個題目完成吧!

/images/emoticon/emoticon07.gif

複習 Day1、Day2

接續昨天的,我重貼一次題目與程式碼

try {
 throw new Error();
}catch(x){
    var x = 'X'
    var y = 'Y'
    const z = 'Z'
    console.log(`${x} is in the catch`)
    console.log(`${y} is in the catch`)
    console.log(`${z} is in the catch`)
}
    console.log(`${x} is outside the catch`)
    console.log(`${y} is outside the catch`)
    console.log(`${z} is outside the catch`)

首先在 Day1,我們了解到由於 try...catch 例外處理的執行流程,六個 console.log 執行的順序會從 catch 區塊,依序由上而下,進行到下方的外部區塊。
接著在 Day2,我們了解到由於變數的特性,所以會有提升、作用域的限制、重新賦值的特性。

於是略過 console.log(${x} is outside the catch) 這條之外,我們所知的執行結果將會是:

X is in the catch
Y is in the catch
Z is in the catch
// 略過,等等來討論!
Y is outside the catch
Uncaught ReferenceError: z is not defined

好的,那就讓我們開始來討論 console.log(${x} is outside the catch) 這一條到底會是什麼執行結果囉~

三、catch 傳入參數

好的,來到壓軸的單元了,為什麼明明 x 跟 y 都是 var 變數、都放在一樣的位置,但這邊要故意拉出來談,陷阱到底是什麼?

/images/emoticon/emoticon19.gif(為什麼呢?)

不賣關子了,大家看到這個標題應該就知道提示很明顯了,沒錯,因為 catch() 中我們傳入了 x。

通常在 try...catch 的語句中, 我們會在 catch()中放入一個 error 參數,也就是一個代表錯誤訊息的物件,而 error 也可以是一個自訂的變數名稱,通常都會寫成 e 或是 error。

重新複習一次,程式碼在 try 區塊拋出錯誤後會暫停、並進入 catch 區塊執行,並針對錯誤狀況做處理,
例如:

try {
  // 嘗試執行會拋出錯誤的程式碼
  throw new Error();
} catch (error) {
  // 處理錯誤
  console.error("An error occurred:", error.message);
}

所以當我們把 x 作為參數傳入 catch()區塊,X 實際上是被當作 error 物件。
我們先不要在 catch 區域為 x 賦值,先把 x 作為 error 物件印出結果看看:

try {
 throw new Error();
}catch(x){
    console.log(x) // Error: 
}

此時,當我們不在 catch 區塊為 error 物件賦值的話,就會看到輸出空白的 Error: ,如果我們將 throw new Error() 改成 throw new Error('This is a custom error mesage'),就會看到 console.log(x) 輸出的訊息為 Error: This is a custom error message,這就是我們為 error 物件給予一個錯誤訊息的結果。

try {
 throw new Error('This is a custom error mesage')
}catch(x){
    // 先註解掉 x = 'X
    console.log(x) // Error: This is a custom error message 
}

而當我們在 catch 為 error 物件用 = 來賦值,就會把原本物件的值蓋掉。
所以乍看之下,x 與 y 是一樣的,但 x 在 catch 區域中被當作一個錯誤物件,所以當我們在 catch 以外嘗試存取 x 時,只會收到 undefined 的結果。

var x; // var 變數被提升到外部,此時若存取 x 變數將獲得 undefined

try {
 throw new Error();
}catch(x){
    // 在 catch 區塊, x 跟外面的 var x 無關,並不會影響 var x,而是代表一個錯誤物件
    x = 'X'
    console.log(`${x} is in the catch`) // 覆蓋錯誤物件 x 的值
}
    console.log(`${x} is outside the catch`) // undefined 

於是,我們終於能夠回答這個題目的答案了!

請問下列程式碼執行結果為何?

try {
 throw new Error();
}catch(x){
    var x = 'X'
    var y = 'Y'
    const z = 'Z'
    console.log(`${x} is in the catch`)
    console.log(`${y} is in the catch`)
    console.log(`${z} is in the catch`)
}
    console.log(`${x} is outside the catch`)
    console.log(`${y} is outside the catch`)
    console.log(`${z} is outside the catch`)

執行結果依序是:

X is in the catch
Y is in the catch
Z is in the catch
undefined is outside the catch
Y is outside the catch
Uncaught ReferenceError: z is not defined

歐耶!完成!

我解答完一個把我考倒的面試題目了~/images/emoticon/emoticon01.gif

今天沒有把細節探討到太深,如果沒有說得很詳盡的地方,歡迎大家幫忙補充,之後我也會再多補充一些資料!

那我們 Day4 見~

參考資料:
MDN: try...catch 語法


上一篇
【2023 挑戰賽 Day2】 #JS 變數提升
下一篇
【2023 挑戰賽 Day4】#轉職經驗 那裡還有許多混沌與未知
系列文
Jr 前端工程師面試題目檢討賽14
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言