javascript中ToPrimitive详解
source link: https://snayan.github.io/post/explanatio_of_ToPrimitive/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
javascript中ToPrimitive详解
July 06, 2017/「 javascript 」/ Edit on Github ✏️看了这么多框架方面的东西,但注意,基础很重要。今天就来说说 javascipt 中容易忽略的类型转换问题。
在 javascript 中有 7 种基本类型,它们为:string
,number
,boolean
,undefined
,null
,symbol
,object
。判断类型的方式是typeof
。我们把string
,number
,boolean
,undefined
,null
,symbol
这几类称为原始类型。
typeof 1 // 'number'
typeof "aa" // 'string'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof undefined // 'undefined'
typeof null // 'object'
typeof {} // 'object'
typeof function() {} // 'function'
注意两点,一是,对于函数,实际上也可以认为是object
,但使用typeof
得到的结果是function
;二是,对于null
,typeof
得到的结果是object
。
再来看看这些类型之间是怎么转换的呢?今天我们讨论的是object
类型转为原始值,对于原始值转为object
,可以直接进行包装即可,例如new Number(1)
,本次不予讨论,本次也不讨论原始类型之间的相互转换。
object 转为 number
先看看下面的几个情况,object
转number
,输出的值是几多
var obj = {}
console.log(Number(obj)) // NaN
obj = {
valueOf: function() {
return 1
},
}
console.log(Number(obj)) // 1
obj = {
toString: function() {
return 2
},
}
console.log(Number(obj)) // 2
obj = {
valueOf: function() {
return 1
},
toString: function() {
return 2
},
}
console.log(Number(obj)) // 1
从上面的例子可以看出,object
转为number
是根valueOf
和toString
函数有关的。具体步骤如下:
- 调用对象的
valueOf()
方法,如果返回结果是原始类型,则根据这个原始类型再转换为number
。 - 否则,调用对象的
toString()
方法,如果返回的结果是原始类型,则根据这个原始类型再转换为number
。 - 否则,抛出一个异常
TypeError
。注意一点的是,symbol
转为number
时会抛出异常的,null
转为number
是0
。
object 转为 string
我们再来看看下面的例子,输出是几多
var obj = {}
console.log(String(obj)) // "[object Object]"
obj = {
valueOf: function() {
return "a"
},
}
console.log(String(obj)) // "[object Object]"
obj = {
toString: function() {
return "b"
},
}
console.log(String(obj))
;("b")
obj = {
valueOf: function() {
return "a"
},
toString: function() {
return "b"
},
}
console.log(String(obj)) // "b"
从上面的例子可以看出,object
转为string
时也是与valueOf
和toString
有关,步骤如下:
- 调用对象的
toString()
方法,如果返回值是原始类型,则再把这个原始类型转为string
- 否则调用对象的
valueOf()
方法,如果返回值为原始类型,则再把这个原始类型转为string
- 否则,抛出一个异常
TypeError
。注意,symbol
转为string
时会抛出异常。
object 转为 boolean
object
转为boolean
时总是true
,在 javascript 中转为boolean
且值为false
时只有以下几种值;false
,''
,0
,NaN
,undefined
,null
。
看了这么多,实际上主要是object
转number
和string
时比较复杂,涉及 javascript 中内部的 ToPrimitive 方法。下面为 ecmascript262 中的官方定义:
The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType. The abstract operation ToPrimitive converts its input argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint PreferredType to favour that type.
函数签名为ToPrimitive(input[,PreferredType])=>PreferredType
。如果 PreferredType 为 Number,则执行以下步骤:
- 如果 input 是原始值,则返回这个值,结束。
- 否则,如果 input 是对象,则调用
input.valueOf()
。如果结果是原始值,则把结果值转为Number
。 - 否则,调用
input.toString()
。如果结果是原始值,则把结果值转为Number
。 - 否则,抛出一个
TypeError
。
如果PreferredType
是String
,则把第二步和第三步进行交换。PreferredType
也可以省略的,这种情况下,日期会被认为是String
而其他值会被认为是Number
。
需要注意的是,每个对象都有默认的valueOf
和toString
方法,valueOf
,toString
则根据具体的类型有所区别, 如下:
var obj = {}
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "[object Object]"
obj = [1, 2]
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "1,2"
obj = function() {}
console.log(obj.valueOf() === obj) // true
console.log(obj.toString()) // "function (){}"
obj = new Date()
console.log(obj.valueOf()) // 1497082546564
console.log(obj.valueOf() === obj) // false
console.log(obj.toString()) // "Sat Jun 10 2017 16:15:46 GMT+0800 (CST)"
//......
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK