别再混淆了!JS类型转换底层:valueOf vs toString vs Symbol.toPrimitive 详解

js获取对象值的方法有三种valueOf()toString()symbol.toPrimitive这些其实是类型转换的问题;三种方式本质上略微不同;

我们知道在js中,'一切皆为对象'。每个对象都有一个toString()方法和valueOf方法,其中toString()方法返回一个表示该对象的字符串,valueOf 方法返回该对象的原始值。

一、valueOf() 与 toString()

基本类型的情况下:

javascript 复制代码
const str = "hello",n = 123,bool = true;
console.log(typeof(str.toString()) + "_" + str.toString())        //string_hello
console.log(typeof(n.toString()) + "_" + n.toString()  )            //string_123
console.log(typeof(bool.toString()) + "_" + bool.toString())        //string_true

console.log(typeof(str.valueOf()) + "_" + str.valueOf())            //string_hello
console.log(typeof(n.valueOf()) + "_" + n.valueOf())                //number_123
console.log(typeof(bool.valueOf()) + "_" + bool.valueOf())          //boolean_true

// valueOf
console.log(str.valueOf() === str)  // true
console.log(n.valueOf() === n) // true
console.log(bool.valueOf() === bool) // true
// toString
console.log(str.toString() === str) // true
console.log(n.toString() === n)     // false
console.log(bool.toString() === bool) // false

toString 方法对于值类型数据使用而言,其效果相当于类型转换,将原类型转为字符串。

valueOf 方法对于值类型数据使用而言,其效果将相当于返回原数据。 引用类型的情况下:

javascript 复制代码
var obj = {};

console.log(obj.toString());    //[object Object] 返回对象类型
console.log(obj.valueOf());     //{} 返回对象本身

综合例子:

javascript 复制代码
let test = { 
    i: 10, 
    toString: function() {
       console.log('toString');
       return this.i; 
    }, 
    valueOf: function() { 
       console.log('valueOf');
       return this.i; 
    }
} 
console.log(test);          // { I:10, toString: f, valueOf: f }
console.log(+test);         // 10 valueOf
console.log('' + test);       // 10 valueOf
console.log(String(test));  // 10 toString
console.log(Number(test));  // 10 valueOf
console.log(test == '10');  // true valueOf
console.log(test == '10');  // true valueOf
console.log(test === '10'); // false

个人理解:

带有运算符的获取值的方式都会走valueOf()方法;强转字符串的时候走toString()方法;

二、toString() 和 String()

  • toString()
    • toString()可以将所有的数据都转换为字符串,但是要排除nullundefined
    • nullundefined不能转换为字符串,nullundefined调用toString()方法会报错
    • 如果当前数据为数字类型,则toString()括号中的可以写一个数字,代表进制,可以将数字转化为对应进制字符串。
JavaScript 复制代码
var num = 123;
console.log(num.toString()+'_'+ typeof(num.toString()));    //123_string
console.log(num.toString(2)+'_'+typeof(num.toString()));    //1111011_string
console.log(num.toString(8)+'_'+typeof(num.toString()));    //173_string
console.log(num.toString(16)+'_'+typeof(num.toString()));   //7b_string
  • String()
    String()可以将nullundefined转换为字符串,但是没法转进制字符串。

三、Symbol.toPrimitive

对象的Symbol.toPrimitive属性。指向一个方法。该对象被转化为原始类型的值时,会调用这个办法,返回该对象对应的原始类型值。 Symbol.toPrimitive被调用时,会接受一个字符串参数,表示当前运算的模式,一个有三种模式。

  • Number: 该场合需要转成数值
  • String: 该场合需要转成字符串
  • Default: 该场合可以转成数值,也可以转成字符串。

Symbol.toPrimitive在类型转换方面,优先级是最高的

JavaScript 复制代码
const test = { 
	i: 10, 
	toString: function() {
	   console.log('toString');
	  return this.i; 
	}, 
	valueOf: function() { 
	   console.log('valueOf');
	   return this.i; 
	},
    [Symbol.toPrimitive](hint) {
        if(hint === 'number'){
          console.log('Number场景');
          return 123;
        }
        if(hint === 'string'){
          console.log('String场景');
          return 'str';
        }
        if(hint === 'default'){
          console.log('Default 场景');
          return 'default';
        }
    }
}

console.log(test);          // { i:10, toString: f, valueOf: f, Symbol(Symbol.toPrimitive): f }
console.log(+test);         // 123 Number场景
console.log(''+test);       // default Default 场景
console.log(String(test));  // str String场景
console.log(Number(test));  // 123 Number场景
console.log(test == '10');  // false default场景
console.log(test === '10'); // false

上面代码中、+test中的加号命名为一元加号+test本质就是转成数值的意思;

Tips

javascript 复制代码
console.log(3 + test);  // 3default Default 场景
console.log(3 - test);  // -120 Number场景
console.log(3 * test);  // 369 Number场景
console.log(3 / test);  // 0.0243902 Number场景

以上的代码中,加减乘除都算运算符,本应都应该走Number场景,但是唯独+号走了Default场景

四、一元加号

一元加号运算符 + 在其操作数之前,并计算其操作数;但如果尚未将其转换为数字,则尝试将其转换为数字

JavaScript 复制代码
console.log(+'')  // 0
console.log(+true)  // 1
console.log(+false)  // 0
console.log(+'hello')  // NaN

console.log(1 + +"2" + "2")  // 32

一元加法是将某事物转换为数字的最快和首选方法,因为它不对数字执行任何其他操作。

如果它无法解析特定值,它将输出为 NaN

感谢您抽出宝贵的时间观看本文;本文是JavaScript系列的第 6 篇,后续会持续更新,欢迎关注~

相关推荐
发现一只大呆瓜2 小时前
深度解密 Rollup 插件开发:核心钩子函数全生命周期图鉴
前端·vite
java_nn2 小时前
一文了解前端技术
前端
发现一只大呆瓜2 小时前
深度解析 Rollup 配置与 Vite 生产构建流程
前端·vite
小码哥_常3 小时前
安卓黑科技:让手机成为你的“跌倒保镖”
前端
小李子呢02113 小时前
前端八股Vue---Vue2和Vue3的区别,set up的用法
前端·javascript·vue.js
m0_647057964 小时前
Harness Engineering 实践指南
前端
邂逅星河浪漫4 小时前
【银行内网开发-管理端】Vue管理端+Auth后台开发+Nginx配置+Linux部署(详细解析)
linux·javascript·css·vue.js·nginx·html·前后端联调
JJay.4 小时前
Android BLE 稳定连接的关键,不是扫描,而是 GATT 操作队列
android·服务器·前端
星空椰4 小时前
JavaScript 进阶基础:函数、作用域与常用技巧总结
开发语言·前端·javascript
奔跑的呱呱牛4 小时前
@giszhc/vue-page-motion:Vue3 路由动画怎么做才“丝滑”?(附在线示例)
前端·javascript·vue.js