[18] 原生功能 Natives - Array、Object、Function、RegExp、Date、Error


keywords:natives,array,object,function,RegExp,date,error

作為建構器的 Natives

array、object、function、RegExp、Date、Error 使用字面形式來建立這些值,與建構器形式所創建的物件相同,但還是要避免使用建構器,因為有陷阱跟例外

陣列 ( Array )

    let a = new Array(4,5,6);

    a; // [4,5,6]

    let b = [4,5,6];

    b; // [4,5,6]
  • Array 建構器有一種特殊 ( 糟糕 ) 的使用方法,只有一個 number 引數被傳入建構器不會把該值當作陣列的內容,而是將它當成一個長度來『 預先設定陣列的大小 』
  • 但實際上沒有預設陣列大小這種事情存在,所建立出來的其實是空陣列,只不過該陣列的 length 特性被設定為所指定的數值
    看看例子:

      let a = new Array(3);
    
      a.length; // 3
    
      a; // [empty × 3]    可怕的是這在各大不同瀏覽器裡會顯示出不同結果 這裡是 Chrome 的結果
    
      a; // [] (3) = $1    safari 宣告時要使用 var a = new Array(3);
    

    這裡跟之前在 [12]值-陣列、類陣列 時介紹的蠻類似的,如果鍵值 ( key ) 的 string 能被強制轉型為標準的十進位 number ,JavaScript 會假設你想把它當成一個 number 所以來使用,而非作為一個 string 鍵值

      let f = [];
    
      f['3'] = 99;
    
      f.length; // 4
    
      f; // [ empty * 3 , 99 ]
    
  • 不管在任何情況下,永遠不要刻意建立並使用這種怪異的空插槽陣列,來比較以下三種狀況:

      let a = new Array(3);
    
      let b = [undefined,undefined,undefined];
    
      let c = [];
    
      c.length = 3;
    
      a; // [empty × 3]
    
      b; // [undefined, undefined, undefined]
    
      c; // [empty × 3]
    
      delete a[1]; // [empty × 3]
    
      delete b[1]; // [undefined, empty, undefined]
    
      delete c[1]; // [empty × 3]
    

Object、Function、RegExp

這些建構器通常也都是非必須的,但 RegExp(..) 具有某些合理的功能:動態地為一個正規表達式定義範式 ( pattern )

    let name = 'Eason';

    let namePattern = new RegExp("\\b(?:"+name+")+\\b","ig");

    'My name is :Eason'.match(namePattern); // ["Eason"]

這種情境常在 JavaScript 中出現,所以會需要使用 new RegExp('pattern','flags') 形式,不過還是強烈建議使用字面值形式定義的正規表達式( regular expressions ),主要的原因是因為效能,JavaScript 引擎會在程式碼執行前預先編譯並快取它們。

Date、Error

這兩個原生建構器有用多了,因為這兩者皆沒有字面值形式可用 XD

Date

  • 要建立一個日期物件值,必須使用 new Date(),此建構器接受額外的引數,以指定使用的日期與時間,若省略就會假設是目前的日期時間

      new Date(); // Fri Nov 29 2019 11:18:56 GMT+0800 (台北標準時間)
    
      new Date().getTime(); // 1574997536447
    
  • 有一個更簡單的方法,呼叫 ES5 所定義的靜態輔助函式 ( static helper function ): Date.now()
      Date.now(); // 1574997536447
    
  • 可以發現呼叫 Date.now(); 會得到跟 new Date().getTime(); 一樣的一串數字,這是該瞬間日期時間的一個字串表示值( string representation )

Error

Error 建構器不管有沒有使用 new 關鍵字,行為都相同

  • 一般會想建立錯誤物件主要是將目前的執行堆疊情境( execution stack context )捕捉到該物件中,這個堆疊情境包括了函式呼叫堆疊( function call stack )及錯誤物件建立處的行號,這會使除錯工作容易許多
  • 錯誤物件的實體至少會有一個 message 特性,最好在錯誤物件上呼叫 toString() ,以取得經過格式化方便閱讀的錯誤訊息
  • 通常會藉由 throw 運算子來使用錯誤物件

      function f1(a) {
    
        if (!a) {
    
          throw new Error("a wasn't provided");
    
        }
    
        ...
      }
    
  • 同時可以使用 try…catch 處理錯誤

      try {
    
        throw new Error('Oops!');
    
      } catch (e) {
    
        console.log(e.name + ': ' + e.message);
    
      }
    
      // Error: Oops!
    
  • 也可以針對錯誤的型態做不一樣的處理

      try {
    
        obj.f1();
    
      } catch (e) {
    
        if (e instanceof EvalError) {
    
          console.log(e.name + ': ' + e.message);
    
        } else if (e instanceof RangeError) {
    
          console.log(e.name + ': ' + e.message);
    
        }
        ...
      }
    
#natives #Array #object #function #regexp #Date #error