iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 14
0

錯誤

這邊是語言的貼身教練,在你把文章打好,要放上去之前,教練會先對內容看看語句是否通暢。

句子 錯誤
好嗎你? ReferenceError
真的。長大了, SyntaxError
都變型男了! TypeError ( 其實是美女來著。 )

主要是 JavaScript 自動捕捉在編譯的時期,發現無法編譯的早期錯誤 ( early error )。
後續會再講解執行時期 ( runtime ),使用 try..catch 以外,來捕捉錯誤的規則。

var a = /+foo/;   // SyntaxError

var a;
42 = a;           // ReferanceError

function foo(a,b,a) {}              // pass
function bar(a,b,a) {"use strict";} // SyntaxError

var a = {b:42, b:43};
a.b;                      // 43
(function() {
    "use strict";
    var m = {p:42, p:43}; // chrome 沒有錯誤不回傳,firefox 會回傳 log。
    console.log(m.p);     // 43
}());

最後一個物件字面值,帶名稱相同的屬性。在測試中沒發生錯誤。再請多多指教。

過早使用變數

ES6 的新概念,導入了 TDZ ( Temporal Dead Zone )。

TDZ 代表的是某個變數的參考動作還不能進行的地方,因為該變數尚未達成必要的初始化動作。

ES6 let 的範例。

{
    typeof a; // undefined
    typeof b; // ReferenceError ! (TDZ)
    let b;
}

函數引數

function foo( a=42, b = a + b + 5 ){}
foo();    // ReferenceError

因為 b = a + b + 5 的 b 參考 會在 參數 b 的 TDZ 中發生。 但 a 就沒有問題

function foo( a = 42, b = a + 1){
    console.log( a, b );
}
foo();            // 42 43
foo( undefined ); // 42 43
foo( 5 );         // 5 6
foo( void 0, 7 ); // 42 7
foo( null );      // null 1

就目前看起來沒傳值,和傳入 undefined 結果相同。
要怎麼分辨? 用 arguments

function foo( a = 42, b = a + 1 ){
    console.log(
        a, b, arguments.length, arguments[0], arguments[1]
    );
}
foo();      // 42 43 2 undefined undefined
foo( 10 );  // 10 11 1 10 undefined
foo( 10, undefined ); // 10 11 2 10 undefined
foo( 10, null );      // 10 null 2 10 null
foo( null, 10 );      // null 10 2 null 10  

用這個方法就可以分辨傳入的參數值,他會插入 argument 陣列的插槽中。如果沒插入,不會有對應的條目 ( entries ),但會顯示 undefined。

但如果對參數在做一次 assign 呢? 他會產生連結,把值傳入 arguments,這會造成資訊洩露。

function foo(a){
    a = 42;
    console.log( arguments[0] );
}
foo( 2 ); // 42
foo();    // undefined

你可以使用嚴格模式避免。

function foo(a){
    "use strict"
    a = 42;
    console.log( arguments[0] );
}
foo( 2 ); // 2
foo();    // undefined

這後面有一些 argument 陣列被棄用,以及他原先好處的描述。這邊就不贅述了。

try..finally

這邊主要是介紹 finally 的用法,還有他執行時的優先順序。

Tony 歸納的規則,如下
執行 try -> 執行 finally -> 執行 loop 的迭代 -> 顯示 finally -> 顯示 try (若被覆蓋就不顯示)

套用這個規則看書上的程式碼會更有感覺。

最後,如果你想解出讓人困惑到死的程式碼,可以使用 finally 加上帶有標籤的 break 來產生取消 return 的效果。

總結

  • 錯誤訊息有在編譯前,和執行時期的勘誤。
  • arguments 的使用方式。
  • try..finally 的優先序。

明~天~見~

參考資料

  1. 你所不知道的 JS
  2. MDN - The arguments object( arguments 使用方式 )
  3. MDN - Function.arguments( 已棄用 )

上一篇
Day13 - 運算子優先序
下一篇
Day15 - 何謂範疇?
系列文
你為什麼不問問神奇 JavaScript 呢?30

尚未有邦友留言

立即登入留言