分析下面代码的执行流程。html
var obj = {
value: 3,
valueOf() {
return 4;
},
toString() {
return '5'
},
}
+obj // 4
''+obj // '4'
`${obj}` // '5'
复制代码
Symbol.toPrimitive
原始值 primitive value 是 Undefined
, Null
, Boolean
, Number
, Symbol
, String
之一,原始值是直接在语言实现的最低级别表示的数据。前端
当对象要被转换为数字或者字符串时,将会涉及到 ToPrimitive ( input [ , PreferredType ] )
转换。程序员
PreferredType
表示对象将要转换的类型
PreferredType
未传递,则令 hint
为 default
PreferredType
为 String,则 hint
为 string
PreferredType
为 Number,则 hint
为 number
在 Symbol.toPrimitive 属性(用做函数值)的帮助下,一个对象可被转换为原始值。该函数被调用时,会被传递一个字符串参数 hint
,表示要转换到的原始值的预期类型。 hint
参数的取值是 "number"、"string" 和 "default" 中的任意一个。es6
经过Symbol.toPrimitive
咱们能够自定义在转换为目标原始值时的一些行为和返回值(返回值不能是非原始值,不然报错),若是没有这个属性,则会调用 valueOf
或者 toString
。bash
var obj = {
value: 3,
valueOf() {
return 4;
},
toString() {
return '5'
},
[Symbol.toPrimitive](hint) {
console.log('hint', hint)
return 6
}
}
复制代码
valueOf
和 toString
若是没有定义 Symbol.toPrimitive
,那么转换会经过 valueOf
、toStirng
处理以后返回。下面看看转换顺序和规则。函数
若是 hint
推断类型是 default
(Date 对象除外) ,则认为它是 number
,如今就只有 number
和 string
两种类型。ui
hint
为 string
,即要转换为字符串,则先用 toString
处理,若是是原始值则返回,不然再用 valueOf
处理,若是返回是原始值则返回,不然会报 TypeError
错误;hint
为 number
,则先用 valueOf
再用 toString
,valueOf
执行能返回原始值则直接返回不会执行 toString
,若是 toString
返回的结果不是原始值则会报 TypeError
错误;上面的规则应用于大多数场景。但对 Date
不适用,日期对象没有 hint
,认为 hint
是 string
。 以下面的例子,'' + d
,对通常对象,hint
是 default
,由前面知道 default
同 number
,对日期对象 hint
是 string
。this
看下面三个例子es5
对象默认的 valueOf
返回本身。spa
var obj = {}
obj === obj.valueOf() // true
复制代码
var obj = {
value: 3,
valueOf() {
console.log('valueof')
return this;
},
toString() {
return '5'
},
}
+obj
// valueof 由于要转换位数字,因此执行了 valueOf,可是返回是对象,因此又执行 toString
// 5
复制代码
var d = new Date()
+d // 1571718957902 时间戳
''+d // "Tue Oct 22 2019 12:35:57 GMT+0800 (China Standard Time)" 字符串,涉及到先转换后拼接
`${d}` // "Tue Oct 22 2019 12:35:57 GMT+0800 (China Standard Time)" 字符串
复制代码
+
运算符+'5'
复制代码
规范
ToNumber(GetValue(expr))
归纳来讲就是转换时 hint
为 number
,对于原始值类型(Undefined
, Null
, Boolean
, Number
, Symbol
, String
),直接使用内部 ToNumber
转换成数字,下面是转换规则。对于对象,先使用 ToPrimitive
再使用 ToNumber
。
来几个例子。
+undefined // NaN
+null // 0
+true // 1
+false // 0
+'6.11' // 6.11
+'6.1e15' // 6100000000000000
+'6.1e21' // 6.1e+21
+' 6 ' // 6
+' 6 7 8 ' // NaN
+'0xf' // 15
+'f' // NaN
var obj = {
value: 3,
valueOf() {
return 4;
},
[Symbol.toPrimitive](hint) {
console.log('hint', hint)
return 6
}
}
+obj
// hint number
// 6
var obj = {
value: 3,
valueOf() {
return 4;
},
}
+obj
// 4
复制代码
Number 当作一个函数来使用。
规范
若是提供了 value,返回 ToNumber(value) 计算出的数字值(非 Number 对象),不然返回 +0。
从规范看出,Number
比 +
运算符少了 GetValue
。GetValue
有和没有对原始值是没有影响的,只对对象有影响。
Number(x)
和 +x
的结果在大多数时候能够认为是彻底同样的,处理字符串时彻底能够互换。
参考
今天的文章就到这里,感谢阅读~
欢迎你们关注个人掘金和公众号,专一于提高前端程序员的核心竞争力