JavaScript隐式类型转换进阶
JavaScript中有许多的隐式类型转换,合理运用它们能对项目的开发提供更便捷的处理方式,目前涉及到隐式类型转换的的运算符主要有:数学运算符(加减乘除,取模,自增等)、if,alert语句、逻辑运算符(&&,||,!等)、关系运算符(==, >,<等)
数学运算符的隐式转换规则
变量表达式在进行数学运算时,会根据变量的类型进行相关的运算操作,此时的变量会进行一些隐式类型转换,具体的规则如下:
-
减法-
,乘法*
,除法/
,取余%
,减等-=
,除等/=
,模等%=
,自减--
,自增++
,正+
,负-
1.如果运算符两侧的变量都是基本数据类型或数组,调用
Number()
方法将变量转换成数字进行运算;2.如果运算符中有对象,则调用对象的
valueOf()
方法,如果返回基本类型,转步骤1;如果valueOf()
方法返回的是对象,则对变量调用toString()
方法,如果返回基本类型,转步骤1,否则返回NaN
。'4' / 2; // 2 '1245' * 10; // NaN [2] / 2; // 1 [2,3] / 2; // NaN [2] * [5]; // 10 let test = {valueOf: () => '123'} ++test; // 124 test = {valueOf: () => [2], toString: () => '200'}; test % 3; // 2 test = {valueOf: () => [2], toString: () => ['200']}; test--; // NaN
-
加法+
,加等+=
1.如果有一侧的变量为字符串,则进行字符串的拼接;
2.如果两侧的变量为出字符串的其他基本数据类型,则调用
Number()
方法,进行数学运算;3.如果有一侧是数组,则调用数组的
toString()
方法,然后进行字符串的拼接;4.如果运算符中有对象,则调用对象的
valueOf()
方法,如果返回基本类型,根据返回的类型转步骤1-2;如果valueOf()
方法返回的是对象,则对变量调用toString()
方法,如果返回基本类型,根据返回的类型转步骤1-2,否则返回NaN
。2 + 3; // 5 '2' + 3; // '23' [2] + [5,6]; // '25,6' let test1 = {valueOf: () => 3}; test1 += 2; // 5 test1 = {valueOf: () => [], toString: () => '55'}; test1 + 2; // '552' test1 = {valueOf: () => [], toString: () => {}}; test1 + 2; // NaN
逻辑运算符的隐式转换规则
逻辑运算符的隐式转换规则是根据运算符两侧的变量调用Boolean()
方法转换成Boolean值再进行逻辑运算,逻辑运算=符主要有或||
,与&&
,非!
.
-
或||
对第一个值调用
Boolean()
方法,如果为true,则返回第一个值;否则返回第二个值// 可以让某个方法或表达式在特定的情况下被调用 let re = !isUsable || (123 + 20); // 143 34 || 43; // 34 '' || 43; // 43
-
与&&
对第一个值调用
Boolean()
方法,如果为true,则返回第二个值,否则返回第一个值'' && 2; // "" {} && 4; // 4 // 让某个方法在特定的情况下被调用 let res = isShowDialog && showDialog();
-
非!
对变量调用
Boolean()
方法,然后对Boolean值取反!false; // true !{}; // false ![]; // false
关系运算符的隐式转换规则
关系运算符通常是将变量进行比较,对于不同类型的变量而言,其比较的规则有有所差别,详细规则如下:
-
大于>
,小于<
,大于等于>=
,小于等于<=
1.如果有一个变量为数字,则将另一个值转换成数字再进行比较,转换规则同数学运算符;
2.如果有两个变量为字符串,则一个一个地比较字符串对应的UNICODE编码;
3.如果有一个变量为字符串,另一个为对象,则先调用对象的
valueOf()
方法,如果返回数值,转步骤1;如果返回字符串,转步骤2;如果返回对象,则调用toString()
方法,如果返回数值,转步骤1,如果返回字符串,转步骤2;4.如果有一个变量是布尔值、null、undefined,则将其转换成数值,再进行比较;
5.如果一个变量为字符串,另一个变量为数组,如果数组第一个元素为字符串,将此字符串与第一个变量比较UNICODE值;如果数组第一个元素为数值,将第一个变量转换成数值再进行比较。
5 > '4'; // true 50 > '51'; // false '51' > '5001'; // true '51' > [50]; // true '51' > ['5001']; // true let test2 = {valueOf: () => [23]}; 51 > test2; // true 22 > test2 // false test2 = {valueOf: () => ['233']}; 51 > test2; // false test2 = {valueOf: () => [],toString: () => 55}; 51 > test2; // false
-
等等==
和不等!=
1.如果其中一个变量是数字,同上;
2.如果两个变量为字符串,同上;
3.如果两个变量都为对象,直接比较两个变量的引用地址是否相同;
4.如果有个变量为字符串,另一个为对象,同上;
5.如果有一个变量是布尔值、null、undefined,除非另一个变量也是对应的值,否则都为false;
6.如果一个变量为字符串,另一个变量为数组,同上。
5 == '5'; // true 51 == {valueOf: () => 51}; // true 51 == {valueOf: () => [], toString: () => 51}; // true '51' == {valueOf: () => [], toString: () => '51'}; // true '51' == '51'; // true {valueOf: () => 123} == {valueOf: () => 123}; // false [2] == 2; // true ['2'] == '2'; // true ['2'] == 2; // true
-
全等===
和不全等!==
1.如果两侧数据类型不相等,返回false;
2.如果两侧都是数字,比较数字大小;
3.如果两侧都是字符串,比较字符串是否相同;
4.如果两侧都是对象,比较对象引用地址是否相同;
JS中的隐式类型转换总会在我们意想不到的情况下发生,在数据处理中尤为如此,所以当请求到后端传送的数据后,为避免进行隐式类型转换,通常需要做到以下两步:
- 将请求过来的数据进行一次复制,避免在无意中修改一些数据。
- 深刻理解隐式类型转换的机制与原理,避免不必要的数据转换。
- 在确认某种数据类型后再作对应的运算操作。
现在去看看你在项目中的代码是否有许多隐式类型转换的操作吧!
奋斗是这么个过程,当时不觉累,事后不会悔。走一段再回头,会发现一个更强的自己,宛如新生