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"native object,就是math、、、new object()和regexp等js規範中定義的物件,其中math、regexp等程式執行時立即被初始化的物件被稱為built-in object。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"外的資料型別字串。
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...