JavaScript 对象转换之 toString、valueOf
开始这个话题之前,我们先看一下下面的几个例子:
parseInt(0.0000004) // 4
![]==[] //true
['x','y'] == 'x,y' //true
alert({name:'mofei'}) //"[object Object]"
结果有时候会让我大吃一惊,这是为什么呢?今天就和大家讨论一下 JavaScript 的对象转换。
基础类型
先让我们了解一下 JavasScript 转换的 原始类型(primitive value):
- Number
- String
- Boolean
在 JavaScript 进行对比或者各种运算的时候会把对象转换成这些类型,从而进行后续的操作,下面逐一说明:
String 转换
在某个操作或者运算需要字符串的时候,往往会触发Object的String转换,举个例子
var obj={name:'Mofei'}
var str = ' ' + obj
console.log(str); // [object Object]
上述的例子中,在字符串相加的过程中,系统调用了 obj
的 String 转换,具体规则如下:
- 如果
toString
方法存在并且返回 原始类型,返回 toString 的结果。 - 如果toString方法不存在或者返回的不是“原始类型”,调用
valueOf
方法,如果valueOf方法存在,并且返回“原始类型”数据,返回valueOf的结果。 - 其他情况,抛出错误。
我们可以用下面的方法简单的证明上面的规则:
首先我们尝试改写一个对象的 toString 方法
var a={
toString:function(){
console.log('调用了 a.toString');
return '111';
}
}
alert(a);
//调用了 a.toString
// 111
可以看到,系统在执行 ' '+a
的时候,自动调用了a的toString方法,将a(Object)转换成了String。
下面我们尝试证明如果toString()方法不可用的时候系统会调用valueOf()方法
var a={
toString:function(){
console.log('调用了 a.toString');
return '111';
},
valueOf:function(){
console.log('调用了 a.valueOf');
return '111';
}
}
alert(a);
//调用了 a.toString
这里我们增加了valueOf方法,但是发现系统并没有调用,这是因为,第一步toString返回的是原始类型,我们尝试把第一步返回的值改成一个对象 {}
var a={
toString:function(){
console.log('调用了 a.toString');
return {};
},
valueOf:function(){
console.log('调用了 a.valueOf');
return '111';
}
}
alert(a);
// 调用了 a.toString
// 调用了 a.valueOf
从结果可以看到,当 toString 不可用的时候,系统会再尝试 valueOf 方法,我们继续修改 valueOf 方法,把 valueOf 方法也改成返回对象 {}
var a={
toString:function(){
console.log('调用了 a.toString');
return {};
},
valueOf:function(){
console.log('调用了 a.valueOf');
return {};
}
}
alert(a);
// 调用了 a.toString
// 调用了 a.valueOf
// Uncaught TypeError: Cannot convert object to primitive value
可以发现,如果 toString 和 valueOf 方法均不可用的情况下,系统会直接返回一个错误。
Number 转换
下面说说 Number 转换,同理,当需要使用 Number 时,( 如 Math.sin() )等,解释器会尝试将对象转换成 Number 对象。
通常有如下的情况会触发 Number 转换
- 方法参数需要Number的时候,如 Math.sin(obj) 等
- 对比的时候,如 obj == 'abc'
- 运算的时候,如 obj + 123
转换规则如下:
- 如果 valueOf 存在,且返回“原始类型”数据,返回 valueOf 的结果。
- 如果 toString 存在,且返回“原始类型”数据,返回 toString 的结果。
- 报错。
可以参考 String 转换的方法进行验证,这里只列出一种典型的方法,其他的可以自己动手来修改
var a={
toString:function(){
console.log('调用了 a.toString');
return 12;
},
valueOf:function(){
console.log('调用了 a.valueOf');
return {};
}
}
a+1
//调用了 a.valueOf
//调用了 a.toString
//13
可以看到,这里我们改写了 valueOf 和 toString 方法,系统在调用 valueOf 方法之后发现返回的不是 原始类型 数据,于是又尝试调用了 toString 方法,并返回了该方法返回的值 12,最后 +1 变成了 13。
Boolean 转换
在进行布尔比较的时候,比如 if(obj) , while(obj) 等等,会进行布尔转换,布尔转换遵循如下规则:
值 | 布尔值 |
---|---|
true/false | true/false |
undefined、null | false |
Number | 0、NaN 对应 false,其他的对应 true |
String | "" 对应 false,其他对应 true('0' 对应的是 true) |
Object | true |
举个比较典型的例子
[] == ![] //true
// 首先第一步右边的是逻辑判断![],说以先转成boolean
// [] == !true
// [] == false
// 左边不是原始类型,尝试把左边转成原始类型,变成
// '' == false
// 转成Number
// 0 == 0
总结
通过上述的介绍,一开始提到的问题应该都很容易得到答案了。
parseInt(0.0000004) // 4
![]==[] //true
['x','y'] == 'x,y' //true
alert({name:'mofei'}) //"[object Object]"
关于这些转换,有时确实很让人费解,不过在了解原理之后,就会变得很容易了。有什么问题,可以给我留言,我会第一时间回复。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论