valueOf,toString,Symbol.toPrimitive

1,106 阅读3分钟

前言:前面我们过了类型的转换,但都只是关于原始类型之间的相互转换。并没有说到对象的类型转换,这篇文章我们来了解下对象是如何进行类型转换地 。

1.JavaScript各个对象中valueOf与toString来源

JavaScript中一切皆对象,只要你了解过原型链就会知道任何一个对象的原始链的顶层指向Object.prototype,而Object中就存在valueOf和toString 方法,对于一切继承Object的对象,就将会继承了Object中的方法。对于继承的valueOf与toString 都可以被重写,而JavaScript 对于不同对象之间的valueOf与toString也可能不同。

2.valueOf 与 toString 转换规则

valueOf: 返回指定对象的原始值。

如下为给对象调用valueOf返回值的情况

例:

// Number
let num = new Number(10);
console.log(typeof num);         // object
console.log(num.valueOf());      // 10

// String 
let str = new String("hello");
console.log(typeof str)          // object
console.log(str.valueOf())       // "hello"

// Boolean 
let bool = new Boolean()
console.log(typeof bool)        // object
console.log(bool.valueOf())     //  false

// Array 
let arr = [1,2,5]
console.log(typeof arr)        // object
console.log(arr.valueOf())     // [1,2,5]

// Object 
let user = {
       name: "Jason",
        age: 24
    }
    console.log(typeof user)     // object
    console.log(user.valueOf())  // {name: "Jason",age: 24}

//Date
let now = new Date()
console.log(typeof now)          // object
console.log(now.valueOf())       // 1600001038411

// Function
function fun(){
    return 10;
}
console.log(typeof fun)        // function 
console.log(fun.valueOf())     // fun(){return 10;}

toString: 返回表示该对象的字符串。

如下为给对象调用toString返回值的情况

例:

// Number
let num = new Number(10);
console.log(typeof num);         // object
console.log(num.toString());      // '10'

// String 
let str = new String("hello");
console.log(typeof str)          // object
console.log(str.toString())       // "hello"

// Boolean 
let bool = new Boolean()
console.log(typeof bool)        // object
console.log(bool.toString())     //  'false'

// Array 
let arr = [1,2,5]
console.log(typeof arr)        // object
console.log(arr.toString())     // '1,2,5'

// Object 
let user = {
       name: "Jason",
        age: 24
    }
    console.log(typeof user)     // object
    console.log(user.toString())  //"[object, Object]"

//Date
let now = new Date()
console.log(typeof now)          // object
console.log(now.toString())       //"Sun Sep 13 2020 20:43:58 GMT+0800 (中国标准时间)"

// Function
function fun(){
    return 10;
}
console.log(typeof fun)        // function 
console.log(fun.toString())     // 'fun(){return 10;}'

注:function 函数隶属于Object, 更本不存在function类型,JavaScript只是为了编程方便而对函数区分对待。

3.valueOf与toString类型转换如何调用。

所有的对象在布尔上下文(context)中均为 true。所以对象不存在 to-boolean 转换,只有向字符串和数字的转换,对于对象来说不管是强行转换还是自动转换,JavaScript 会隐式调用valueOf和toString方法。

4.valueof与toString 的优先级

1.在不重写方法的情况下

  • to-Number转换为Number 类型时调用 valueOf 方法
  • to-String 转换为String 类型时调用 toString 方法

2.在toString 方法重写的情况下

  • to-Number转换为Number 类型时调用 toString 方法
  • to-String 转换为String 类型时调用 toString 方法

3.两个方法都重写的情况下

  • to-Number转换为Number 类型时调用 valueOf 方法
  • to-String 转换为String 类型时调用 toString 方法

4.在valueOf方法重写的情况下

  • to-Number转换为Number 类型时调用 valueOf 方法
  • to-String 转换为String 类型时调用 toString 方法

总结: 只要是toString方法不重写 在to-Number时调用valueOf,to-String调用toString,反之将优先会调用toString方法。

例:

let num = new Number(10);
// to-number
console.log(Number(num))    // 10
console.log(+num)           // 10

// to-string
console.log(String(num))    // "10"

分析: valueOf返回的是原始值,toString返回的是对象的字符串

             1.to-number 时调用valueOf 返回 10

             2.to-string  时调用toString 返回 '10'

5.alert函数

在JavaScrpit中经常会用到alert 函数,该函数在执行是会去调用toString函数将函数中要显示的值或者对象进行转换。转换根据toString函数转换规则。

alert({})            //  "[object Object]"
alert(1)             //  "1"
alert([2,4,6])       //  "2,4,6"

6.Symbol.toPrimitive

Symbol.toPrimitive是一个内置的 Symbol 值,它是作为对象的函数值属性存在的,如果对象中存在个属性时,当一个对象转换为对应的原始值时,会优先调用此函数。

let user = {
    name: 'Jason',
    age: 24,
    [symbol.toPrimitive](hint){
        if(hint === 'string') return this.name;
        eles if(hint === 'number')  return this.age;
    } 
}

//测试
console.log(String(user))     // hint: string  打印 "Jason"
console.log(Number(user))     // hint: numbber 打印  24

分析: 对于Symbol.toPrimitive被调用时,将会传如转换的类型,我们可以针对转换的类型自定义我们想让它转换成的类型或值。hint 为指定转换的类型名。

注: Symbol.toPrimitive存在时优先调用,不存在时才去调用valueOf与toString方法。