先来看一个栗子:

if('0.00'){
  console.log('0.00')
}
var obj = {
    valueOf: function(){ return {} }, 
    toString: function(){ return {} }
}
console.log(obj == 0)

知道上面的栗子输出上面吗?

首先,JavaScript的内置类型有:nullundefinednumberstringbooleanobjectsymbol(ES6)。除去object,其他算是基本类型(primitives)。把一个值从一个类型转换成其他的类型的做法叫做类型转换。可以是显示的,也可以是隐式的

抽象值操作

类型的转换涉及到了转换的基本规则,这里介绍ToStringToNumberToBooleanToPrimitive

ToString

参数 结果
undefined "undefined"
null "null"
Boolean "false" or "true"
Number 将数字转化成字符串,如"1.1"
String 不变
Object ToPrimitiveToString

ToNumber

参数 结果
undefined NaN
null +0
Boolean false->0, true->1
Number 不变
String 转换规则间下面*
Object ToPrimitiveToNumber

String 的ToNumber规则。字符串和数字的字面量差不多(其他情况转化为NaN),即:

  1. 允许字符串前后有空白符

  2. 允许前面是0而不会被转化为8进制

  3. 允许用+/-代表符号位

  4. 只有空白符的情况下,转化为0

ToBoolean

参数 结果
undefined false
null false
Boolean 不变
Number 0,NaN->false; other->true
String length等于0->false; other->true
Object true

ToPrimitive

参数 结果
undefined 不变
null 不变
Boolean 不变
Number 不变
String 不变
Object 转化规则见下面*

这里涉及到了ToPrimitive ( input [, PreferredType] )input为输入的值, PreferredType为可选项(默认情况下是Number。另一个是String,作用和Number相反,先执行toString(),在执行valueOf())。

默认情况下(PreferredType为Number),内部先执行valueOf()得到的值如为primitive(基本类型)则输出结果,否则再执行toString()得到的值如为primitive则输出结果,否则报错。

两种转换

理解了上面的抽象值操作,就可以来看一下下面两种不同的转换。

显式转换

String():满足ToString转换规则

String(null) //"null"

Number():满足ToNumber转换规则

Number(' 010 ') //10

Boolean:满足ToBoolean转换规则

Boolean([1, 2, 3]) //true

parseInt(string, radix):满足ToString转换规则

var a = {
  //先执行toString
  toString: function () {
    return {}
  },
  //再执行valueOf
  valueOf: function () {
    return 0x10
  }
}
parseInt(a) //16

需要注意的是,由于a是对象,需要通过ToPrimitive得到Primitive(此时ToPrimitive ( input [, PreferredType] )PreferredTypeString),再将ToString(Primitive)得到"0x10"

隐式转换

一元操作符+:满足ToNumber转换规则

var a = "6";
+a + 6 //12

二元操作符 +

  1. 分别计算左右操作数,得到lval,rval。(有步骤合并省略)

  2. lprim = ToPrimitive(lval)。

  3. rprim = ToPrimitive(rval)。

  4. 如果lprim或rprim是字符串,都转换为字符串然后相加返回。

  5. 都转换为数字相加后返回。

[1, 2] + 1 //"1,21"

二元操作符 -

  1. 分别计算左右操作数,得到lval,rval。(有步骤合并省略)

  2. lnum = ToNumber(lval)。

  3. rnum = ToNumber(rval)。

  4. 相减后返回。

[1, 2] - 1 //NaN

条件 if(express)(||、&&、三元...):满足ToBoolean转换规则

if (' ') {
  console.log('blank')
} 
//blank

==运算

Type(x) Type(y) Result
两者类型相同 遵循===运算
null Undefined true
Undefined null true
Number String x == toNumber(y)
String Number toNumber(x) == y
Boolean (any) toNumber(x) == y
(any) Boolean x == toNumber(y)
String or Number Object x == toPrimitive(y)
Object String or Number toPrimitive(x) == y
otherwise… false
var a = {
  toString () {
    console.log('toString');
    return '1'
  },
  valueOf () {
    console.log('valueOf');
    return 1
  }
}
console.log('1' == a) // true

===运算

Type(x) Values Result
两者类型不一样 false
Undefined or Null true
Number 两者数值一样(非NaN) true
String 两者完全一样 true
Boolean 两者一样 true
Object 两者指向同一个对象 true
otherwise… false

关系比较(如<)

主要步骤:首先都转换为基础类型,如果都是字符串,按字符串比较;否则都转数字比较。

下面借用网上的图

==运算
==

===运算
===

参考

Truth, Equality and JavaScript
You-Dont-Know-JS笔记之类型和语法


huahua
463 声望11 粉丝

fighting