keywords:prototype
,polyfilling
,transpiling
,array-like
原型 ( Prototype )
- 當我們參考物件上的一個特性 ( property )ex:
f1.car // 參考 f1 物件上的 car 特性
,如果 f1 本身不存在 car 特性,JavaScript 會自動使用 f1 物件內部的原型參考( prototype reference ),在 f1 原型物件上尋找 car 特性。 也可以視原型參考是物件缺少特性時的一種後備機制,而不是直接跳出錯誤。
看個範例:const f1 = { x: 9 } // 建立 f2 並將它連結到 f1 const f2 = Object.create(f1); f2.y = 'hi' f2.y; // 'hi' f2.x; // 9
f2.x 之所以回傳 9 是因為 x 是 f1 的原型 | |
---|---|
- 這種連結特色最常被試著 模擬/虛構 具有繼承( inheritance )能力的類別 ( class ) 機制
- 實際上應用原型的一種自然方式叫做行為委派 ( behavior delegation ),在這模式下會刻意將連結的物件設計成能夠將所需的部分行為委派給其他物件
Polyfilling
- polyfill 一詞是被發明出來的術語,意思是依據一個新功能的定義,在舊的 JavaScript 環境中,產生具有相同行為的程式碼,由 Remy Sharp 所創。
- ES6 定義了一個叫 Number.isNaN(..) 的工具函式,以精確且無臭蟲的方式來檢查是否為 NaN 值,在舊的 JavaScript 環境中並沒有這種函式,所以我們可以 polyfill
ex:if(!Number.isNaN) { // 防止這個工具在 ES6 瀏覽器上套用這個 polyfill定義 Number.isNaN = function isNaN (x) { return x !== x; }; }
- 🚩 NaN 是整個語言中唯一不等於自己的值 O.o
- 並非所有新功能都完全可 polyfill ,但自己實作總是未必能符合語言的規格,所以最好是使用一組詳細審核且能夠信任的 polyfill 例如:ES5-Shim 和 ES6-Shim
Transpiling
- 當一些新功能無法被 polyfill 至新瀏覽器時,較好的選擇是使用能將新程式碼轉換為等效舊程式碼的工具,這個過程叫做 『 transpiling 』,此詞結合了 transforming ( 變換 ) 及 compiling ( 編譯 ) 兩詞
通常在建置過程 ( build process )加入 transpiler ,就像程式碼的 linter 或 minifier 壓縮成更小的檔案
看個範例:function f1(x = 9) { console.log(x); } f1(); // 9 f1(1); // 1
這裡使用了 ES6 新增的功能,預設參數 ( default parameter values ),也就是這一行
function f1(x = 9) {
,意思是如果調用 f1 時沒有傳入參數就把 x 設為 9作為一個 transpiler 要如何讓舊環境也能執行一樣的功能呢?
function f1() { let x = arguments[0] !== ( void 0 ) ? arguments[0] : 9; console.log(x) }
what? 🤔
幾個 Tips:- 根據 MDN 文檔 arguments:類陣列( Array-like )物件可以讀取傳入 function 的參數
"Array-like" 類陣列可以使用 array 特性 .length,第一個索引為 0,但不包括 array 的方法像是 forEach()、map() 或 pop()
function f1() { console.log('arguments[0]:',arguments[0]); } f1(4,5,6); // arguments[0]: 4 f1(); // arguments[0]: undefined
function f2() { arguments.forEach(item => console.log(item)); } f2(7,8,9); // Uncaught TypeError: arguments.forEach is not a function
void 0; // undefined
- transpiler 應該被視為 JavaScript 開發生態系統及程序的標準,因為每幾個月就會有新語法和新功能被加入
- 現在有不少很棒的 transpilers 可以挑選:
- Babel ( 之前的 6to5 ):將 ES6 以上版本程式碼 transpile to ES5
- Traceur:將 ES6、ES7 等之後版本的程式碼 transpile to ES5