对象toString和valueOf方法的详解
2019-04-13 本文已影响0人
vinterx
讲解这章之前,先看个简单的案例
let qq = 'vinter'
let aa = 13
let bb = true
let obj = {name: 'vinter'}
let arr = [1,2]
// 常用对象
let date = new Date()
let fn = () => {}
// console.dir(Number)
// console.dir(String)
// console.dir(Boolean)
// let cc = null
// let dd = undefined
console.log(qq.toString())
console.log(aa.toString())
console.log(bb.toString())
console.log(obj.toString())
console.log(arr.toString())
console.log(date.toString())
console.log(fn.toString())
console.log('==============')
console.log(qq.valueOf())
console.log(aa.valueOf())
console.log(bb.valueOf())
console.log(obj.valueOf())
console.log(arr.valueOf())
console.log(date.valueOf())
console.log(fn.valueOf())
image.png
- 从上面可以看出,所有的常规数据类型的原型中都是具有toString()和valueOf方法的,所以实例才能调用这些方法,但
是没有这两种方法的,NaN虽然是Number类型中的异类,但是也有这两种方法。 - 20.toString()会被误解不是对象,是因为JS会首先解析其为浮点,(20).toString()能正常输出,所以数字也是对象。
- 其次除了对象Object或者对象实例的toString方法会返回形如[object 类型]外,其他如String、Function、Number、Boolean等类型会调用自己的toString()方法返回原始值的字符串类型;而valueOf()方法则返回原始值。
理解那些类型具有这两种方法后,接下来进入正题。
上章节提到三个问题:
- 对象Object的toString()和数组toString()方法的区别;
- 对象toString()方法可以检查对象类型,可以归类有几种检查类型的方法;
- toString()方法和valueOf()方法是如何被隐式调用的,在什么场景下会被隐式调用。
四种类型检查比较
写几种常用类型
let str = '123456'
let bol = true
let num = 123
let obj = {name: 'vinter'}
let arr = [1,2,3]
let nul = null
let undef = undefined
class Parent {
constructor(age, sex) {
this.age = age
this.sex = sex
}
action() {}
}
class Son extends Parent {
constructor(age,sex,name) {
super(age,sex)
this.name = name
}
say() {}
}
let son = new Son(18, 'male', 'vinter')
注意:
let Son = () => {} // 这是错误的
let Son = function(){} // 这是正确的
let son = new Son()
1、typeof
示例
console.log(typeof str) // string
console.log(typeof bol) // boolean
console.log(typeof num) // number
console.log(typeof obj) // object
console.log(typeof arr) // object
console.log(typeof nul) // object
console.log(typeof undef) // undefined
console.log(typeof son) // object
console.log(typeof Son) // function
总结
- typeof检查的类型全都是小写字符串如"object"
- typeof能检查function
- typeof不能区分对象的类型,检测的对象除了函数外,全部输入“object”
- typeof检查null为对象而检查undefined为undefined
2、instanceof
console.log( str instanceof Object) // false
console.log( bol instanceof Boolean) // false
console.log( num instanceof Number) // false
console.log( obj instanceof Object) // true
console.log( arr instanceof Object) // true
console.log( nul instanceof Object) // false
console.log( undef instanceof Object) // false
console.log( son instanceof Object) // true
console.log( son instanceof Son) // true 重点
console.log( Son instanceof Function) // true 重点
console.log( Son instanceof Object) // true
总结
- instanceof不能检查简单类型,只能检查复杂类型即对象
- instanceof能区分对象类型
- instanceof检测undefined和null不是对象
3、Object.prototype.toString
console.log( Object.prototype.toString.call(str)) // [object String]
console.log( Object.prototype.toString.call(bol)) // [object Boolean]
console.log( Object.prototype.toString.call(num)) // [object Number]
console.log( Object.prototype.toString.call(obj)) // [object Object]
console.log( Object.prototype.toString.call(arr)) // [object Array]
console.log( Object.prototype.toString.call(nul)) // [object Null]
console.log( Object.prototype.toString.call(undef)) // [object Undefined]
console.log( Object.prototype.toString.call(son)) // [object Object]
console.log( Object.prototype.toString.call(Son)) // [object Function]
转换
console.log(Object.prototype.toString.call(str).slice(8, -1)) // [object String] ==> String
总结
- 这个方法是既能检查对象类型又能检测简单类型,并且还能检测null和undefined类型
- 检测的类型都是首字母大写如:String,和typeof不同的地方(注意)
- 通常需要调用slice(8,-1)方法进行转换
4、constructor
console.log( str.constructor === String) // true
console.log( bol.constructor === Boolean) // ture
console.log( num.constructor === Number) // true
console.log( obj.constructor === Object) // true
console.log( arr.constructor === Object) // false
console.log( arr.constructor === Array) // true 重点
// console.log( nul.constructor === Object) // 报错
// console.log( undef.constructor === Object) // 报错
console.log( son.constructor === Object) // false
console.log( son.constructor === Son) // true 重点
console.log( Son.constructor === Object) // false
console.log( Son.constructor === Function) // true 重点
总结
- 不能检查null和undefined
- 能够区分对象类型
- 能够检测简单类型
综合上述:
简单的用typeof足够,但是对于要求严格的代码,推荐使用Object.prototype.toString.call(params).slice(8, -1)
toString()方法和valueOf()方法是如何被隐式调用的
注意:万物皆对象,null和undefined除外,这对下面理解有帮助。
对象toString()和valueOf谁先被调用
let obj = {
valueOf: function(){
console.log("valueOf")
return 10;
},
toString: function(){
console.log("toString")
return '10';
}
}
alert(obj) // toString 显示
alert(++obj) // valueOf 运算
console.log(obj == "10") // 10 true 左右对象均调用valueOf()方法
console.log(obj + "10") // 10 "1010" (js的特殊例子,虽然都调用valueOf(),但是却转化为字符串)
总结
1、 在进行强转字符串类型时将优先调用toString方法,强转为数字时优先调用valueOf。
2、 在有运算操作符的情况下,valueOf的优先级高于toString。
3、valueOf偏于运算,而toString则偏向显示
4、加法是个特殊的案例,虽然调用了valueOf方法但是却是字符串相加
null、undefined、""、0、NaN
// 比较运算符 == 推荐使用比较运算符 ===
console.log(1 == true)
console.log(0 == false)
console.log("0" == false)
console.log([] == false)
console.log("" == false)
console.log(null == undefined)
// 逻辑运算符&& || !(重要)
console.log(!"")
console.log(!0)
console.log(!null)
console.log(!undefined)
console.log(!NaN)
// 以上全部返回true