彻底理解JavaScript中的类型转换(上)

简介: 彻底理解JavaScript中的类型转换

1. 什么是类型转换?


Javascript 是一种弱类型语言,这意味着变量是没有明确类型的,而是由 JavaScript 引擎在编译时隐式完成。类型转换是将一种数据类型转换为另一种数据类型,例如:

20 + "twenty" // => "20twenty"
"10" * "10" // => 100 
2 - "x" 

Javascript 使用严格相等(===)和宽松相等(==)来测试两个值的相等性,类型转换仅在使用宽松相等运算符时发生。当使用 === 测试严格相等时,要比较的变量的类型和值都必须相同,例如:

10 === 10     // true
NaN === NaN   // false

在上面的代码中,10和10都是数字并且是完全相等的,所以正如预期的那样返回了true,两个 NaN 永远不会相等。当使用 == 测试宽松相等时,可能会发生隐式转换:

'20' == 20    // true
false == 0    // true

对于任何数据类型,无论是原始类型还是对象,都可以进行类型转换。尽管原始类型和对象的转换逻辑各不相同,但是都只能转换为三种类型:字符串(string)、数字(number)、布尔值(boolean)

JavaScript 中的类型转换有两种方式:

  • 隐式类型转换: 由 JavaScript 编译器完成的自动类型转换。
  • 显式类型转换: 由开发人员完成的手动类型转换。

下面先来看看 JavaScript 中的显式和隐式类型转换。

(1)显示类型转换

我们可以通过 JavaScript 内置的一些 API 将一种类型转换为另一种类型,这称为显式类型转化。执行显式类型转换的最简单方法是使用 Boolean()Number()String()parseInt()等函数,例如:

String(2 - true);     // '1'
'56' === String(56);  // true
Number('2350e-2');    // '23.5'
Number('23') + 7;     // 30
Boolean('');          // false
Boolean(2) === true;  //true

(2)隐式类型转换

隐式类型转换是将一种数据类型转换为另一种数据类型(确保在相同数据类型之间完成操作)以使运算符或函数正常工作,这种转换是由 JavaScript 编译器自动完成的,隐式类型转换也称为类型强制。例如:

'25' + 15;          // '2515'
23 * '2';           // 46
23 - true;          // 22
true - null;        // 1
false + undefined;  // NaN
const arr = [];
if(arr) { console.log('Hello World') };

下面这些常见的操作会触发隐式地类型转换,编写代码时要格外注意:

  • 运算相关的操作符:+、-、+=、++、* 、/、%、<<、& 等。
  • 数据比较相关的操作符: >、<、== 、<=、>=、===。
  • 逻辑判断相关的操作符: &&、!、||、三目运算符。

① + 运算符

/* 一个操作数 */
+ x // 将x转化为数字, 如果不能转化为数组将输出NaN
+ "1234string"   // NaN 
+ 1              // 1
+ '1'            // 1
+ true           // 1
+ undefined      // NaN
+ null           // 0
+ new Date()     // 1660493819396
/* 两个操作数 */
a + b
// 1. 如果其中任何一个是对象,则先将其转换为原始类型
{} + {}          // '[object Object][object Object]'
[] + []          // ''
[] + new Date()  // 'Mon Aug 15 2022 00:18:18 GMT+0800 (中国标准时间)'
// 2. 如果一个是字符串,则将另一个转换为字符串
1 + ''           // '1'
'' + 1           // '1'
'' + true        // 'true'
// 3. 否则,将两者都转换为数字
1 + true         // 2
true + true      // 2

② -、*、/、++、--

// 将一个或多个值转换为数字
 - '1'     // -1
 [] - 1    // -1
 [] - {}   // NaN

③ ==、!=

javascript
复制代码
// 两个操作数
 a == b
// 1. 如果一个是 `null` 而另一个是 `undefined`,它们是相等的
null == undefined    // true
// 2. 如果一个是数字,另一个是字符串,将字符串转换为数字,再比较
1 == '1'             // true
// 3. 如果其中一个是布尔值,将其转换为数字,再次比较
true == 1            // true
false == 0           // true
// 4. 如果一个是对象,另一个是数字或字符串,将对象转换为原始类型,再次比较
[1] == 1             // true
['1'] == '1'         // true

下图是在使用 == 时,判断两个操作数是否相等的总结(绿色表示相等,白色表示不等):

33.webp.jpg

④ >、>=、<、<=

javascript
复制代码
// 两个操作数
a > b
// 1. 如果其中一个是对象,则将其转换为原始类型,再次比较
[2] > 1   // true
// 2. 如果两者都是字符串,使用字母顺序比较它们
'b' > 'a' // true
// 3. 如果其中一个是数字,则将一个或两个非数字转换为数字
'2' > 1   // true

⑤ in

/* 如果左操作数不是字符串,则将其转换为字符串 */
 a in b
'1' in {1: ''}    // true
 1 in {1: 'a'}    // true
 1 in ['a', 'b']  // true


2. 常见类型转换


(1)字符串转换

将数据类型转换为字符串称为字符串转换,可以使用 String() 函数将数据类型显式转换为字符串。当一个操作数是字符串时,可以通过使用 + 运算符来触发隐式字符串转换。

① 数字 => 字符串:

Number对象的 toString() 方法会返回指定 Number 对象的字符串表示形式。String()new String() 会把对象的值转换为字符串。

String(20);           // '20'
String(10 + 40);      // '50'
(10 + 40).toString(); // '50'
new String(10 + 20);  // '30'

② 布尔值 => 字符串:

String()toString() 方法会将布尔值转化为对应的字符串形式。

String(true);     // 'true'
String(false);    // 'false'
true.toString()   // 'true'
false.toString()  // "false"

③ 数组 => 字符串:

String() 方法会将数组元素通过逗号连接起来,无论嵌套多少层,都会将其展开并返回元素拼接好的字符串。如果是空数字,会返回空字符串:

String(true);     // 'true'
String(false);    // 'false'
true.toString()   // 'true'
false.toString()  // "false"

④ 对象 => 字符串:

使用 String() 方法会将对象转化为 '[object Object]',无论对象是否为空对象:

String({name: "Hello"});   // '[object Object]'

⑤ null / undefined / NaN => 字符串:

使用 String() 方法会将  nullundefinedNaN 转化为其对应的字符串形式:

String(undefined);    // 'undefined'String(null);         // 'null'String(NaN);          // 'NaN'

⑥ 日期 => 字符串:

String(newDate('2022-08-20')) // 'Sat Aug 20 2022 08:00:00 GMT+0800 (中国标准时间)'

⑦ 隐式转换

当任何数据类型使用+运算符与字符串连接时会发生到字符串的转换(隐式转换):

"25" + 56;              // '2556'
"25" + null;            // '25null'
"Hello " + undefined;   // 'Hello undefined'
"25" + false;           // '25fasle'
"25" + {};              // '25[object Object]'
"25" + [10];            // '2510'

所以,当我们想要创建一个操作并且操作数类型之一是字符串时,应该小心使用类型强制转换。

⑧ 总结

下面是 ECMAScript 规范中将数据类型转换为字符串的规则:

8.webp.jpg

ECMAScript 规范:262.ecma-international.org/5.1/#sec-9.…

(2)布尔转换

将数据类型转换为布尔值称为布尔转换。这种转换既可以由 Boolean() 函数显式完成,也可以在逻辑上下文中隐式完成(如if/else )或通过使用逻辑运算符( ||、&&、! )触发。

① 字符串 => 布尔值:

使用 Boolean() 方法转化字符串时,只有当字符串为空时会返回false,其他情况都会返回 true

Boolean('hello'); // true 
Boolean(' ');     // true 
Boolean('');      // false

② 数字 => 布尔值:

使用 Boolean() 方法转化数字时,只有 0、-0 或 NaN 会转化为 false,其他情况会返回 true

Boolean(-123); // true 
Boolean(123);  // true 
Boolean(0);    // false
Boolean(-0);   // false
Boolean(NaN);  // false

③ 数组 / 对象 => 布尔值:

使用 Boolean() 方法转化数组或对象时,无论数组和对象是否有内容,都会返回true

Boolean([1, 2, 3]); // true
Boolean([]);        // true
Boolean({});  // true
Boolean({'hello': 'world'});  // true

④ null / undefined => 布尔值:

使用 Boolean() 方法转化nullundefined时,都始终返回 false


Boolean(undefined);  // false Boolean(null);       // false

⑤ 隐式转换

在数学运算中,true 转换为 1,false 转换为 0:

j

true + 5;    // 6
false + 5;   // 5
5 - true;    // 5
5 - false;   // 4

⑥ 逻辑运算符、逻辑上下文

// 如果其中一个不是布尔值,则将其转换为布尔值
Boolean( null || undefined || 0 || -0 || NaN || '' )    // false
Boolean( 1 && 'a' && { } && [] && [0] && function(){} ) // true
true && false // false
true && true // true
true || false // true
true || !false // true

注意,逻辑运算符,例如 ||&& 内部进行布尔转换,但实际上返回原始操作数的值,即使它们不是布尔值。

javascript

复制代码

'hello' && 123;   // 123

可以使用双感叹号(!!)来将变量转为为布尔值:

!!0    // false
!!""   // false
!!" "  // true
!!{}   // true
!![]   // true
!!true // true

if、else if、while、do/while 和 for 使用与 &&、||、! 相同的隐式类型转换方式(逻辑表达式)。

下面是在 if 语句(逻辑上下文)中的隐式转换规则(绿色为true,白色为false):

9.webp.jpg

⑦ 总结

除了下面这些之外的所有其他值都是真值,包括对象、数组、日期等。甚至所有Symbol、空对象和数组都是真值。

Boolean('');        // false
Boolean(0);         // false     
Boolean(-0);        // false
Boolean(NaN);       // false
Boolean(null);      // false
Boolean(undefined); // false
Boolean(false);     // false
Boolean({})             // true
Boolean([])             // true
Boolean(Symbol())       // true
Boolean(function() {})  // true

可以通过以下方式来过滤数组中的假值:

[0, "", " ", null, undefined, NaN].map(Boolean); // 输出结果:[false, false, true, false, false, false]

我们可以会遇到一种情况,当使用 5 == true 时,结果为false,而使用if(5) {}时,则 5 被认为是 true 并进入if/else语句:

5 == true;  // false
if (5) {
    console.log('5');  // 5
};

这种情况下,即一个值和数字进行比较时,JavaScript 会试图将这个值转换为数字。所以,当比较5 == true 时,JavaScript 倾向于将true转换为1,因为 1不等于5,因此结果为 false。而在if(5) {}的情况下,5 被转换为布尔值,而 5 是一个真值,所以它进入if块。在这种情况下,可以选择显式转换以避免错误,因为 5 是一个真值,可以执行Boolean(5) == true,这样就会返回true了。

下面是 ECMAScript 规范中将数据类型转换为布尔值的规则:

11.webp.jpg

ECMAScript 规范:262.ecma-international.org/5.1/#sec-9.…


彻底理解JavaScript中的类型转换(下)https://developer.aliyun.com/article/1411370


相关文章
|
6月前
|
JavaScript 前端开发
JavaScript基础语法(类型转换)
JavaScript基础语法(类型转换)
50 0
|
JavaScript 前端开发
js中的类型转换
js中的类型转换
54 0
|
6月前
|
JavaScript 前端开发
JavaScript变量、数据类型、运算符及类型转换
JavaScript变量、数据类型、运算符及类型转换
67 0
|
30天前
|
JavaScript 前端开发 安全
如何处理 JavaScript 中的类型转换错误?
【10月更文挑战第9天】处理类型转换错误需要综合运用多种方法和策略,同时要保持对潜在问题的警惕性。通过合理的错误处理,可以提高程序的健壮性,减少因类型转换错误带来的负面影响。
17 0
|
30天前
|
JavaScript 前端开发
JS隐式类型转换规则
【10月更文挑战第9天】 不同的 JavaScript 引擎可能在隐式类型转换的具体实现上存在一些细微差别。理解这些隐式类型转换规则对于正确处理数据和避免错误非常重要。
16 0
|
2月前
|
JavaScript 前端开发
JavaScript 类型转换
JavaScript 类型转换
25 4
|
3月前
|
JavaScript 前端开发
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
|
4月前
|
JavaScript
js【详解】自动类型转换
js【详解】自动类型转换
25 0
|
4月前
|
JavaScript 前端开发
|
6月前
|
JavaScript 前端开发 Python
javascript中的强制类型转换和自动类型转换
javascript中的强制类型转换和自动类型转换