重学JS: 隐式强制类型转换

1,896 阅读5分钟

隐式强制类型转换指的是那些隐藏的强制类型转换,副作用也不是很明显,事实上,只要自己觉得不够明显的强制类型转换都可以算作隐式强制类型转换,接下来,此文将会介绍几种常见的隐式类型转换。

加法操作符

转换规则:

  • 如果两个操作数,一个操作数是数字,另一个数是布尔值,那么则将布尔值转换为数字,然后进行加法操作
  • 如果两个操作都是字符串,则将第二个操作数与第一个操作数拼接起来
  • 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,然后再将两个字符串拼接起来
    • 如果另一个操作数是数字、或布尔值,则调用它们的toString()方法取得对应的字符串值
    • 如果另一个操作数对象,对象valueOf()方法返回基本值,则调用valueOf()方法取得返回值,然后再做字符串拼接,否则直接调用toString()方法取得对应的字符串值

举例:

console.log(1 + true) // 2
console.log('1' + '1') // '11'
console.log(1 + '1') // '11'
console.log('1' + 'true') // '1true'
var a = {
  valueOf: function() {
    return 2
  },
  toString: function() {
    return 1
  }
}
var b = {b: 1}
console.log(a + '1') // '21'
console.log(b + '1') // '[object Object]1'

减法操作符

转换规则:

  • 如果有一个操作数字符串、布尔值、null或者undefined,则先在后台调用Number()函数将其转换为数值,如果转换的结果是NaN,则减法的结果就是NaN
  • 如果有一个操作数是对象,则调用的valueOf()方法取得表示该对象的数值,如果得到的结果是NaN,则减法的结果就是NaN。如果对象valueOf()方法返回不是基本值,则调用toString()方法并将得到的字符串转为数字

举例:

console.log(5 - '1') // 4
console.log(5 - true) // 4
console.log(5 - null) // 5
console.log(5- undefined) // NaN
const c = {
  valueOf: function() {
    return '1'
  }
}
console.log(5 - c) // 4

隐式强制类型转为布尔值

场景:

  • if()语句中的条件判断表达式
  • for()语句中的条件判断表达式
  • while()和do..while()循环条件中的判断表达式
  • ?:三元运算中的判断表达式
  • 逻辑元算符||和&&左边的操作数

以上的场景中非布尔值会被隐式的强制转为布尔值,转换规则遵循上篇文章的ToBoolean转换规则
举例:

const d = 11
const e = null
let f
const g = f ? d : e
console.log(g) // null
console.log(d && e) // null
console.log(d || e) // 11

相等

相等操作符分为宽松相等==和严格相等===,这两个都用来判断值是否相等,区别在于在判断两边操作数是否相等时,宽松相等允许进行强制类型转换,而严格相等不允许进行强制类型转换,因此下面只会介绍宽松相等在比较时的强制类型转换
转换规则:

  • 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值,false转为0true转为1
  • 如果一个操作数是字符串,另一个操作数是数字,在比较之前先将字符串转换为数字
  • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,若不是基本类型值,则调用toString()方法,用得到的基本类型值按照前面的规则进行比较
  • null和undefined是相等的
  • 要比较相等性之前,不能将null和undefined转换成其他任何值
  • 如果有一个操作数是NaN,则相等操作符返回false,而不相等返回true。即使两个操作数都是NaN,相等操作符也返回false
  • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true,否则,返回false

举例:

console.log(null == undefined) // true
console.log('NaN' == NaN) // false
console.log(5 == NaN) // false
console.log(NaN == NaN) // false
console.log(NaN != NaN) // true
console.log(false == 0) // true
console.log(true == 1) // true
console.log(true == 2) // false
console.log(undefined == 0) // false
console.log(null == 0) // false
console.log('5' == 5) // true

比较操作符

比较操作符包括小于(<)、大于(>)、小于等于(<=)、和大于等于(>=) 转换规则:

  • 如果两个操作数都是字符串,则比较两个字符串的字符编码值
  • 如果一个操作数是数值,则将另一个操作数转换为数值,然后进行数值比较
  • 如果一个操作数是对象,则调用这个对象的valueOf()方法,若返回值是基本类型,则用得到的结果进行比较,否则调用toString()方法,用得到的值进行比较
  • 如果一个操作数是布尔值,则先将其转换为数字,然后进行比较

举例:

console.log('11' < 3) // false
console.log(true < 2) // true
const h = {
  valueOf: function () {
    return '22'
  }
}
console.log(h > 1) // true

总结

这篇文章对JS中的常见隐式强制类型转换做了一个小结,希望能对大家理解有所帮助。如果有错误或不严谨的地方,欢迎批评指正,如果喜欢,欢迎点赞