JavaScript 关系运算的隐式转化

一、前言

JavaScript是一门弱类型的语言,他在声明变量的时候不需要指定类型,对变量赋值也没有类型的检测,所以js是非常的灵活的,但是有时候也会出现一些非常匪夷所思的问题。比如下面的例子

console.log(1+'1');

隐式类型转换就是指,数据的类型在不用人工干预的情况下进行转换的行为。在js中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算。
0 这种无需程序员手动转换,而由编译器自动转换的方式就称为隐式转换


二、隐式类型转换

通过下面的例子,分析他们结果,了解隐式类型转换。

一元运算
let   a = 1 + 'a';
console.log(a) // 1a
let  b = 1 - 'b'
console.log(b) // NaN
let c = 11 + '1';
console.log(c) // 111
let d = 11 - '1';
console.log(d) // 10

这个例子很多时候大家想到结果是对的,但是其中的深层原因是为什么,估计大部分人一知半解。先解释下其中的隐式转化,在JavaScript中进行运算的时候,会对运算的字符转化成数字在进行计算,Number(‘b’) 的结果是NaN,Number(‘11’) = 11,所以b的运算结果是NaN,d的结果是10。这个就解释了b和d的结果为什么是NaN和10了。但是按照这个规则来解释a和c又不对了,这个是因为字符串的相加运算是字符串的拼接,两个参数会调用valueOf(),需要的话会调用toString(),所以这就是a和c的值为什么不是NaN和10的原因。

####JavaScript中的关系运算符 == 和 >
JavaScript中的关系符有很多,现在主要通过==和>介绍其中的隐式类型转换。先看简单的例子

console.log(0 == ''); // true
console.log(0 == '0'); // true
console.log(undefined == ''); // false
console.log(undefined == null); // true
console.log(null == null); // true
console.log(undefined == undefined); // true
console.log(NaN == NaN);  // false
console.log(NaN == 0);  // false
console.log( true == 1); // true
console.log( true == '1'); // true
console.log( false == ''); // true
console.log( false == '0'); // true

上面例子的结果之所以如此,其中就是他们大都进行了隐式类型转换,只要是涉及到不同数据类型需要计算的时候都会触发隐式类型转换,然后隐式类型中主要有三种转换方式:

  • 将值转为原始值,ToPrimitive()。

  • 将值转为数字,ToNumber()。

  • 将值转为字符串,ToString()。

上面涉及到的隐式转化的规则是:
1.字符串和数字进行比较时,字符串转换成数字,二者再比较。
2.字符串和布尔值进行比较时,二者全部转换成数值再比较。
3.布尔值和数字进行比较时,布尔转换为数字,二者比较。
其中,** 有三个值是无视规则的,null,undefined, NaN **,NaN和任何值都不等,包括它自己NaN,而null 和 undefined相等之外,与其他值都不等,但等于它自身。

复杂数据类型的隐式类型转换
console.log([] == true);  //false
console.log([1,2,3] == '1,2,3') // true
console.log([1] == 1);  // true 
console.log([] == false);  // true 
console.log(![] == false);  // true 

先来个图解释下

任意两种类型比较时,如果不是同一个类型比较的话,则按如图方式进行相应类型转换,如对象和布尔比较的话,对象 => 字符串 => 数值 布尔值 => 数值。这就解释了上面的结果,

其中,最后两个例子比较有趣,这两个的结果都是true,第一个是,对象 => 字符串 => 数值0 false转换为数字0,这个是true应该没问题,第二个前边多了个!,则直接转换为布尔值再取反,转换为布尔值时,空字符串(’’),NaN,0,null,undefined这几个外返回的都是true, 所以! []这个[] => true 取反为false,所以[] == false为true。

** 延伸例子 **

[2,3] + [1,2] // ‘2,31,2’
[2] + 1 // ‘21’
[2] + (-1) // “2-1”

大小的比较
console.log(2 > 10); //false
console.log('2' > 10); //false
console.log('2' > '10'); //true
console.log('abc' > 'b'); //false
console.log('abc' > 'aad'); //true

解释下上面的结果,当关系运算符两边有一边是字符串时,会将其他数据类型通过**Number()转化,然后比较关系。解释了前两个例子。当关系运算符两边都是字符串时,会将其他数据类型通过Number转化,但 此时的并不是按照Number的形式转化成数字,而是按照字符串对应的unicode编码来转化成数字 **,使用charCodeAt(字符下标,默认为0),

console.log(‘2’.charCodeAt()) // 50
console.log(‘10’.charCodeAt()) // 49

这就解释了第三个例子,第五个例子是因为多个字符从左往右一次比较。a==a, b > a,所以最后一个例子结果为true。
** 延伸 **

0-9 unicode编码 48 - 57
a-z unicode编码 97 - 122

** 延伸例子 **

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值