为什么Object.protype.toString.call(foo)可以检测到foo's类型
Why can Object.prototype.toString.call(foo) detect foo's type?
我知道我们可以在Javascript中检测变量的类型,如下所示:
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call({}); // [object Object]
Object.prototype.toString.call(''); // [object String]
Object.prototype.toString.call(new Date()); // [object Date]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(function () {}); // [object Function]
Object.prototype.toString.call(/test/i); // [object RegExp]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(); // [object Undefined]
但为什么呢?
这些值([object Array]、[object String]…)是如何返回的,Object.prototype.toString
做什么?
Object.prototype.toString
基本上返回对象的[[Class]]
(实现细节)内部属性。引用ECMA Script 5.1规范中的一节,其中定义了
- 如果
this
的值为undefined
,则返回"[object Undefined]"
- 如果
this
的值为null
,则返回"[object Null]"
- 设O是调用
ToObject
并将this
值作为参数的结果- 设class为O的
[[Class]]
内部属性的值- 返回字符串值,该值是连接三个字符串
"[object "
、class
和"]"
的结果
此外,
[[Class]]
内部属性的值由本规范为每种内置对象定义。主机对象的[[Class]]
内部属性的值可以是除了"Arguments"
、"Array"
、"Boolean"
、"Date"
、"Error"
、"Function"
、"JSON"
、"Math"
、"Number"
、"Object"
、"RegExp"
和"String"
中的一个之外的任何字符串值。[[Class]]
内部属性的值在内部用于区分不同类型的对象请注意,此规范没有为程序提供任何访问该值的方法,除非通过Object.prototype.toString
因此,Object.prototype.toString
是唯一可以访问[[Class]]
属性的函数。
如果你碰巧使用ECMA 6(就像在NodeJS或更新的浏览器技术上一样),你可以使用以下函数来获取"类名"。
// primitives
var array = [], obj = {}, str = "", date = new Date(),
num = 1, flt = 1.0, reg = new RegExp(/woohoo/g),
bool = true, myType = new MyType(), udf = undefined, nul = null;
// names of various types (primitive and not)
var names = cName(array) + ", " + cName(obj) + ", " + cName(str) + ", " +
cName(num) + ", " + cName(flt) + ", " + cName(reg) + ", " +
cName(bool) + ", " + cName(date) + ", " + cName(myType) + ", " +
cName(MyType) + ", " + cName(udf) + ", " + cName(nul);
// custom type
function MyType(){}
console.log( names );
// output:
// Array, Object, String, Number, Number, RegExp, Boolean, Date, MyType, MyType, undefined, null
// implementation
function cName(obj){
// default to non-null value.
var ret = '';
if(typeof obj === 'undefined') { ret = 'undefined'; }
else if(obj === null) { ret = String(obj); }
else if(typeof obj.constructor !== 'undefined' && obj.constructor !== null){
ret = obj.constructor.name
if(ret == 'Function') { ret = obj.name; }
}
return ret;
}
虽然确实没有"类",但当传递类似Array, vs Object, vs. Null
的东西时,如果你想知道它是哪一个,这会有所帮助。
在其中任何一个上调用CCD_ 35将返回CCD_。然后是必须处理null
和undefined
之类的事情的警告。
调用Object.prototype.toString()
比访问constructor.name
更重,因为没有从某种类型到字符串的转换,我相信constructor
和constructor.name
都是成员变量,而不是getter
,这意味着在检索所述名称时没有调用其他函数。
- 如何检测是否有溢出
- 如何检测用于WebGL的专用或集成显卡
- 防止Alt+Shift默认操作或检测多种操作系统语言的Javascript
- 如何在使用selectBoxIt JQuery插件时检测选项更改
- 如何使用密码检测网络中的状态连接
- 使用JavaScript检测Flash
- 在不阻止默认行为的情况下检测IE10中的缩放
- 检测个位数整数时正在转换毫秒
- 检测电话窃听,即:<a href="电话:xxx">在UIWebview上
- 动态插入的表:JQuery未检测到最后一行
- 检测页面上某个元素中选择(突出显示)或单击的内容
- jQuery检测浏览器是否支持Zoom
- 检测iframe是否跨域的愚蠢方法
- 检测图像分辨率
- 如何检测第三方广告服务器请求
- 我是否可以检测到javascript正在被卸载(作为调试模式)
- 当没有文本输入聚焦时检测空格键按下
- 正在检测导航到<a name=“;最新主题”></a>
- 如何检测重叠元素下的单击
- 为什么Object.protype.toString.call(foo)可以检测到foo's类型