JavaScript 学习笔记 之 强制类型转换 (三)

宽松相等(==)和严格相等(===)

为什么这个问题的讨论要放在类型转换这里呢?

首先,这里有一个常见的误区,==是检查值是否相等,===是检查值和类型是否相等

然而JavaScript中实际上是

==允许在比较中进行强制类型转换,而===不允许

首先在性能上,两者差别不大(大概百万分之一秒)

我们考虑的只有需不需要强制类型转换这一点而已

抽象相等(==)

ES5中"抽象相等比较法"定义了==运算符的行为

其中规定如果两个值类型相同,就仅仅比较它们是否相等

如果两个值类型不同,==会发生隐式强制类型转换,会将其中之一或者两者都转换为相同的类型后再比较

但是有几个特殊情况需要注意

  • NaN不等于NaN
  • +0等于-0

然后还定义了对象的宽松相等==,两个对象指向同一个值的时候即视为相等(比较对象的时候==和===是完全一样的,都不会发生强制类型转换)

常见情况

  1. 字符串和数字之间的比较
  2. 其他类型和布尔类型之间的比较
  3. null和undefined之间的比较
  4. 对象和非对象之间的相等比较

1. 字符串和数字之间的比较

如果==运算符中有一边是字符串,另一边是数字

则将字符串强制转换为数字后进行比较

如 "42"==42 实际上是 42==42

2. 其他类型和布尔值之间的相等比较

如果==运算符中有一边是布尔值

则将布尔值强制转换为数字后进行比较

			"42" == true //false

3. null和undefined之间的比较

如果==运算符中有一边是null,另一边是undefined

则结果为true

也就是说==中null和undefined相等(他们自身也相等)

除此之外其他值都不存在这种情况

4. 对象和非对象之间的相等比较

如果==运算符中有一方是字符串或数字(布尔值会首先被转换为数字)

另一方是对象(对象/函数/数组)

那么对象首先会进行一个ToPrimitive抽象操作转换为对应的基本类型值

ToPrimitive抽象操作通过内部操作[[DefaultValue]]检查是否有valueOf()方法,如果有并返回基本类型值,就使用该值进行强制类型转换,如果没有就使用toString()的返回值(如果存在)来进行强制类型转换,普通对象的toString()会返回内部[[class]]的值,比如"[object Object]",而数组会将所有单元字符串化后用","连接起来,基本类型的封装对象则会由valueOf返回基本类型值

一些例外的情况

			Object(null) == null, //false
			Object(undefined) == undefined, //false
			Object(NaN) == NaN, //false

null和undefined没有封装对象,因此Object(null)返回的是Object()本身

Object(NaN)等同于new Number(NaN),但是拆封后 NaN == NaN 返回一个false值

抽象关系比较

前面说了==时候的比较规则

这里说下a<b中涉及的隐式强制类型转换

(该算法仅针对于a<b,a>b会被处理成b<a)

首先,比较双方先调用ToPrivate,如果结果出现非字符串,就再调用ToNumber将双方强制类型转换为数字来比较

如果双方都是字符串,则按照字母顺序来比较

但是有一点格外需要注意

JavaScript中的a<=b实际上等同于 !(a>b) 然后会被处理成!(b<a)

		var a = {
			num: 1
		}
		var b = {
			num: 2
		}

		a > b //false
		a == b //false
		a < b //false

		a <= b //true
		a >= b //true

这个例子中a,b都被转为"[object Object]",因此 a<b a>b都返回false,而a<=b和a>=b都返回的是!false也就是true

但是==的时候由于两边都是对象并且并不指向同一个对象,因此返回false

猜你喜欢

转载自blog.csdn.net/Aproducer/article/details/82873733