ToString

任何非字串的值被强制转型为字串时,会遵循ES5的规格中的ToString来运作。
规则简单说明如下

  • undefined -> 'undefined'
  • null -> 'null'
  • boolean的true -> 'true',false -> 'false'
  • 在数字方面,非常大或非常小的数字以指数呈现,例如:'1.23e21'
  • object
    1. 若有定义其toString方法,则会以它自己的toString方法所产生的结果为优先,例如,阵列有自己定义的toString方法,因此[1,2,3].toString()会得到"1,2,3"
    2. 若没有定义toString方法,则回传内部的属性[[Class]],这是一个用来标记这个值是属于物件的哪个子分类的标签,例如:({}).toString()会得到[object Object]

ToNumber

若需要将非数字值当成数字来操作,像是做数学运算,就会遵循ES5的规格中的ToNumber来运作。
规则简单说明如下

  • undefined -> NaN。
  • null -> +0 即是0。
  • boolean 的true -> 1,false -> +0 即是0。
  • string -> 数字或NaN。
  • object
    1. 若有定义其valueOf方法,则会优先使用valueOf取得其基本型别值。
    2.若没有定义valueOf方法,则会改用toString方法取得其基本型别值,再用ToNumber转为数字。在这里先简化为Number(..)会来处理这一连串的流程即可。
    3.注意,以Object.create(null)建立的null没有valueOftoString方法,因此在试图转为基本型别值的时候会出错,丢出TypeError。

ToBoolean

当 JavaScript 需要一个布尔值时(例如:if 语句),任何值都可以被使用,最终这些值将被转换为 truefalse。下面的值被转换为 false

undefined,null,false,-0,+0,NaN,’’。

所有其他值都认为是 true。 被转换成 false 的值我们成之为 falsy,被转换成 true 的值我们成之为 truthy。 您可以使用 Boolean 来测试一个值到底被转换成了什么。
Boolean 将其参数转换为布尔值(boolean)

ToPrimitive

在比较运算与加法运算中,都会涉及到将运算符两侧的操作对象转化为原始对象的步骤;而 JavaScript 中这种转化实际上都是由 ToPrimitive 函数执行的。实际上,当某个对象出现在了需要原始类型才能进行操作的上下文时,JavaScript 会自动调用 ToPrimitive 函数将对象转化为原始类型;该函数的简化代码如下

  1. var ToPrimitive = function (obj, preferredType) {
  2. var APIs = {
  3. typeOf: function (obj) {
  4. return Object.prototype.toString.call(obj).slice(8, -1);
  5. },
  6. isPrimitive: function (obj) {
  7. var _this = this,
  8. types = ['Null', 'Undefined', 'String', 'Boolean', 'Number'];
  9. return types.indexOf(_this.typeOf(obj)) !== -1;
  10. }
  11. };
  12. // 如果 obj 本身已经是原始对象,则直接返回
  13. if (APIs.isPrimitive(obj)) {
  14. return obj;
  15. }
  16. // 对于 Date 类型,会优先使用其 toString 方法;否则优先使用 valueOf 方法
  17. preferredType = (preferredType === 'String' || APIs.typeOf(obj) === 'Date') ? 'String' : 'Number';
  18. if (preferredType === 'Number') {
  19. if (APIs.isPrimitive(obj.valueOf())) { // valueOf 之后如果是原始类型 return
  20. return obj.valueOf()
  21. };
  22. if (APIs.isPrimitive(obj.toString())) { // valueOf 之后如果不是是原始类型 调用toString
  23. return obj.toString()
  24. };
  25. } else {
  26. if (APIs.isPrimitive(obj.toString())) {
  27. return obj.toString()
  28. };
  29. if (APIs.isPrimitive(obj.valueOf())) {
  30. return obj.valueOf()
  31. };
  32. }
  33. throw new TypeError('TypeError');
  34. }

注意:如果我们强制将某个对象的 valueOftoString 方法都覆写为返回值为对象的方法,在进行隐士类型转换的时候,则会直接抛出异常

比较运算

实际上在条件判断运算 == 中的转换规则是这样的:

  1. 如果比较的两者中有布尔值 Boolean ,会把 Boolean 先转换为对应的 Number,即 0 和 1,然后进行比较。
  2. 如果比较的双方中有一方为 Number,一方为 String时,会把 String 通过 Number() 方法转换为数字,然后进行比较。
  3. 如果比较的双方中有一方为 Boolean,一方为 String时,会将双方转换为数字,然后再进行比较。
  4. 如果比较的双方中有一方为 Number,一方为Object时,则会调用 valueOf 方法将Object转换为数字,然后进行比较。
  • 如果 x 或 y 中有一个为 NaN,则返回 false;
  • 如果 x 与 y 皆为 null 或 undefined 中的一种类型,则返回 true(null == undefined // true);否则返回 false(null == 0 // false);
  • 如果 x,y 类型不一致,且 x,y 为 String、Number、Boolean 中的某一类型,则将 x,y 使用 toNumber 函数转化为 Number 类型再进行比较;
  • 如果 x,y 中有一个为 Object,则首先使用 ToPrimitive 函数将其转化为原始类型,再进行比较。
#1 
1 == true // true
0 == false // true
#2
1 == '1' // true
#3
'1' == true // true
#4
var obj = {
    valueOf: function() {
        return 1
    }
}
1 == obj // true
#5
[] = ![] // true
// [] -> '' -> 0 
// ![] -> false -> 0

加法运算

对于加法运算而言,JavaScript 首先会将操作符两侧的对象转换为 Primitive 类型;然后当适当的隐式类型转换能得出有意义的值的前提下,JavaScript 会先进行隐式类型转换,再进行运算。例如如 value1 + value2 这个表达式,首先会调用 ToPrimitive 函数将两个操作数转化为原始类型:

prim1 := ToPrimitive(value1)
prim2 := ToPrimitive(value2)

这里将会优先调用除了 Date 类型之外对象的 valueOf 方法,而因为数组的 valueOf 方法的返回值仍为数组类型,则会返回其字符串表示。而经过转换之后的 prim1 与 prim2 中的任一个为字符串,则会优先进行字符串连接;否则进行加法计算