记癌丝很灵活,类型转换立大功。
类型转换就是从一种类型转换为另一种类型。这里不想说关于是显式还是隐式的,这全都是相对而言的,你懂对你来说就全是显式。
== 和 === 的区别
==
允许在相等比较中进行强制类型转换
===
不允许
关于==
的各种类型转换我拒绝回答。
ToPrimitive
是什么
Symbol.toPrimitive
是内置的 symbol 属性,其指定了一种接受首选类型并返回对象原始值的表示的方法。它被所有的强类型转换制算法优先调用。
js
const isBasicType = (val = "") => {
const t = Object.prototype.toString.call(val);
if (
t == "[object String]" ||
t == "[object Boolean]" ||
t == "[object Number]" ||
t == "[object Null]" ||
t == "[object Undefined]" ||
t == "[object Symbol]"
) {
return val;
}
return;
};
const user = {
[Symbol.toPrimitive](hint) {
console.log(hint);
// 假设这个Symbol.toPrimitive不存在就按照下面的样子转换
if (hint === "number" || hint === "default") {
return isBasicType(this.valueOf()) || this.toString();
}
if (hint === "string") {
return isBasicType(this.toString()) || this.valueOf();
}
},
toString() {
// console.log('toString');
return "toString";
},
valueOf() {
return 999;
// console.log('valueOf');
return "valueOf";
},
};
console.log("// toPrimitive(number) valueOf -> toString");
console.log("Number(user):", Number(user));
console.log("user - 1:", user - 1);
console.log("user > 1:", user > 1);
console.log("user > 'a':", user > "a");
console.log("user * 2:", user * 2);
console.log("// toPrimitive(default) valueOf -> toString");
console.log("user +1:", user + 1);
console.log("// toPrimitive(string) toString -> valueOf");
console.log("String(user):", String(user));
console.log("// 直接调用toString");
console.log(user.toString());
// toPrimitive(number) valueOf -> toString
number
Number(user): 999
number
user - 1: 998
number
user > 1: true
number
user > 'a': false
number
user * 2: 1998
// toPrimitive(default) valueOf -> toString
default
user +1: 1000
// toPrimitive(string) toString -> valueOf
string
String(user): toString
// 直接调用toString
toString
调用 obj[Symbol.toPrimitive](hint)
如果这个方法存在,由toPrimitive返回。 不存在按照下面的处理。
js
if (hint === "number" || hint === "default") {
return isBasicType(this.valueOf()) || this.toString();
}
if (hint === "string") {
return isBasicType(this.toString()) || this.valueOf();
}
valueOf
toString
valueOf
对于基础类型的数据,直接返回该类型
string
number
boolean
null
undefined
symbol
对于非原始值的重写规则如下
对象 | valueOf的返回值 |
---|---|
Array | 数组本身 |
*Boolean | 布尔值 |
*Date | 返回毫秒形式的时间戳 |
Function | 函数本身 |
*Number | 数字值 |
Object | 对象本身 |
*String | 字符串值 |
注意:String
Number
Boolean
Date
不返回自己
toString转换规则
对象 | toString的返回值 |
---|---|
Array | 以逗号分割的字符串,如[1,2]的toString返回值为"1,2" |
Boolean | "true" "false" |
Date | 可读的时间字符串,如"Tue Oct 15 2019 12:20:56 GMT+0800 (中国标准时间)" |
Function | 声明函数的JS源代码字符串 |
Number | "数字值" |
Object | "[object Object]" |
String | "字符串" |
注意:前提是原型上有toString,像null
undefined
调用不了。
检验一下
js
var bar=true;
console.log(bar+0);
console.log(bar+"xyz");
console.log(bar+true);
console.log(bar+false);
console.log('1'>bar);
console.log(1+'2'+false);
console.log('2' + ['str',1]);
var obj1 = {
a:1,
b:2
}
console.log('2'+obj1);
var obj2 = {
toString:function(){
return 'a'
}
}
console.log('2'+obj2)
NaN
- 无穷大除以无穷大
- 给任意负数做开方运算
- 算数运算符与不是数字或无法转换为数字的操作数一起使用
- 字符串解析成数字
js
Infinity / Infinity; // 无穷大除以无穷大
Math.sqrt(-1); // 给任意负数做开方运算
'a' - 1; // 算数运算符与不是数字或无法转换为数字的操作数一起使用
'a' * 1;
'a' / 1;
parseInt('a'); // 字符串解析成数字
parseFloat('a');
Number('a'); //NaN
'abc' - 1 // NaN
undefined + 1 // NaN
//一元运算符(注意点)
+'abc' // NaN
-'abc' // NaN
自动转换为 string 类型
字符串的自动转换,主要发生在字符串的加法运算时。 当一个值为字符串,另一个值为非字符串,转换未字符串。
js
'2' + 1 // '21'
'2' + true // "2true"
'2' + false // "2false"
'2' + undefined // "2undefined"
'2' + null // "2null"
//toString的对象
var obj2 = {
toString:function(){
return 'a'
}
}
console.log('2'+obj2)
//输出结果2a
//常规对象
var obj1 = {
a:1,
b:2
}
console.log('2'+obj1);
//输出结果 2[object Object]
//几种特殊对象
'2' + {} // "2[object Object]"
'2' + [] // "2"
'2' + function (){} // "2function (){}"
'2' + ['abc',1] // 2abc,1
自动转换为 number 类型
有加法运算符,但是无 String 类型的时候,都会优先转换为 Number 类型
js
true + 0; // 1
true + true; // 2
true + false; //1
"5" - "2"; // 3
"5" * "2"; // 10
true - 1; // 0
false - 1; // -1
"1" - 1; // 0
"5" * []; // 0
false / "5"; // 0
"abc" - 1; // NaN
null + 1; // 1
undefined +
1 + // NaN
//一元运算符(注意点)
"abc" - // NaN
"abc" + // NaN
true - // 1
false; // 0
注意:null 转为数值时为 0,而 undefined 转为数值时为 NaN。
什么时候进行布尔转换
js
if (!undefined && !null && !0 && !NaN && !"") {
console.log("true");
} // true
//下面两种情况也会转成布尔类型
expression ? true : false;
!!expression;
还是说一下==
吧
== 抽象相等比较与+运算符不同,不再是 String 优先,而是 Number 优先。
js
var obj1 = {
valueOf:function(){
return '1'
}
}
1 == obj1 //true
//obj1转为原始值,调用obj1.valueOf()
//返回原始值'1'
//'1'toNumber得到 1 然后比较 1 == 1
[] == ![] //true
//[]作为对象ToPrimitive得到 ''
//![]作为boolean转换得到0
//'' == 0
//转换为 0==0 //true
//boolean 先转成number,按照上面的规则得到1
//3 == 1 false
//0 == 0 true
3 == true // false
'0' == false //true