本帖最后由 没名字i 于 2020-4-9 10:02 编辑
js中类型转换分为显示转换和隐式转换,下面我总结一下都有哪些情况会发生类型转换。
一.显示转换
1.通过调用 parseInt、parseFloat、new Number()等都会发生显示转换。在转换中的规则如下:
第一个字符是有效数字,就会将有效数字部分转换为数值;
[AppleScript] 纯文本查看 复制代码 console.log(parseInt('123abc')); // 123
第一个字符是非数字,就会转换为NaN;
[AppleScript] 纯文本查看 复制代码 console.log(parseInt('abc123')); // NaN
那么请看一下下面这道显式转换题:
[AppleScript] 纯文本查看 复制代码 var str = 'abc123',
num = parseFloat(str);
if (num === NaN) {
alert(NaN);
} else if (num === 123) {
alert(123);
} else if (typeof num === 'number') {
alert('number');
} else {
alert('str');
}
// 结果是: 'number'
最终输出'number',原因是str第一个字符非数字,会转换成NaN,众所周知的NaN是不全等与NaN的。而typeof NaN是number,所以输出结果是'number'
二、隐式转换
众所周知,js中当遇到+ - * / > < ==等运算符的时候,会发生隐式转换。而+和其他运算符有一些不同。除了+,其他都会转换为数值型。
1.+操作符
对于+,遇到字符串那么就会按照字符串拼接去计算,而不是简单的加运算。
console.log('123'+ 456); // 123456
复制代码
当非数字类型遇到+的时候,也会发生隐式类型转换。
[AppleScript] 纯文本查看 复制代码 // Boolean类型遇到数值,会转换成数值型。 true=1; false=0
console.log(true+1); // 2
console.log(false+1); // 1
console.log(false + false); // 0
console.log(true + true); // 2
// 当Boolean遇到字符串,会转换成字符串
console.log(true+'1'); // true1
当+作为***一元操作符***的时候,其位于操作树的前面。如果操作数不是一个数值,会尝试将其转换成一个数值。这时候就发生隐式转换了。尽管一元负号也能转换非数值类型,但是一元正号是转换其他对象到数值的***最快方法***,也是***最推荐***的做法,因为它不会对数值执行任何多余操作。遇到不能转换的返回NaN。会将布尔类型、null、字符串转换为数值型。
[AppleScript] 纯文本查看 复制代码 +3 // 3
+"3" // 3
+true // 1
+false // 0
+null // 0
+function(val){ return val;} //NaN
看如下一道面试题:
[AppleScript] 纯文本查看 复制代码 var a = 'abc' + 123 + 456;
alert(a); // abc123456
var b = '456' - '123';
alert(b); // 333
var c = 1,
d = '1';
var f = c > d ? (c < d ? c : d) : (c == d ? c : d);
alert(f); // 输出1
2.其他的隐式转换
当作为对象属性的key值时,所有类型都会被toString()。
[AppleScript] 纯文本查看 复制代码 var a = {};
b = 123;
a = 'hello';
console.log(Object.keys(a)) // ["123"]
所以看如下一道面试题:
[AppleScript] 纯文本查看 复制代码 // 题一
var a={}, b='123', c=123;
a='b';
a[c]='c';
console.log(a); // 都会转换为字符串123,所以 a[c]会覆盖a,输出 c
-----------------------------
// 题二
var a={}, b=Symbol('123'), c=Symbol('123');
a='b';
a[c]='c';
console.log(a); // Symbol是生成唯一值的。 所以b不等于c,输出 'b'
------------------------------
// 题三
var a={}, b={key:'123'}, c={key:'456'};
a='b';
a[c]='c';
console.log(a); // 对象类型作为属性名,都会被转换为string,所以a会被a[c]覆盖掉。输出'c'
三、类型判断方法
类型判断的方法有typeof、instanceof、Object.prototype.toString.call(xxx) === '[object yyy]'。他们都有哪些优缺点呢?
1.typeof
它只能判断基本数据类型有:number、string、boolean、symbol、undefined。对于对象类型和null,统一都返回object.
[AppleScript] 纯文本查看 复制代码 console.log(typeof '123'); // string
console.log(typeof 123); // number
console.log(typeof false); // boolean
console.log(typeof Symbol(123)); // symbol
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof new Date()); // object
2.instanceof
它用来检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。就是检测某个实例对象是不是该函数的实例
[AppleScript] 纯文本查看 复制代码 function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const auto = new Car('Honda', 'Accord', 1998);
console.log(auto instanceof Car); // true
console.log(auto instanceof Object); // true
3.Object.prototype.toString.call
最严谨的判断是通过Object.prototype.toString.call来判断类型。
[AppleScript] 纯文本查看 复制代码 console.log(Object.prototype.toString.call('123') === '[object String]'); // true
console.log(Object.prototype.toString.call(123) === '[object Number]'); // true
console.log(Object.prototype.toString.call(Symbol(123)) === '[object Symbol]'); // true
console.log(Object.prototype.toString.call(new Date()) === '[object Date]'); // true
链接:https://juejin.im/post/5e8d5e6251882573834ecaa4
|