javascript的原型例如string、numeric和boolean可以相互进行类型转换,同样,object类型也可以转换为原型,但是由于所有对象转换为boolean都为true,所以不存在boolean的转换。因此,object通常只有两种原型转换:一种是string,另一种是numeric。
javascript对于object的原型转换有默认的机制,下面简要的记录一下~
对象的原型转换机制
object会根据上下文环境所需要的原型来进行转换,比如alert(),则会转换为string,如果是数值运算符操作则会转换为numeric。进一步讲,object会使用ToPrimitive算法来转换为原型,这种算法允许我们自定义特定的对象方法来将对象转换为原型,这种转换有一个叫做hint(提示)的原语,object会根据hint的值来选择转换为string还是numeric。
hint的值分为三种:string、numeric和default。当hint的值为string时,object会转换为string原型,numeric则转换为numeric原型,default则为无法确定转换为string还是numeric,因为两种原型都可以转换,这种情况一般很少。
为了实现object的原型转换,javascript有以下的转换机制:
(1)如果存在obj[Symbol.toPrimitive](hint)方法,则调用它;
(2)如果hint是string的话,调用obj.toString(),如果obj.toString()不存在则调用obj.valueOf();
(3)如果hint是numeric的话,调用obj.valueOf(),如果obj.valueOf()不存在则调用obj.toString();
Symbol.toPrimitive
javascript提供了内置方法Symbol.toPrimitive,通过它我们可以自定义object具体的转换原型,例如:
let user = {
name: "John",
money: 1000,
[Symbol.toPrimitive](hint) {
alert(`hint: ${hint}`);
return hint == "string" ? `{name: "${this.name}"}` : this.money;
}
};
// conversions demo:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500
toString()/valueOf()
当对象不存在Symbol.toPrimitive方法时,javascript会试图去寻找并调用toString()和valueOf()方法,例如:
let user = {
name: "John",
money: 1000,
// for hint="string"
toString() {
return `{name: "${this.name}"}`;
},
// for hint="number" or "default"
valueOf() {
return this.money;
}
};
alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500
如果toString()和valueOf()都不存在的话,对象则无法转换为原型。
ToPrimitive and ToString/ToNumber
无论是Symbol.toPrimitive(hint)还是toString(),valueOf(),都必须返回一个原型,这个原型可以使string也可以是numeric,例如:
let obj = {
toString() { // toString handles all conversions in the absence of other methods
return "2";
}
};
alert(obj * 2); // 4, ToPrimitive gives "2", then it becomes 2
let obj = {
toString() {
return "2";
}
};
alert(obj + 2); // 22 (ToPrimitive returned string => concatenation)
let obj = {
toString() {
return true;
}
};
alert(obj + 2); // 3 (ToPrimitive returned boolean, not string => ToNumber)
不管Symbol.toPrimitive(hint),toString(),valueOf()返回什么原型,javascript会根据hint来进行转换,而这个hint的值是由上下文环境来确定的。