谈谈 Object.prototype.toString 。

原文链接
我的blog

前几日看到一个比较熟习的面试题,推断一个变量是否是数组?
以下几种要领供参考:

var arr = [1, 2, 3]
Array.isArray(arr)
arr instanceof Array
arr.constructor === Array
Object.prototype.toString.call(arr) === '[object Array]'
...

这篇文章主假如谈谈 Object.prototype.toString

ECMAScript 5

在ECMAScript 5中,Object.prototype.toString()被挪用时,会举行以下步骤:

  • 假如 thisundefined ,返回 [object Undefined]
  • 假如 thisnull , 返回 [object Null]
  • O 为以 this 作为参数挪用 ToObject 的效果;
  • classO 的内部属性 [[Class]] 的值;
  • 返回三个字符串 "[object", class, 以及"]" 拼接而成的字符串。

[[Class]]

[[Class]]是一个内部属性,值为一个范例字符串,能够用来推断值的范例。

有这么一段细致的诠释:

本范例的每种内置对象都定义了 [[Class]] 内部属性的值。宿主对象的 [[Class]] 内部属性的值能够是除了 “Arguments”, “Array”, “Boolean”, “Date”, “Error”, “Function”, “JSON”, “Math”, “Number”, “Object”, “RegExp”, “String” 的任何字符串。[[Class]] 内部属性的值用于内部辨别对象的品种。注,本范例中除了经由过程 Object.prototype.toString ( 见 15.2.4.2) 没有供应任何手腕使顺序接见此值。

在JavaScript代码里,唯一能够接见该属性的要领就是经由过程 Object.prototype.toString ,一般要领以下:

Object.prototype.toString.call(value)

举例:

> Object.prototype.toString.call(null)
'[object Null]'

> Object.prototype.toString.call(undefined)
'[object Undefined]'

> Object.prototype.toString.call(Math)
'[object Math]'

> Object.prototype.toString.call({})
'[object Object]'

> Object.prototype.toString.call([])
'[object Array]'

因而,能够用以下函数,来猎取恣意变量的[[Class]]属性:

function getClass (a) {
  const str = Object.prototype.toString.call(a)
  return /^\[object (.*)\]$/.exec(str)[1]
}

运转即可得

> getClass(null)
'Null'

> getClass(undefined)
'Undefined'

> getClass(Math)
'Math'

> getClass({})
'Object'

> getClass([])
'Array'

ECMAScript 6

在ES6,挪用 Object.prototype.toString 时,会举行以下步骤:

  • 假如 thisundefined ,返回 '[object Undefined]' ;
  • 假如 thisnull , 返回 '[object Null]'
  • O 为以 this 作为参数挪用 ToObject 的效果;
  • isArrayIsArray(O)
  • ReturnIfAbrupt(isArray) (假如 isArray 不是一个正常值,比方抛出一个毛病,中缀实行);
  • 假如 isArraytrue , 令 builtinTag'Array' ;
  • else ,假如 O is an exotic String object , 令 builtinTag'String'
  • else ,假如 O 含有 [[ParameterMap]] internal slot, , 令 builtinTag'Arguments'
  • else ,假如 O 含有 [[Call]] internal method , 令 builtinTagFunction
  • else ,假如 O 含有 [[ErrorData]] internal slot , 令 builtinTagError
  • else ,假如 O 含有 [[BooleanData]] internal slot , 令 builtinTagBoolean
  • else ,假如 O 含有 [[NumberData]] internal slot , 令 builtinTagNumber
  • else ,假如 O 含有 [[DateValue]] internal slot , 令 builtinTagDate
  • else ,假如 O 含有 [[RegExpMatcher]] internal slot , 令 builtinTagRegExp
  • else , 令 builtinTagObject
  • tagGet(O, @@toStringTag) 的返回值( Get(O, @@toStringTag) 要领,既是在 O 是一个对象,而且具有 @@toStringTag 属性时,返回 O[Symbol.toStringTag] );
  • ReturnIfAbrupt(tag) ,假如 tag 是正常值,继续实行下一步;
  • 假如 Type(tag) 不是一个字符串,let tag be builtinTag
  • 返回由三个字符串 "[object", tag, and "]" 拼接而成的一个字符串。

在ES6里,之前的 [[Class]] 不再运用,取而代之的是一系列的 internal slot ,有一个比较完全的诠释:

Internal slots correspond to internal state that is associated with objects and used by various ECMAScript specification algorithms. Internal slots are not object properties and they are not inherited. Depending upon the specific internal slot specification, such state may consist of values of any ECMAScript language type or of specific ECMAScript specification type values

也许的意义是:Internal slots 对应于与对象相关联并由种种ECMAScript范例算法运用的内部状况,它们没有对象属性,也不能被继续,依据详细的 Internal slot 范例,这类状况能够由任何ECMAScript言语范例或特定ECMAScript范例范例值的值构成。

另外,经由过程对 Object.prototype.toString 在ES6的完成步骤剖析,我们实在能够很轻易转变 Object.prototype.toString.call 的效果,像下面一样:

let obj = {}

Object.defineProperty(obj, Symbol.toStringTag, {
    get: function() {
        return "newClass"
    }
})

console.log(Object.prototype.toString.call(obj)) // "[object newClass]"

ECMAScript 7

ES7现在照样事情草案,到现在为止,就 Object.prototype.toString 的完成步骤来讲, 只是移除了ES6个中的 ReturnIfAbrupt

参考

  1. http://www.ecma-international…
  2. http://www.adobe.com/devnet/a…
  3. https://developer.mozilla.org…
  4. http://www.ecma-international…
  5. http://es6.ruanyifeng.com/#do…
  6. https://tc39.github.io/ecma26…

完。

    原文作者:三毛
    原文地址: https://segmentfault.com/a/1190000009407558
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞