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没有valueOf
或toString
方法,因此在试图转为基本型别值的时候会出错,丢出TypeError。
ToBoolean
当 JavaScript 需要一个布尔值时(例如:if
语句),任何值都可以被使用,最终这些值将被转换为 true
或 false
。下面的值被转换为 false
:
undefined,null,false,-0,+0,NaN,’’。
所有其他值都认为是 true
。 被转换成 false
的值我们成之为 falsy,被转换成 true
的值我们成之为 truthy。 您可以使用 Boolean 来测试一个值到底被转换成了什么。
Boolean 将其参数转换为布尔值(boolean)
ToPrimitive
在比较运算与加法运算中,都会涉及到将运算符两侧的操作对象转化为原始对象的步骤;而 JavaScript 中这种转化实际上都是由 ToPrimitive 函数执行的。实际上,当某个对象出现在了需要原始类型才能进行操作的上下文时,JavaScript 会自动调用 ToPrimitive 函数将对象转化为原始类型;该函数的简化代码如下
var ToPrimitive = function (obj, preferredType) {
var APIs = {
typeOf: function (obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
},
isPrimitive: function (obj) {
var _this = this,
types = ['Null', 'Undefined', 'String', 'Boolean', 'Number'];
return types.indexOf(_this.typeOf(obj)) !== -1;
}
};
// 如果 obj 本身已经是原始对象,则直接返回
if (APIs.isPrimitive(obj)) {
return obj;
}
// 对于 Date 类型,会优先使用其 toString 方法;否则优先使用 valueOf 方法
preferredType = (preferredType === 'String' || APIs.typeOf(obj) === 'Date') ? 'String' : 'Number';
if (preferredType === 'Number') {
if (APIs.isPrimitive(obj.valueOf())) { // valueOf 之后如果是原始类型 return
return obj.valueOf()
};
if (APIs.isPrimitive(obj.toString())) { // valueOf 之后如果不是是原始类型 调用toString
return obj.toString()
};
} else {
if (APIs.isPrimitive(obj.toString())) {
return obj.toString()
};
if (APIs.isPrimitive(obj.valueOf())) {
return obj.valueOf()
};
}
throw new TypeError('TypeError');
}
注意:如果我们强制将某个对象的
valueOf
与toString
方法都覆写为返回值为对象的方法,在进行隐士类型转换的时候,则会直接抛出异常
比较运算
实际上在条件判断运算 ==
中的转换规则是这样的:
- 如果比较的两者中有布尔值
Boolean
,会把Boolean
先转换为对应的 Number,即 0 和 1,然后进行比较。 - 如果比较的双方中有一方为
Number
,一方为String
时,会把String
通过Number()
方法转换为数字,然后进行比较。 - 如果比较的双方中有一方为
Boolean
,一方为String
时,会将双方转换为数字,然后再进行比较。 - 如果比较的双方中有一方为
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 中的任一个为字符串,则会优先进行字符串连接;否则进行加法计算