分析下面代碼的執行流程。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
的結果在大多數時候能夠認爲是徹底同樣的,處理字符串時徹底能夠互換。
參考
今天的文章就到這裏,感謝閱讀~
歡迎你們關注個人掘金和公衆號,專一於提高前端程序員的核心競爭力