JS中的valueof()和toString()

142 阅读4分钟

前言

==运算符中,如果比较的操作数一个为引用数据类型,一个为基础数据类型,会先将引用数据类型进行隐式转换,这里也就会用到valueof()toString(),学习这两个方法有助于我们理解==运算符的使用

valueOf()函数

valueOf()方法属于Object对象,因为所有对象都继承了Object对象实例,所以几乎所有的实例对象都可以使用这个方法

对象返回值
String字符串值
Number数字值
Boolean布尔值
Array数组实例对象
Oject对象本身
Function函数本身
Date从1970.1.1午夜开始记得毫秒数
Null/Undefined抛出TypeError异常

下面是一些例子

// Array:返回数组对象本身
var array = ["CodePlayer", true, 12, -5];
console.log( array.valueOf() === array ); // true

// Date:当前时间距1970年1月1日午夜的毫秒数 
// Mon Aug 01 2022 10:00:52 GMT+0800 (中国标准时间)
var date = new Date();
console.log(date.valueOf()); // 1659319290701

// Number:返回数字值 
var num = 15.26540; 
num.valueOf() // 15.2654 
console.log(num.valueOf() === num); // true

// 布尔:返回布尔值true或false 
var bool = true; 
console.log(bool.valueOf() === bool); // true

// Function:返回函数本身 function foo(){} 
console.log( foo.valueOf() === foo ); // true 
var foo2 = new Function("x", "y", "return x + y;"); 
console.log( foo2.valueOf() === foo2); // true

// Object:返回对象本身 
var obj = {name: "张三", age: 18}; 
console.log( obj.valueOf() === obj ); // true 

// String:返回字符串值 
var str = "http://www.xyz.com"; 
console.log( str.valueOf() === str ); // true

// new一个字符串对象 
// String {"http://www.xyz.com"} 
var str2 = new String("http://www.xyz.com"); 
str2.valueOf() // "http://www.xyz.com" 
// 两者的值相等,但不全等,因为类型不同,前者为string类型,后者为object类型 console.log( str2.valueOf() === str2 ); // false

toString() 函数

toString()函数的作用是把一个 逻辑值转换为字符串,并返回结果

Number 类型

  • toString()可以根据所传递的参数将数组转换为相应禁止的数字字符串,范围为2~36
let a = 37
console.log(a.toString(2)) // 100101
console.log(a.toString(36)) // 11
NaN.toString() // 'NaN'
Infinity.toString() //'Infinity'

数值变量不能直接调用toString()方法,必须先试用小括号或者通过变量调用,因为整数后的 . 会被识别为小数点

0.toString() // Uncaught SyntaxError: Invalid or unexpected token
1.2.toString() // '1.2'
(12).toString() // '12'
  • 负浮点数或加’+'号的正浮点数直接跟上.toString(),相当于先运行toString()方法,再添加正负号,转换为数字
+1.23.toString();//1.23 
typeof +1.23.toString();//'number' 
-1.23.toString();//-1.23
typeof -1.23.toString();//'number'

(+1.2).toString();//'1.2' 
(-1.2).toString();//'-1.2'

Object 类型

对象Object类型及自定义对象类型加括号返回[object Object]

{}.toString() //报错,Unexpected token .
({}).toString() //[object Object]
({a:123}).toString() //[object Object]
Object.toString() //"function Object() { [native code] }"

Function 类型

当我们对一个自定义函数调用toString()方法时,可以得到该函数的源代码;如果对内置函数使用toString()方法时,会得到一个[native code]字符串。因此,可以使用toString()方法来区分自定义函数和内置函数

function test(){
    alert(1);//test
}
test.toString();/*"function test(){
                    alert(1);//test
                  }"*/
Function.toString();//"function Function() { [native code] }"

Array 类型

数组Array类型返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串

[].toString() // ''
[1,2].toString() // '1,2
Array.toString() // 'function Array() { [native code] }'

Date 类型

时间Date类型返回表示当前时区的时间的字符串表示

(new Date()).toString() // 'Mon Aug 01 2022 10:59:57 GMT+0800 (中国标准时间)'
Date.toString() // 'function Date() { [native code] }'

RegExp 类型

正则表达式RegExp类型返回正则表达式字面量的字符串表示

/ab/i.toString() // '/ab/i'
/mom( and dad( and baby)?)?/gi.toString() // 'mom( and dad( and baby)?)?/gi'
RegExp.toString() // 'function RegExp() { [native code] }'

Error类型

Error.toString();//"function Error() { [native code] }"
RangeError.toString();//"function RangeError() { [native code] }"
ReferenceError.toString();//"function ReferenceError() { [native code] }"
SyntaxError.toString();//"function SyntaxError() { [native code] }"
TypeError.toString();//"function TypeError() { [native code] }"
URIError.toString();//"function URIError() { [native code] }"

类型识别

可以使用Object.prototype.toString() 来进行类型识别,返回代表改对象的[ object 数据类型 ] 字符串表示

console.log(Object.prototype.toString.call("jerry")) //[object String]
console.log(Object.prototype.toString.call(12)) //[object Number]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(null)) //[object Null]
console.log(Object.prototype.toString.call({name: "jerry"})) //[object Object]

console.log(Object.prototype.toString.call(function(){})) //[object Function]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(new Date)) //[object Date]
console.log(Object.prototype.toString.call(/\d/)) //[object RegExp]
function Person(){}
console.log(Object.prototype.toString.call(new Person)) //[object Object]
function type(obj){
    return Object.prototype.toString.call(obj).slice(8,-1).toLowerCase();
}
console.log(type("jerry"));//"string"
console.log(type(12));//"number"
console.log(type(true));//"boolean"
console.log(type(undefined));//"undefined"
console.log(type(null));//"null"
console.log(type({name: "jerry"}));//"object"

console.log(type(function(){}));//"function"
console.log(type([]));//"array"
console.log(type(new Date));//"date"
console.log(type(/\d/));//"regexp"
function Person(){};
console.log(type(new Person));//"object"

除了类型识别以外,还可以识别arguments或者DOM元素

(function(){
    console.log(Object.prototype.toString.call(arguments)) //[object Arguments]
})()
console.log(Object.prototype.toString.call(document)) //[object HTMLDocument]

toString()和valueOf()调用顺序

toString()可以看做是把一个数据转换成了相应字符串的形式 valueOf()则是获取指定对象的原值

  1. 在有操作符的情况下:valueOf()的优先级 > toString()

  2. 在使用String(obj)强转字符串时优先使用 toString(),使用Number(obj)强转为数字时,优先使用valueOf()

如果在强转字符传时,没有重写toString方法,但是重写了valueOf方法,此时会优先调用valueOf方法

  1. 在进行对象转换时,优先调用toString方法(两者都没有重写的情况下)

如果没有重写toString(),但是重写了valueOf()则优先调用valueOf()方法