国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > JS > 正文

JavaScript中Object.prototype.toString方法的原理

2024-05-06 16:29:08
字體:
供稿:網(wǎng)友
這篇文章主要介紹了JavaScript中Object.prototype.toString方法的原理的相關(guān)資料,需要的朋友可以參考下
 

在JavaScript中,想要判斷某個對象值屬于哪種內(nèi)置類型,最靠譜的做法就是通過Object.prototype.toString方法.

var arr = [];console.log(Object.prototype.toString.call(arr)) //"[object Array]"

本文要講的就是,toString方法是如何做到這一點的,原理是什么.

ECMAScript 3

在ES3中,Object.prototype.toString方法的規(guī)范如下:

15.2.4.2 Object.prototype.toString()

在toString方法被調(diào)用時,會執(zhí)行下面的操作步驟:

1. 獲取this對象的[[Class]]屬性的值.

2. 計算出三個字符串"[object ", 第一步的操作結(jié)果Result(1), 以及 "]"連接后的新字符串.

3. 返回第二步的操作結(jié)果Result(2).

[[Class]]是一個內(nèi)部屬性,所有的對象(原生對象和宿主對象)都擁有該屬性.在規(guī)范中,[[Class]]是這么定義的

 

內(nèi)部屬性 描述
[[Class]] 一個字符串值,表明了該對象的類型.

 

然后給了一段解釋:

所有內(nèi)置對象的[[Class]]屬性的值是由本規(guī)范定義的.所有宿主對象的[[Class]]屬性的值可以是任意值,甚至可以是內(nèi)置對象使用過的[[Class]]屬性的值.[[Class]]屬性的值可以用來判斷一個原生對象屬于哪種內(nèi)置類型.需要注意的是,除了通過Object.prototype.toString方法之外,本規(guī)范沒有提供任何其他方式來讓程序訪問該屬性的值(查看 15.2.4.2).

也就是說,把Object.prototype.toString方法返回的字符串,去掉前面固定的"[object "和后面固定的"]",就是內(nèi)部屬性[[class]]的值,也就達到了判斷對象類型的目的.jQuery中的工具方法$.type(),就是干這個的.

在ES3中,規(guī)范文檔并沒有總結(jié)出[[class]]內(nèi)部屬性一共有幾種,不過我們可以自己統(tǒng)計一下,原生對象的[[class]]內(nèi)部屬性的值一共有10種.分別是:"Array", "Boolean", "Date", "Error", "Function", "Math", "Number", "Object", "RegExp", "String".

ECMAScript 5

在ES5.1中,除了規(guī)范寫的更詳細一些以外,Object.prototype.toString方法和[[class]]內(nèi)部屬性的定義上也有一些變化,Object.prototype.toString方法的規(guī)范如下:

15.2.4.2 Object.prototype.toString ( )

在toString方法被調(diào)用時,會執(zhí)行下面的操作步驟:

如果this的值為undefined,則返回"[object Undefined]".

如果this的值為null,則返回"[object Null]".

讓O成為調(diào)用ToObject(this)的結(jié)果.

讓class成為O的內(nèi)部屬性[[Class]]的值.

返回三個字符串"[object ", class, 以及 "]"連接后的新字符串.

可以看出,比ES3多了1,2,3步.第1,2步屬于新規(guī)則,比較特殊,因為"Undefined"和"Null"并不屬于[[class]]屬性的值,需要注意的是,這里和嚴格模式無關(guān)(大部分函數(shù)在嚴格模式下,this的值才會保持undefined或null,非嚴格模式下會自動成為全局對象).第3步并不算是新規(guī)則,因為在ES3的引擎中,也都會在這一步將三種原始值類型轉(zhuǎn)換成對應的包裝對象,只是規(guī)范中沒寫出來.ES5中,[[Class]]屬性的解釋更加詳細:

所有內(nèi)置對象的[[Class]]屬性的值是由本規(guī)范定義的.所有宿主對象的[[Class]]屬性的值可以是除了"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", "String"之外的的任何字符串.[[Class]]內(nèi)部屬性是引擎內(nèi)部用來判斷一個對象屬于哪種類型的值的.需要注意的是,除了通過Object.prototype.toString方法之外,本規(guī)范沒有提供任何其他方式來讓程序訪問該屬性的值(查看 15.2.4.2).

和ES3對比一下,第一個差別就是[[class]]內(nèi)部屬性的值多了兩種,成了12種,一種是arguments對象的[[class]]成了"Arguments",而不是以前的"Object",還有就是多個了全局對象JSON,它的[[class]]值為"JSON".第二個差別就是,宿主對象的[[class]]內(nèi)部屬性的值,不能和這12種值沖突,不過在支持ES3的瀏覽器中,貌似也沒有發(fā)現(xiàn)哪些宿主對象故意使用那10個值.

ECMAScript 6

ES6目前還只是工作草案,但能夠肯定的是,[[class]]內(nèi)部屬性沒有了,取而代之的是另外一個內(nèi)部屬性[[NativeBrand]].[[NativeBrand]]屬性是這么定義的:

 

內(nèi)部屬性 屬性值 描述
[[NativeBrand]] 枚舉NativeBrand的一個成員. 該屬性的值對應一個標志值(tag value),可以用來區(qū)分原生對象的類型.

 

[[NativeBrand]]屬性的解釋:

[[NativeBrand]]內(nèi)部屬性用來識別某個原生對象是否為符合本規(guī)范的某一種特定類型的對象.[[NativeBrand]]內(nèi)部屬性的值為下面這些枚舉類型的值中的一個:NativeFunction, NativeArray, StringWrapper, BooleanWrapper, NumberWrapper, NativeMath, NativeDate, NativeRegExp, NativeError, NativeJSON, NativeArguments, NativePrivateName.[[NativeBrand]]內(nèi)部屬性僅用來區(qū)分區(qū)分特定類型的ECMAScript原生對象.只有在表10中明確指出的對象類型才有[[NativeBrand]]內(nèi)部屬性.

表10 — [[NativeBrand]]內(nèi)部屬性的值

 

屬性值 對應類型
NativeFunction Function objects
NativeArray Array objects
StringWrapper String objects
BooleanWrapper Boolean objects
NumberWrapper Number objects
NativeMath The Math object
NativeDate Date objects
NativeRegExp RegExp objects
NativeError Error objects
NativeJSON The JSON object
NativeArguments Arguments objects
NativePrivateName Private Name objects

 

可見,和[[class]]不同的是,并不是每個對象都擁有[[NativeBrand]].同時,Object.prototype.toString方法的規(guī)范也改成了下面這樣:

15.2.4.2 Object.prototype.toString ( )

在toString方法被調(diào)用時,會執(zhí)行下面的操作步驟:

如果this的值為undefined,則返回"[object Undefined]".

如果this的值為null,則返回"[object Null]".

讓O成為調(diào)用ToObject(this)的結(jié)果.

如果O有[[NativeBrand]]內(nèi)部屬性,讓tag成為表29中對應的值.

否則

讓hasTag成為調(diào)用O的[[HasProperty]]內(nèi)部方法后的結(jié)果,參數(shù)為@@toStringTag.

如果hasTag為false,則讓tag為"Object".

否則,

讓tag成為調(diào)用O的[[Get]]內(nèi)部方法后的結(jié)果,參數(shù)為@@toStringTag.

如果tag是一個abrupt completion,則讓tag成為NormalCompletion("???").

讓tag成為tag.[[value]].

如果Type(tag)不是字符串,則讓tag成為"???".

如果tag的值為"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp",或

者"String"中的任一個,則讓tag成為字符串"~"和tag當前的值連接后的結(jié)果.

返回三個字符串"[object ", tag, and "]"連接后的新字符串.

表29 — [[NativeBrand]] 標志值

 

[[NativeBrand]]值 標志值
NativeFunction "Function"
NativeArray "Array"
StringWrapper "String"
BooleanWrapper "Boolean"
NumberWrapper "Number"
NativeMath "Math"
NativeDate "Date"
NativeRegExp "RegExp"
NativeError "Error"
NativeJSON "JSON"
NativeArguments "Arguments"

 

可以看到,在規(guī)范上有了很大的變化,不過對于普通用戶來說,貌似感覺不到.

也許你發(fā)現(xiàn)了,ES6里的新類型Map,Set等,都沒有在表29中.它們在執(zhí)行toString方法的時候返回的是什么?

console.log(Object.prototype.toString.call(Map())) //"[object Map]"console.log(Object.prototype.toString.call(Set())) //"[object Set]"

其中的字符串"Map"是怎么來的呢:

15.14.5.13 Map.prototype.@@toStringTag

@@toStringTag 屬性的初始值為字符串"Map".

由于ES6的規(guī)范還在制定中,各種相關(guān)規(guī)定都有可能改變,所以如果想了解更多細節(jié).看看下面這兩個鏈接,現(xiàn)在只需要知道的是:[[class]]沒了,使用了更復雜的機制.

以上所述是小編給大家分享的JavaScript中Object.prototype.toString方法的原理,希望對大家有所幫助!



注:相關(guān)教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 镇安县| 安图县| 屯留县| 宁明县| 石棉县| 伽师县| 海伦市| 成安县| 青海省| 施秉县| 邵武市| 遂平县| 邛崃市| 丘北县| 洞口县| 沭阳县| 新宾| 甘洛县| 上高县| 左云县| 惠水县| 富宁县| 泊头市| 丹寨县| 印江| 西宁市| 福贡县| 红原县| 桂林市| 洛川县| 绍兴市| 虹口区| 南京市| 麦盖提县| 张掖市| 乡城县| 浠水县| 永胜县| 盐源县| 积石山| 额尔古纳市|