一个小测试, 试试:

let o = {valueOf() {return 0;},
};
console.log(+o); // 0
console.log(1 + o); // 1
console.log(1 - o); // 1
console.log('' + o); // '0'
console.log(`${o}`); // '[object Object]'

结论

  1. 当操作需要一个字符串时, hint=string, 当操作需要一个数字时, hint=number, 当运算符不确定时hint=default.
  2. 如果存在 obj[Symbol.toPrimitive](hint), 就直接调用
  3. 如果 hintstring, 先调用 obj.toString(), 没有再调用 obj.valueOf()
  4. 如果 hintnumber, 先调用 obj.valueOf(), 没有再调用obj.toString()
  5. 如果 hintdefault, Date 按照 hint=string处理, 其它按照 hint=number 处理
  6. 如果 toString 或者 valueOf 返回的不是原始类型, 则忽略该调用, 转向下一个调用, 如果没有下一个调用, 则报错, 但是 toPrimitive 必须返回原始类型, 否则报错

详解

根据上下文, 会有以下转换 hint

string

当操作需要一个字符串时, 对象转换的 hintstring.

// alert(参数是字符串)
alert(obj);
confirm(obj);// 对象的属性是字符串
anotherObj[obj] = 123;

number

当操作需要一个数字时, 对象转换的 hintnumber.

// 明确转换成数字
Number(obj);
// 转换成数字(非加法)
+obj;
// 数学运算(加法除外)
1 - obj;
1 * obj;
1 / obj;

因为历史原因大小比较的 hint 也是 number

// hint 为 number
obj1 > obj2;

default

当运算符不确定时, 对象转换的 hintdefault.

// 比如加法, 可以是数字相加, 也可以是字符串相加
1 + obj;
'1' + obj;// == 弱相等比较
// obj == string/number/symbol
obj == '1';
obj == 1;

通常, 内置对象(除了 Date 外), default 转换 和 number 转换是相同的
Date 的 default 转换 和 string 相同 [Date.prototype[@@toPrimitive]](https://developer.mozilla.org...

转换步骤

  1. 如果存在 obj[Symbol.toPrimitive](hint), 就直接调用
  2. 如果 hintstring, 先调用 obj.toString(), 没有再调用 obj.valueOf()
  3. 如果 hintnumber, 先抵用 obj.valueOf(), 没有再调用obj.toString()

example

Symbol.toPrimitive

type primitiveType = null | undefined | number | boolean | string | symbol;
type hintType = 'string' | 'number' | 'default';obj[Symbol.toPrimitive] = function(hint: hintType): primitiveType {console.log(`hint is: ${hint}`);return hint == 'string' ? '一个字符串' : 0;
};

toString / valueOf

let user = {name: 'John',money: 1000,// for hint="string"toString(): string {return `{name: "${this.name}"}`;},// for hint="number" or "default"valueOf(): number {return this.money;},
};alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500
let obj = {toString() {return '2';},
};// 加法, 调用 `default` hint, `default` 和 `number` 转换相同,
// 先调用 valueOf 方法, 因为不存在, 所以调用 toString 方法, 返回 "2"
// "2" + 2 = "22"
alert(obj + 2); // "22"// 存在 valueOf, 所以 2+2 = 4
let obj = {toString() {return '2';},valueOf() {return 2;},
};alert(obj + 2); // 4
let d = new Date();
let d2 = d.getTime() - 1;// 加法, 调用 `default` hint, Date 的 `default` 和 `string` 相同
alert(1 + d); // 1Fri Feb 15 2019 20:59:00 GMT+0800 (China Standard Time)// 减法, 调用 `number` hint
alert(d - d2); // 1

参考文档

  • https://javascript.info/object-toprimitive
  • [Date.prototype[@@toPrimitive]](https://developer.mozilla.org...

文章若有纰漏请大家补充指正,谢谢~~
http://blog.xinshangshangxin.com SHANG 殇

[对象转原始类型总结] ('' + obj) === `${obj}`? 不一定!相关推荐

  1. 【前端2】js:原始类型,运算符,调试,页面加载,轮播图,Bom(对象,时钟),Dom(全选全不选,省市级联,隔行/触摸换色,表单校验)

    文章目录 1.js两种引入:js最终要引入到html在浏览器中运行 2.js五大原始类型:undefined 3.js的运算符和流程控制:js不支持单&和单|性能低 4.案例_99乘法表:So ...

  2. 理解JavaScript的原始类型

    2019独角兽企业重金招聘Python工程师标准>>> JavaScript中的原始类型(primitive type)包括Undefined.Null.Number.Boolean ...

  3. java解包_Java的原始类型自动包装与解包机制

    java5之后对原始数据类型如int.char.long等基本数据类型有自动打包成相应的复合类型Integer.Character.Long等的机制:也可以将复合类型自动转换为原始类型. 这取决于程序 ...

  4. java在何时获得对象的确切类型_JAVA面试题(1)

    基础部分 面向对象 1.谈谈你对多态的理解. 答:在java中对于多态的理解是很重要的 多态的定义: 允许不同类的对象对同一消息做出相应,同一消息可以根据发送对象的不同而采用多种不同的行为方式,(发送 ...

  5. 《JavaScript高级程序设计》阅读笔记(二):ECMAScript中的原始类型

    2.6 原始类型 ECMAScript有5种原始类型(primitive type),即Undefined.Null.Boolean.Number和String.ECMAScript提供了typeof ...

  6. 《JavaScript面向对象精要》——第1章 原始类型和引用类型1.1 什么是类型

    本节书摘来自异步社区<JavaScript面向对象精要>一书中的第1章,第1.1节,作者:[美]Nicholas C. Zakas 译者: 胡世杰 更多章节内容可以访问云栖社区" ...

  7. 如何区分引用类型和原始类型

    下表列出了原始类型以及它们的对象封装类. 原始类型和封装类 原始类型 封装类 boolean Boolean char Character byte Byte short Short int Inte ...

  8. ECMAScript 基础--原始类型

    ECMAScript 有 5 种原始类型(primitive type),即 Undefined.Null.Boolean.Number 和 String. typeof 运算符 对变量或值调用 ty ...

  9. c# 变量,对象,静态类型,集合类的线程安全回顾

    1.变量的线程安全性与变量的作用域有关. 2.对象 对象是类型的实例 在创建对象时,会单独有内存区域存储对象的属性和方法.所以,一个类型的多个实例,在执行时,只要没有静态变量的参与,应该都是线程安全的 ...

最新文章

  1. Node.js模块化开发||Node.js中模块化开发规范
  2. 【Pytorch神经网络理论篇】 03 Pytorch快速上手(三)张量的数据操作
  3. freemaker中小数展示为整数的问题
  4. git 初始化git存储库_什么不保存到Git存储库中
  5. 随机组卷功能,你值得拥有~~~
  6. mysql infobright 缺点_Infobright存储引擎的特点
  7. mysql 部署最佳实践_MySQL安装脚本最佳实践
  8. ios safari 模拟器_Safari调试iOS应用
  9. C++学习笔记:实现向量类的加减赋值运算,重载运算符
  10. 最优秀的6410开发板全球震撼首发!
  11. RTSP安防网络摄像头/海康大华硬盘录像机/NVR网页无插件低延时播放流媒体服务器EasyNVR页面显示网络请求失败问题
  12. 入职快手半年工作小结
  13. 贪吃蛇小程序·C/C++
  14. 简体中文转换繁体中文
  15. 夺神之权服务器维护,流放之路3月28日夺神之权停服更新详解
  16. 使用JDBC完成数据的增加
  17. zxing生成二维码去白边
  18. 药房药品管理信息系统
  19. 理化试验室计算机维护保养,实验室常用仪器的维护保养
  20. 亚马逊平台在哪个站点开店好

热门文章

  1. nand flash和nor flash区别_从闪存的发展历史看,eMMC与NAND Flash有什么区别与联系?...
  2. linux 路由跟踪命令_一文掌握linux系统路由跟踪指令traceroute
  3. cesium加载 gltf模型
  4. oracle替换指定字符串字符_实例:替换方框内字符串内容
  5. python定义test方法_关于python:使用pytest测试类方法
  6. vscode 不支持的客户端_Windows平台上有哪些你不知道的神器?
  7. 视频抽帧并存图 python_使用Python实现跳帧截取视频帧
  8. 若依微服务部署遇到问题
  9. 2016考试计算机知识基础题库,2016年计算机二级公共基础知识基础练习题演练(6)...
  10. python后端程序例子_Python MR程序示例