原文链接
我的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()
被挪用时,会举行以下步骤:
- 假如
this
是undefined
,返回[object Undefined]
; - 假如
this
是null
, 返回[object Null]
; - 令
O
为以this
作为参数挪用ToObject
的效果; - 令
class
为O
的内部属性[[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
时,会举行以下步骤:
- 假如
this
是undefined
,返回'[object Undefined]'
; - 假如
this
是null
, 返回'[object Null]'
; - 令
O
为以this
作为参数挪用ToObject
的效果; - 令
isArray
为IsArray(O)
; -
ReturnIfAbrupt(isArray)
(假如isArray
不是一个正常值,比方抛出一个毛病,中缀实行); - 假如
isArray
为true
, 令builtinTag
为'Array'
; -
else
,假如O is an exotic String object
, 令builtinTag
为'String'
; -
else
,假如O
含有[[ParameterMap]] internal slot,
, 令builtinTag
为'Arguments'
; -
else
,假如O
含有[[Call]] internal method
, 令builtinTag
为Function
; -
else
,假如O
含有[[ErrorData]] internal slot
, 令builtinTag
为Error
; -
else
,假如O
含有[[BooleanData]] internal slot
, 令builtinTag
为Boolean
; -
else
,假如O
含有[[NumberData]] internal slot
, 令builtinTag
为Number
; -
else
,假如O
含有[[DateValue]] internal slot
, 令builtinTag
为Date
; -
else
,假如O
含有[[RegExpMatcher]] internal slot
, 令builtinTag
为RegExp
; -
else
, 令builtinTag
为Object
; - 令
tag
为Get(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
。
参考
- http://www.ecma-international…
- http://www.adobe.com/devnet/a…
- https://developer.mozilla.org…
- http://www.ecma-international…
- http://es6.ruanyifeng.com/#do…
- https://tc39.github.io/ecma26…
完。