自动类型转换
自动类型转换主要针对的是对象类型,有俩种情况会出现:
-
等性运算(
==
,即比较,如:false == []) -
四则运算(
+-*/
,如:[] + 1)
在这两种运算中,js解释器需要将对象类型转换成原始类型(除了null
与undefined
),才能进行后续的操作。
在说明自动类型转换前,首先要了解两个方法:
-
Object.prototype.toString
-
Object.prototype.valueOf
这两个方法定义在Object.prototype
上,是转换的核心
对象=>数字
在用对象做四则运算时,JS解释器会尝试将其转换成数字
比如下面这种操作:
let obj = {};
obj + 1;
解释器会进行如下操作
let obj = {};
let temp = 0;
if(typeof obj.valueOf() != 'object'){
temp = obj.valueOf();
}else if(typeof obj.toString() != 'object'){
temp = obj.toString();
}else{
throw new Error("Uncaught TypeError: Cannot convert object to primitive value...")
}
temp + 1; // "[object object]1"
用语言描述其过程:
-
调用valueOf(),返回值若不是原始类型,执行2
-
调用toString(),返回值若不是原始类型,执行3
-
抛出错误:
Uncaught TypeError: Cannot convert object to primitive value(…)
下面来几个实例测试下:
仅调用 valueOf
let obj = {};
obj + 1; // "[object Object]1"
obj.valueOf = () => {
return 0;
}
obj.toString = () => {
return -1;
}
obj + 1; // 1
调用valueOf
与toString
let obj = {};
obj.valueOf = () => {
return {};
}
obj.toString = () => {
return -1;
}
obj + 1; // 0
var obj = {};
对象=>字符串
直接输出一个对象时,JS解释器会尝试将其转为字符串
比如下面的代码:
let obj = {};
alert(obj);
解释器会进行如下操作:
let obj = {};
let temp = "";
if(typeof obj.toString() != 'object'){
temp = obj.toString();
}
else if(typeof obj.valueOf() != 'object'){
temp = obj.valueOf();
}
else{
throw new Error("Uncaught TypeError: Cannot convert object to primitive value(…)")
}
console.log(temp);
上面的步骤用语言描述就是:
-
调用toString(),返回值若不是原始类型,执行2
-
调用valueOf(),返回值若不是原始类型,执行3
-
抛出错误:” Uncaught TypeError: Cannot convert object to primitive value(…)”
恰恰与转换成数字的调用顺序相反
同样用实例测试下:
仅调用toString
let obj = {};
obj.toString = () => {
return "hi";
}
obj.valueOf = () => {
return "hello"
}
alert(obj); // "hi"
调用toString
与valueOf
// 调用 toString() 与 valueOf()
let obj = {};
obj.toString = () => {
return {};
}
obj.valueOf = () => {
return "hello"
}
alert(obj); // "hello"
等性运算 ==
在进行==
比较时,不同类型的比较一般会都会转换成数字来进行
比如:[] == false
=> 0 == 0
=> true
其中又有些特殊情况
比如:
-
NaN == NaN
=>false
-
null == undefined
=>true
参考博文