JS 类型转换,小尝一口

JavaScript 类型转换

字符串数字布尔值
undefined"undefined"NaNfalse
null"null"0false
true"true"1
false"false"0
""0false
"1.2"1.2true
"one"NaNtrue
0"0"false
-0"0"false
NaN"NaN"false
Infinity"Infinity"true
-Infinity"-Infinity"true
1"1"true
{}"[object Object]"NaNtrue
[]""0true
[9]"9"9true
[1, 2, 3]"1,2,3"NaNtrue
['a']"a"NaNtrue
function foo(){}"function foo(){}"NaNtrue

类型转换的基本规则

  • ToString
  • ToNumber
  • ToBoolean
  • ToPrimitive

ToString

负责非字符串字符串的强制类型转换。

基本数据类型
  • null => "null"
  • undefined => "undefined"
  • true => "true"
  • 12 => "12"
对象

除非自行定义,否则 toString() 返回内部属性 [[Class]] 的值。

这个属性无法直接访问,一般通过 Object.prototype.toString(..) 查看

如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。

var a = {
    name: 'ym'
}
var b = {
    name: 'ym',
    toString: function() {
        return this.name;
    }
}

a.toString(); // "[object Object]"
b.toString(); // "ym"
复制代码
数组

数组的默认 toString() 方法经过重新定义

var a = [1, 2, 3];
a.toString(); // "1,2,3"
复制代码

ToNumber

基本数据类型
  • true => 1 false => 0
  • undefined => NaN
  • null => 0
对象(包括数组)

首先会被转换为相应的基本类型值。如果是非数字的基本类型值,则按上面的规则强制转换。

将值转换为相应基本类型的步骤:(ToPrimitive)

  1. 检查该值是否有 valueOf() 方法。
    • 如果有并且返回基本类型值,就使用该值进行强制类型转换。
    • 如果没有就使用 toString() 的返回值进行强制转换。
  2. 如果 valueOf()toString() 均不返回基本类型值,会产生 TypeError 错误。
// case1: 对象只有 valueOf 方法,并且返回基本类型值
// 此时就调用 valueOf
var a = {
    valueOf: function() {
        return '42';
    }
}

// case2: 对象只有 toString 方法,并且返回基本类型值
// 此时调用 toString
var b = {
    toString: function() {
        return '32';
    }
}

// case3:两种方法都有。并且 valueOf 返回基本类型值
// 此时调用 valueOf
var c = {
    valueOf: function() {
        return '42';
    },
    toString: function() {
        return '32'
    }
}

// case4: 两种方法都有。但是 valueOf 返回的不是基本类型值,而 toString 返回基本类型值
// 此时调用 toString
var d = {
    valueOf: function() {
        return [1, 2];
    },
    toString: function() {
        return '32'
    }
}

// case5: 两种方法都有。但是返回的都不是基本类型值
// 此时报错 Uncaught TypeError: Cannot convert object to primitive value
var e = {
    valueOf: function() {
        return [1, 2];
    },
    toString: function() {
        return [1, 3];
    }
}

Number(a); // 42
Number(b); // 32
Number(c); // 42
Number(d); // 32
Number(e); // Uncaught TypeError: Cannot convert object to primitive value
复制代码

栗子:chestnut:

// [].valueOf() => []
// [].toString() => ""
// "" => 0
Number([]); // 0

// ['abc'].valueOf() => ['abc']
// ['abc'].toString() => "abc"
// "abc" => NaN
Number(['abc']); // NaN
复制代码

ToBoolean

两类值
  • 可以被强制转换为 false 的值(注意这一部分的值比较少)

    • undefined
    • null
    • false
    • +0 -0 NaN
    • ""

    注意1[]{} 强制转换并不是 false 而是 true

    注意2

    var a = new Boolean(false);
    var b = new Number(0);
    var c = new String("");
    
    Boolean(a && b && c) // 三者强制转换均为 true,因为本质是对象
    复制代码
  • 其他(转换为 true

== 号的比较

两个值的类型相同

这种情况就只比较值是否相等,不会做类型转换。

正常情况
1 == 1 // true
'abc' == 'abc' // true
true == true // true
null == null // true
undefined == undefined // true
[] == [] // false
{} == {} //false
复制代码
特别情况
NaN == NaN // false
+0 == -0 // true
复制代码

两个值的类型不同

这种情况会发生隐式类型转换。会将其中之一或者二者都转换为相同的类型后再进行比较。

数字和字符串

不论二者的位置关系是怎么样,就是将字符串转换为数字类型

  • a 是数字,b 是字符串,返回 a == ToNumber(b)
  • a 是字符串,b 是数字,返回 ToNumber(a) == b
// case1: 数字 == 字符串
42 == '42' // true
42 === '42' // false

// case2: 字符串 == 数字
'42' == 42 // true
复制代码
布尔和其他类型
  1. 布尔类型首先会转换成数字类型。(同样跟位置没有关系)

    => 因此问题变成了数字和其他类型的比较了

// case1:布尔 == 字符串
// 第一步:true => 1
// 第二步:'42' => 42
// 第三步:1 == 42 => false
true == '42' // false
false == '42' // false

// case2:布尔 == 数字
true == 1 // true
false == 0 // true
复制代码
null 和 undefined

不论位置,结果为 true。

null == undefined // true
undefined == null //true
复制代码
null 和 undefined 与其他类型

均返回 false。

null == false // false
undefined == false // false
null == "" // false
undefined == "" // false
null == 0 // false
undefined == 0 // false
复制代码
对象和非对象

对象首先要转化为基本数据类型

  • a 是对象,b 是非对象,返回 a == ToPrimitive(b)
  • a 是非对象,b 是对象,返回 ToPrimitive(a) == b
// case1
// 第一步:[42] => '42'
// 第二步:'42' => 42
// 第三步:42 == 42 => true
42 == [42] // true

// case2:布尔和数组
// false => 0
// [] => ""
// "" => 0
[] == false // true
// ![] => false
![] == false // true
复制代码
'abc' == new String('abc') // true
123 == new Number(123) // true
false == new Boolean(false) // true

null == Object(null) // false
undefined == Object(undefined) // false
NaN == new Number(NaN) // false
复制代码
数组与其他

数组会转换为字符串,因此问题就变成了字符串与其他的比较

[] == false // true
[] == "" // true
[] == 0 // true

// ToBoolean(![]) => false
// [] == false => true
[] == ![] // true

// 因为先进行 !运算,所以 false 不会首先转换为数字
// 第一步:![] => false
// 第二步:false == false => true
![] == false // true
复制代码

注意!:由于 !的优先级要高于 ==,因此会先进行 !运算,再进入 == 流程

+ 号的隐式转换

数字和字符串运算

两种情况
  • 字符串 + 数字 => 字符串
  • 数字 + 字符串 => 字符串
总结

字符串和数字存在加法运算,最终得到字符串。

加号和字符串

  • + 数字字符串 => 数字
  • + 非数字字符串 => NaN

参考

  • 《你不知道的JS》

  • 《JavaScript 权威指南》

转载于:https://juejin.im/post/5bc92fd85188255c5b5c6db2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值