[譯]typeof 與 instanceof 技巧 - 簡易的動態型別檢查

這邊文字要講的是關於使 instanceof 可適用於更多的情形下。

1. 關於 typeof vs instanceof

在 javascript 中,當我們需要確認一個值的型別時,我們就必須要選擇對應的方法。大略來說:

  • typeof 檢查某值是否為某種原生型別
1
if (typeof value === 'string')
  • instanceof 用來檢查某個值是否為某 class 的實例物件或建構函式。
1
if (value instanceof Map)

除此之外,value.constructorvalue.constructor.name 偶爾也可以派上用場。

光是檢查原生型別和物件的方式不一樣這樣就已經非常不理想了,然後在加上 javascript 一些詭異的行為就讓事情變的更加複雜

  • typeof nullobject 並不是 null。(typeof undefined -> undefined)
  • typeof 區分 objectfunction ,而兩者都是一種物件

上面這兩個詭異的行為導致沒有簡單方式直接拿 typeof 來檢查是否為物件

  • 並非所有的物件都是 Object 的物件實例
1
2
3
4
5
6
> Object.create(null) instanceof Object
false
o = {};
// 等於
o = Object.create(Object.prototype);

2. 讓 instanceof 可以檢查原生型別

使用特定的 PrimitiveNumber 類別,下面的程式碼可以讓 expression 表達式 x instanceof PrimitiveNumber 為 true。
而能夠辦到這樣的原因是因為我們使用 Symbol.hasInstance 實作了 PrimitiveNumber 的 static method 靜態方法

關於 Symbol.hasInstance
簡單說就把 Symbol.hasInstance 當作 method 的 key 就是提供我們客製 instanceof 行為的方法。

1
2
3
4
5
6
7
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === 'number'
}
}
console.log(123 instanceof PrimitiveNumber) // true
  1. 使用 TypeRight 函式庫檢查動態型別

TypeRight 是一個微型的函式庫用來檢查動態型別,另外它使用上面說明的方式實作。其 instanceof 運算子 如下

  • PrimitiveUndefined
  • PrimitiveNull
  • PrimitiveBoolean
  • PrimitiveString
  • PrimitiveSymbol

TypeRight 目前並不提供物件檢查的型別(PrimitiveObject) 不過您可以輕易的加入。

通過這些基本的功能,我們可以使用 TypeRight 檢查函式的參數是否正確

1
2
3
4
5
6
7
8
9
import * as tr from 'type-right'
function dist(x, y) {
tr.force(x, tr.PrimitiveNumber, y, tr.PrimitiveNumber)
return math.hypot(x, y)
}
dist(3, 4) // 5
dist(3, undefined) // TypeError

4. 其他檢查型別的方式

目前有兩個提案跟處理檢查型別有關的功能,正處於 stage 0 的狀態

4.1 模式匹配

這個提案稱為 ECMAScript Pattern Matching Syntax 是 Brian Terlson 和 Sebastian Markbage 提出的。
其中最主要的是 Symbol.matches 的概念,其大概的使用方式入下

1
2
3
4
5
class PrimitiveNumber {
static [Symbol.matches](x) { // (A)
return x instanceof this;
}
}

4.2 Builtin.is() 和 Builtin.typeOf()

這個提案是由 James M Snell 提出的。

Builtin.is(value1, value2) 可以檢查 value1value2 是否參考同一個 constructor。這個提案也考慮到了其他面向的問題

1
2
3
4
> Builtin.is(Date, vm.runInNewContext('Date'))
true
> Builtin.is(Date, Date)
true

Builtin.typeOf() 看起來就像是 typeof 的擴展,同時支援原生型別和內建的 class

1
2
3
4
5
6
7
8
9
10
11
Builtin.typeOf(undefined); // 'undefined'
Builtin.typeOf(null); // 'null'
Builtin.typeOf(123); // 'number'
Builtin.typeOf(new Number()); // 'Number'
Builtin.typeOf([]); // 'Array'
Builtin.typeOf(new Map()); // 'Map'
// The builtin counts, not the user-defined class
class MyArray extends Array {}
Builtin.typeOf(new MyArray()); // 'Array'

參考

分享到

[譯] sphinx-js 介紹 - Javascript 專案的文件工具

很長一段時間在 javascript 專案,文件的部分並沒有什麼好用的工具。JSDoc 大概是這個領域中唯一的競爭者,並且其設計中有些非常不錯的地方:

繼續閱讀

分享到

Rails Webpacker 筆記

在 Javascript 不斷快速變化的今日,對 Rails 而言一直有個相對支援度較不足的地方,那就是支援一些較新的 Javascript 封裝機制(bundle)。不過從 5.1 開始這個大家希望的功能將會支援 - 全新的 webpacker gem。

Rails 5.1 開始內建可以使用 --webpack 參數開啟支援 webpackeryarn,並且支援整合 ReactAngularVueelm 等。

繼續閱讀

分享到

使用 Rails Webpacker 安裝 Foundation 6

動機

由於 foundation-rails 6.4.1 版本有個 Issue 目前還沒合併。加上 Rails 已經支援了 webpack 2.x。這篇文章純粹紀錄另外一種做法。

繼續閱讀

分享到

Promise 學習筆記

這篇文章主要是為了複習與更加深入掌握 Javascript Promise 而產生的筆記。在直接閱讀關於 Promise A+ 或原理說明之前先通過比喻的方式理解可以更加深記憶。如果您對於 Promise 還是有點似懂非懂,不妨可以看看。

繼續閱讀

分享到

電子發票系統安裝

前言

1.png

支援電子發票,營業人必須使用 Turnkey Client 連線工具 來執行發票開立、發票作廢、發票註銷、折讓開立、折讓作廢等(傳送/接收發票資料檔案)。

本篇為 Turnkey Client on Ubuntu 的安裝筆記。

繼續閱讀

分享到

RabbitMQ 學習筆記 - 安裝、入門、Work Queues

本篇是關於 RabbitMQ 的入門學習筆記,內容從安裝到學習使用 Work Queue 的方式。能夠引導您快速入門。大部分的資料來自於官方的學習文件佐以實作時相關問題的資料補充。

繼續閱讀

分享到

Heroku 優化 Node 應用程式 - 併發

Node 對於擴展到不同規格的主機環境上其能力有限。首先是它是單執行緒,所以預設它不會自動使用額外的 CPU 核心。再者由於它基於 v8 引擎所以有記憶體上的限制概略是 1.5GB,所以也無法自動使用額外的記憶體。

因此 Nodejs 的應用程式需要多個進程來最大化可用的資源。這個過程我們稱為叢集,我們可以透過使用 Nodejs Cluster API 來完成這個功能。
我們可以直接在程式中使用 API 又或者使用基於這些 API 抽象化的函式庫。這裡我們將使用 throng

使用叢集的方式,應用程式可以善加利用各種 dyno 的資源使效能得到提升。Heroku 的 Nodejs buildpack 也提供一些環境變數來協助我們。

繼續閱讀

分享到

[譯] 使用 stream 的方式處理 JSON 傳輸

網頁應用程式在處理大量資料時一直都不是一件簡單的事。當需要接受大量資料時不只速度會變慢,且容易出錯,逾時等等。因此這是使用者體驗設計上的一個挑戰。
傳送大量資料同樣的也不容易,特別是在傳送前處理某些複雜的資料成為我們需要的資料時。

在這篇文章,我們將要來看看如何面對這些挑戰

繼續閱讀

分享到

使用 Passport 實作 Nodejs 應用程式驗證機制

為應用程式實作穩固的驗證機制一直以來都是令人害怕的工作,當然在 Nodejs 的世界中也不例外。

在這篇文章,我們將要從零開始開發一個 Nodejs 的應用程式搭配一套熱門的驗證 Middleware - passport
passport 本身單純只關注驗證相關的部分,在官方文件中它這麼描述:這是一套簡單,可無縫整合於 Node 的 Middlewre。理解它本質是 Middleware 有助於後續的應用。

繼續閱讀

分享到