从valueOf()和toString()谈JavaScript隐式类型转换
首先需要知道一点,valueOf和toString函数通常不会显式调用,一般调用时机都是当语句执行时,如果数据类型不符合期待,解释器自动执行帮助我们完成类型转换(通常作用于object对象)。接下来首先根据不同情况分析隐式类型转换规则。
先看一段stackoverflow上的代码示例。
var x = {
toString: function () { return "foo"; },
valueOf: function () { return 42; }
};
alert(x); // foo
"x=" + x; // "x=42"
x + "=x"; // "42=x"
x + "1"; // 421
x + 1; // 43
["x=", x].join(""); // "x=foo"
我们重写了对象的toString和valueOf方法,可以看出执行不同语句时,分别隐式调用了这两个方法,那么分别适用于什么情况呢?不妨对这些代码做一个分类来讨论。
1.操作符
当操作符作用于数值计算时
- 基本数据类型会隐式调用Number()转换为数值进行计算
- 对象会先调用valueOf()取得操作数,如果运算结果为NaN则再调用toString()
大多数操作符为这种类型。而加性操作符中存在一个特例情况,当两个操作数执行加法计算时,如果存在一个操作数为字符串,则对所有操作数执行toString()函数进行转换然后进行拼接操作。伪代码解释如下:
a + b:
pa = ToPrimitive(a)
pb = ToPrimitive(b)
if(pa is string || pb is string)
return concat(ToString(pa), ToString(pb))
else
return add(ToNumber(pa), ToNumber(pb))
toPrimitive是通过valueOf将数据转化为基本数据类型,若得到基本数据类型则结束,否则调用toString的假想函数。
2.语句
- 当需要利用布尔值进行判断时,会自动调用Boolean()转换表达式结果
- 当alert输出时,优先调用toString()
- 当以[x]形式进行属性访问时,优先调用toString()
综合以上,根据我的理解总结出: 隐式数据转换即为解释器自发根据需要调用Number(),Boolean()等基本类型转换函数使结果符合期待。若参数为object类型时,调用ToPrimitive()(假想函数),该函数根据需要的数据类型做出的反应也不同,若在使用操作符运算时需要number类型则优先调用valueOf(),结果为NaN再调用toString()。其他大部分情况需要string类型则优先调用toString()。这两种方法都可以重写,附原生方法参考。
valueOf()原生实现
数据类型 | 返回值 |
---|---|
Array | 与 Array.toString 和 Array.join 方法相同 |
Function | 函数本身 |
Date | 毫秒数UTC |
Boolean | 布尔值 |
Number | 数字值 |
String | 字符串值 |
Object | 对象本身 |
toString()原生实现
数据类型 | 返回值 |
---|---|
Array | 与 Array.valueOf 和 Array.join 方法相同 |
Function | 获取函数源代码 |
Object | 返回[object type] |
Boolean | 布尔值 |
Date | 格式化日期 |
String | 字符串值 |
Number | 数字值,可以携带进制参数 |
-- EOF --
添加在分类「
前端开发
」下,并被添加
「JavaScript」
标签。