日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

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

發(fā)布時(shí)間:2025/1/21 javascript 77 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript:Object.prototype.toString方法的原理 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

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

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

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

ECMAScript 3

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

15.2.4.2 Object.prototype.toString()

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

1. 獲取this對(duì)象的[[Class]]屬性的值.

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

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

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

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

然后給了一段解釋:

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

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

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

ECMAScript 5

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

15.2.4.2 Object.prototype.toString ( )

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

  • 如果this的值為undefined,則返回"[object Undefined]".
  • 如果this的值為null,則返回"[object Null]".
  • 讓O成為調(diào)用ToObject(this)的結(jié)果.
  • 讓class成為O的內(nèi)部屬性[[Class]]的值.
  • 返回三個(gè)字符串"[object ", class, 以及 "]"連接后的新字符串.
  • 可以看出,比ES3多了1,2,3步.第1,2步屬于新規(guī)則,比較特殊,因?yàn)?#34;Undefined"和"Null"并不屬于[[class]]屬性的值,需要注意的是,這里和嚴(yán)格模式無關(guān)(大部分函數(shù)在嚴(yán)格模式下,this的值才會(huì)保持undefined或null,非嚴(yán)格模式下會(huì)自動(dòng)成為全局對(duì)象).第3步并不算是新規(guī)則,因?yàn)樵贓S3的引擎中,也都會(huì)在這一步將三種原始值類型轉(zhuǎn)換成對(duì)應(yīng)的包裝對(duì)象,只是規(guī)范中沒寫出來.ES5中,[[Class]]屬性的解釋更加詳細(xì):

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

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

    ECMAScript 6

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

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

    ?[[NativeBrand]]屬性的解釋:

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

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

    屬性值對(duì)應(yīng)類型
    NativeFunctionFunction objects
    NativeArrayArray objects
    StringWrapperString objects
    BooleanWrapperBoolean objects
    NumberWrapperNumber objects
    NativeMathThe Math object
    NativeDateDate objects
    NativeRegExpRegExp objects
    NativeErrorError objects
    NativeJSONThe JSON object
    NativeArgumentsArguments objects
    NativePrivateNamePrivate Name objects

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

    15.2.4.2 Object.prototype.toString ( )

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

  • 如果this的值為undefined,則返回"[object Undefined]".
  • 如果this的值為null,則返回"[object Null]".
  • 讓O成為調(diào)用ToObject(this)的結(jié)果.
  • 如果O有[[NativeBrand]]內(nèi)部屬性,讓tag成為表29中對(duì)應(yīng)的值.
  • 否則
  • 讓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是一個(gè)abrupt completion,則讓tag成為NormalCompletion("???").
  • 讓tag成為tag.[[value]].
  • 如果Type(tag)不是字符串,則讓tag成為"???".
  • 如果tag的值為"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp",或者"String"中的任一個(gè),則讓tag成為字符串"~"和tag當(dāng)前的值連接后的結(jié)果.
  • 返回三個(gè)字符串"[object ", tag, and "]"連接后的新字符串.
  • 表29 — [[NativeBrand]] 標(biāo)志值

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

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

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

    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ī)定都有可能改變,所以如果想了解更多細(xì)節(jié).看看下面這兩個(gè)鏈接,現(xiàn)在只需要知道的是:[[class]]沒了,使用了更復(fù)雜的機(jī)制.

    http://stackoverflow.com/questions/13151643/access-nativebrand-class-in-es6-ecmascript-6

    https://mail.mozilla.org/pipermail/es-discuss/2012-June/023676.html

    總結(jié)

    以上是生活随笔為你收集整理的JavaScript:Object.prototype.toString方法的原理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。