类型转换是指将数据由一种类型变换为另一种类型。在编译器自动赋值时,会发生隐式转换,但在代码中,也可以用一些写法强制要求进行显式转换。例如:在表达式 5 + 2.0 中,整数 5 被隐式转换为浮点数,但 Number("0x11") 和 "0x11" 则被显式转换为数字 17。
转Boolean
条件判断时,除了 undefined
, null
, false
, NaN
, ''
, 0
, -0
,其他所有值都转为 true
,包括所有对象。
转对象
对象在转换基本类型时,首先会调用 valueOf
然后调用 toString
。
-
valueOf
: 返回指定对象的原始值。 -
toString
: 返回一个表示该对象的字符串
// Number
var num = 15.26540;
num.valueOf() // 15.2654
num.toString() // "15.2654"
1 + num // 16.2654
"1" + num // 115.2654
// Array
var array = ["ABC", true, 12, -5];
array.valueOf() // (4) ["ABC", true, 12, -5]
array.toString() // "ABC,true,12,-5"
1 + array // "1ABC,true,12,-5"
array + array //"ABC,true,12,-5ABC,true,12,-5" 注意这里是字符串,而不是数组
// 布尔值
var bool = true;
bool.valueOf() // true
bool.toString() // "true"
1 + bool // 2
bool + bool // 2
"1" + bool // "1true"
// 若布尔值为 false ,转为 number 时的值为 0
var bool = false;
1 + bool // 1
bool + bool // 0
// Function
function foo(){}
foo.valueOf() // ƒ foo(){}
var foo2 = new Function("x", "y", "return x + y;");
foo2.valueOf()
/*
ƒ anonymous(x,y
) {
return x + y;
}
*/
// Object
var obj = {name: "张三", age: 18};
obj.valueOf() // {name: "张三", age: 18}
obj.toString() // "[object Object]"
1 + obj // "1[object Object]"
obj + obj // "[object Object][object Object]"
注意:字符串上下文中的对象通过 toString()
方法转换,这与使用valueOf
转换为原始字符串的String对象不同。所有对象都能转换成一个“[object 类型]”
这种格式的字符串。但是很多对象不能转换为数字,布尔或函数。
重写valueOf()
和toSting
let a = {
valueOf() {
return 0;
},
toString() {
return 'a';
},
}
1 + a // => 1
'1' + a // => '10'
也可以重写 Symbol.toPrimitive
,该方法在转基本类型时调用优先级最高
const obj = {
valueOf() {
return 0;
},
[Symbol.toPrimitive](hint) {
if (hint == 'number') {
return 42;
}else if(hint == 'string'){
return "hello";
}
return true;
}
};
console.log(+obj2); // 42 -- hint 参数值是 "number"
console.log(`${obj2}`); // "hello" -- hint 参数值是 "string"
console.log(obj2 + ""); // "true" -- hint 参数值是 "default"
四则运算符
- 加法运算时:一方是字符串类型,就会把另一个也转为字符串类型。并且加法运算会触发三种类型转换:将值转换为原始值,转换为数字,转换为字符串。
- 其他运算符:一方是数字,那么另一方就转为数字。
若为字符串会转换为数字,转换失败结果会为NaN
// 一方为数字
1 + '1' // '11'
2 * '2' // 4
4 / '2' // 2
// 都不为数字
'4' / '2' // 2
'2a' * '2' // NaN
['a', 'b'] + ['c', 'd'] // '"a,bc,d",此次为字符串拼接
// 特殊
'a' + + 'b' // -> "aNaN"
// 因为 + '1' -> 1
// + 'b' -> NaN
相等性判断
JavaScript提供三种不同的值比较操作:
- 严格相等 ,类型和值都相等,使用
===
- 宽松相等 ,值相等,使用
==
- Object.is (ES6 新特性, 确定两个值是否相同。)
一般而言,所有的对象都与 undefined
和 null
不相等。但是大部分浏览器允许非常窄的一类对象(即,所有页面中的 document.all 对象),在某些情况下,充当效仿 undefined 的角色。
判断x==y
,其中x
和y
都是值
-
若
x
和y
类型相等-
x
类型为Null
,返回true
-
x
类型为Undefined
,返回true
-
x
类型为Number
,则-
x
为NaN
,返回false
-
y
为NaN
,返回false
-
x
为+0
且y
为-0
,返回true
-
x
为-0
且y
为+0
,返回true
-
x
和y
数值相等,返回true
- 返回
false
-
-
x
类型为String
,若x
和y
为完全相同的字符序列,返回true
.否则,返回false
-
x
类型为Boolean
,同为true
或者false
时返回true
.否则,返回false
6.同为引用同一对象时返回true
.否则,返回false
-
若
x
为null
且y为undefined
, 返回true
。若
x
为undefined
且y为null
, 返回true
。若
Type(x)
为Number且Type(y)
为String
,返回comparison x
==ToNumber(y)
的结果。若
Type(x)
为String
且Type(y)
为Number
,.返回比较ToNumber(x)
==y
的结果。若
Type(x)
为Boolean
, 返回比较ToNumber(x)
== y的结果。若Type(y)为
Boolean
,返回比较x ==ToNumber(y)
的结果。若
Type(x)
为String
或Number
, 且Type(y)
为Object
, 返回比较x
==ToPrimitive(y)
的结果。若
Type(x)
为Object且Type(y)
为String
或Number
, 返回比较ToPrimitive(x)
==y
的结果。返回false
。
1 == '1' // true
null = undefined // true
null = document.all // true
undefined = document.all // true
现在来解析一道题目 [] == ![] // -> true
,下面是这个表达式为何为 true
的步骤
// [] 转成 true,然后取反变成 false
[] == false
// 根据第 8 条得出
[] == ToNumber(false)
[] == 0
// 根据第 10 条得出
ToPrimitive([]) == 0
// [].toString() -> ''
'' == 0
// 根据第 6 条得出
0 == 0 // -> true
总结:[] == ! [] -> [] == false -> [] == 0 -> '' == 0 -> 0 == 0 -> true