JavaScript 是一种动态类型语言,变量没有类型限制,可以随时赋予任意值,所以这里我们就要聊聊数据的类型转换。
数据类型转换主要分强制转换和隐式转换两种:
1.强制转换。
强制转换是指使用String,Number,Boolean三个方法,手动将各种类型的值转换成对应的字符串、数值、布尔值。
1.1 String
String函数可以将任意类型的值转化成字符串,具体转换规则如下;
(1)原始值类型
- a. 字符串:转换后还是原始的值;
- b. 数值:转换为对应的字符串;
- c. 布尔值:true => 'true', false => 'false';
- d. null:null => 'null';
- e. undefined:undefined => 'undefined';
String(123); // "123" String('abc'); // "abc" String(true); // "true" String(undefined); // "undefined" String(null); // "null"
(2) 对象。要理解String方法的内在规则,就不用死记了。具体规则如下;
- 先调用自身的toString(可能会被自定义)方法,如果返回的是原始类型的值,直接对返回的值使用String方法返回,不在进行后面步骤。
const obj1 = { a: 1 }; String(obj1); // [object Object] // 相当于 String(obj1.toString()); // [object Object] const obj2 = { toString: () => { return 2; } } String(obj2); // '2'
- 如果toString方法返回的是对象,则继续调用自身(而不是toString方法返回的对象)的valueOf(同样也可能会被自定义)方法,如果返回原始类型的值,直接对返回的值使用String方法返回,不在进行后面步骤。
const obj1 = { toString: () => { return {}; }, valueOf: () => { return 'haha'; }, } String(obj1); // 'haha' const obj2 = { toString: () => { return { valueOf: () => { return 'heihei'; }, }; }, valueOf: () => { return 'haha'; }, } String(obj2); // 'haha' // 注意,这里并不是调用toString返回对象的valueOf方法,而是调用原对象的valueOf方法
- 如果valueOf方法返回的还是对象,就报错。
const obj1 = { toString: () => { return {}; }, } String(obj1); // Uncaught TypeError: Cannot convert object to primitive value
1.2 Number
Number函数可以将任意类型的值转化成数值,具体转换规则如下;
(1)原始类型
- a. 字符串;
- 如果可以转换为数值,返回数值;
- 如果不可以转换为数值,返回NaN;
- 空字符串转换为0;
- 会自动过滤一个字符串前导和后缀的空格;
Number('123'); // 123 Number('123aaa'); // NaN Number(''); // 0 Number(' '); // 0 Number(' 0 '); // 0 Number(' 0 0 '); // NaN
- b. 数值:直接原值返回;
Number(123); // 123 Number(0); // 0 Number(0.23); // 0.23 Number(NaN); // NaN Number(Infinity); // Infinity Number(-Infinity); // -Infinity
- c. 布尔值:true => 1, false => 0;
Number(true); // 1 Number(false); // 0
- d. null:null => 0;
Number(null); // 0
- e. undefined:undefined => NaN;
Number(undefined); // NaN
(2)对象。简单的规则就是除非是包含单个数值的数组(或者空数组),都返回NaN。
Number({}); // NaN
// 相当于
({}).valueOf(); // {}
({}).toString(); // '[object Object]'
Number('[object Object]'); // NaN
Number([]); // 0
// 相当于
[].valueOf(); // []
[].toString(); // ''
Number(''); // 0
Number([1]); // 1 等同于Number(['1']);
// 相当于
[1].valueOf(); // [1]
[1].toString(); // '1'
Number('1'); // 1
具体转换的规则和String相似,只不过调换了调用toString和valueOf方法(注意,这两个方法都可能会被自定义覆盖)的顺序。
- 先调用obj.valueOf方法,如果返回原始类型的值,直接对返回值调用Number函数返回。
const obj = { valueOf: () => { return '123'; }, } Number(obj); // 123
- 如果valueOf方法返回的是对象,则继续调用obj.toString方法。如果toString方法返回的是原始类型的值,对返回值调用String函数。
const obj1 = { valueOf: () => { return {}; }, } Number(obj1); // NaN // 这里obj1的toString方法返回‘[object Object]’; const obj2 = { valueOf: () => { return {}; }, toString: () => { return '123'; }, } Number(obj2); // 123
- 如果toString方法返回的还是对象,直接报错。
const obj = { valueOf: () => { return {}; }, toString: () => { return {}; }, }; Number(obj); // Uncaught TypeError: Cannot convert object to primitive value
1.3 Boolean
Boolean()函数可以将任意类型的值转为布尔值。
其规则就相对简单一些,除了以下五个值转化为false之外,其他的都是true;
undefined
null
0
(包含-0
和+0
)NaN
''
(空字符串)Boolean(undefined); // false Boolean(null); // false Boolean(0); // false Boolean(NaN); // false Boolean(''); // false 这里是空字符串 Boolean(' '); // true 这里是带空格的
以上就是关于强制转换的介绍。
2.隐式转换。
规则就是,预期什么类型的值,就调用对应的转换函数。
2.1 转换为布尔值
JavaScript 遇到预期为布尔值的地方,比如if判断语句、三目运算、使用!(非运算符)等等,就会调用Boolean函数进行隐式转换。
2.2 转换为字符串
主要发生在字符串的加法运算中。非字符串类型的值会先调用String转换为字符串,然后在进行加法运算。
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
2.3 转换为数值
除了加法(+)会把运算子转换成字符串,其他的运算符都会将运算子调用Number函数转换为数值。
'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 这里Number(undefined)得到的是NaN
一元运算符也会把运算子转成数值。
+'abc' // NaN
-'abc' // NaN
+true // 1
-false // 0