JS魔法堂 函式過載 之 獲取變數的資料型別

2021-09-07 05:26:15 字數 3653 閱讀 9841

brief

有時我們需要根據入參的資料型別來決定呼叫哪個函式實現,就是說所謂的函式過載(function overloading)。因為js沒有內建函式過載的特性,正好給機會我們思考和實現一套這樣的機制。

使用方式:

function foo()

foo[

"object,number

"] = function(o, n)

foo[

"string

"] =function(s)

foo[

"array

"] = function(a)

機制實現:

;(function(e/*

xports*/)

}} function getsignature(args)

var rtypes = "

^\\s*

" + types.join("\

\s*,\\s*

") + "\

\s*$

"return

regexp(rtypes)

} function type(val)

}(window))

那現在問題就落在type函式的實現上了!

關於獲取變數的資料型別有typeof、object.prototype.tostring.call和obj.constructor.name三種方式,下面我們一起來了解一下!

typeof operator

語法: typeof val

內部邏輯:

function typeof

(val)

type(val)抽象操作的邏輯:

undefined -> "undefined"

null -> "object"

boolean -> "boolean"

number -> "number"

string -> "string"

objecjt,若物件為native object並且沒有[[call]]內建方法,則返回"object"

若物件為native object或host object且有[[call]]內建方法,則返回"function"

若物件為host object並且沒有[[call]]內建方法,則返回除"undefined"、"boolean"、"number"和"string"外的資料型別字串。

native object,就是math、、、new object()和regexp等js規範中定義的物件,其中math、regexp等程式執行時立即被初始化的物件被稱為built-in object。

host object,就是宿主環境提供的物件,如瀏覽器的window和nodejs的global。

從上述type(val)抽象操作的邏輯得知:

1. typeof能清晰區分boolean、number、string和function的資料型別;

2. 對於未宣告和變數值為undefined的變數無法區分,但對未宣告的變數執行typeof操作不會報異常;

3. typeof對null、陣列和物件是無能的。

針對2、3點我們可以求助於 object.prototype.tostring.call(val) 。

object.prototype.tostring.call(val)

object.prototype.tostring.call(val)或({}).tostring.call(val)均是獲取val的內建屬性[[class]]屬性值,並經過加工後返回。

內部邏輯:

function object.prototype.tostring()

注意:1. 由於內部硬編碼null返回"[object null]",因此雖然null本應不屬於object型別,但js中我們依然將其當作object來使用(歷史+避免破壞已有庫的相容性,導致後來無法修正該錯誤了);

2. 即使入參為primitive value,但內部還是會對其進行裝箱操作(通過toobject抽象操作)。

那現在我們就需要了解一下[[class]]內部屬性了。

內部屬性[[class]]

在構造物件時會根據物件的型別設定[[class]]的值,而其值型別為字串。對於native object而言,其值範圍是:arguments

array、boolean、date、error、function、json、math、number、object、regexp、string。對於host object而言,則用htmlelement、htmldocument等了。

注意:[[class]]是用於內部區分不同型別的物件。也就是僅支援js語言規範和宿主環境提供的物件型別而已,而自定義的物件型別是無法儲存在[[class]]中。

function foo(){}

var foo = new

foo()

console.log(({}).tostring.call(foo))

//顯示[object object]

於是我們需要求助於constructor.name屬性了。

obj.constructor.name

function foo(){}

var foo = new

foo()

console.log(foo.constructor.name)

//顯示foo

那如果採用匿名函式表示式的方式定義建構函式呢?只能說直接沒轍,要不在建構函式上新增個函式屬性來儲存(如foo.classname="foo"),要不自己構建乙個類工廠搞定。

implementaion of type function

綜上所述得到如下實現:

/*

* 獲取物件的資料型別

* @method type

* @param object - 獲取資料型別的物件

* @param [getclass] - 使用者自定義獲取資料型別的方法

* @returns 資料型別名稱 */

function type(o

/*bject

*/, g/*

etclass

*/))

var rtype = /\s*\[\s*object\s*([0-9a-z]+)\s*\]\s*/i

t =({}).tostring.call(o)

t = t.match(rtype)[1]

if ("

object

" !== t) return

t t =o.constructor.name

if (!t && arguments.callee(g) === "

function")

t = t || "

object

"return

t}

consolusion

thanks

JS魔法堂 doctype我們應該了解的基礎知識

一 前言 什麼是doctype?其實我們一直使用,卻很少停下來看清楚它到底是什麼,對網頁有什麼作用。本篇將和大家一起 那個默默無聞的doctype吧!二 什麼是doctype doctype或dtd就是宣告在文件首行,位於前,用於告知瀏覽器該文件遵循那種級別的html或xhtml規範。其宣告格式如下...

JS魔法堂 獲取當前指令碼檔案的絕對路徑

一 前言 當寫模組載入器時,獲取當前指令碼檔案的絕對路徑作為基礎路徑是必不可少的一步,下面我們一起來 一下這個問題吧!二 各大瀏覽器的實現方式 a chrome和ff 超簡單的一句足矣!var getcurrabspath function 這裡利用了物件 document.currentscrip...

JS魔法堂 獲取當前指令碼檔案的絕對路徑

一 前言 當寫模組載入器時,獲取當前指令碼檔案的絕對路徑作為基礎路徑是必不可少的一步,下面我們一起來 一下這個問題吧!二 各大瀏覽器的實現方式 a chrome和ff 超簡單的一句足矣!var getcurrabspath function 這裡利用了物件 document.currentscrip...