时间:2021-05-25
前言
在读 Winter 大佬的《重学前端》栏目时,重温了 JS 的「拆箱转换」。「装箱转换」与「拆箱转换」以前都是了解的,今天来看,自己所谓的了解也真是一知半解。在阅读 Winter 老师写的内容后,对「拆箱转换」这个知识点还是不甚清楚,因此我再去深入地了解一番,参考资料详见文末的「参考链接」。
被我们忽略的表象
首先,我们来看一下例子:
const a = { name: 'a', toString () { console.log(this); console.log('toString'); return { name: 'toString' }; }, valueOf () { console.log(this); console.log('valueOf'); return { name: 'valueOf' }; }};a * 2;// {name: "a", toString: ƒ, valueOf: ƒ}// valueOf// {name: "a", toString: ƒ, valueOf: ƒ}// toString// Uncaught TypeError: Cannot convert object to primitive valuea + "";// {name: "a", toString: ƒ, valueOf: ƒ}// valueOf// {name: "a", toString: ƒ, valueOf: ƒ}// toString// Uncaught TypeError: Cannot convert object to primitive alert(a);// {name: "a", toString: ƒ, valueOf: ƒ}// toString// {name: "a", toString: ƒ, valueOf: ƒ}// valueOf// Uncaught TypeError: Cannot convert object to primitive value可以看到,toString 和 valueOf 的执行顺序并不固定,而是根据某个条件来决定的,那么是根据什么呢?那就是在拆箱转换时,调用了对象的 ToPrimitive 内部函数时,其会根据执行上下文,自动传入一个转换类型参数,暂时给它命名为 hint。
ToPrimitive
在 JavaScript 标准中,规定了 ToPrimitive 函数,它是对象类型到基本类型转换的实现者(即,拆箱转换);但这是一个内部算法,是编程语言在内部执行时遵循的一套规则。
对象到 String 和 Number 的转换都遵循“先拆箱再转换”的规则。通过拆箱转换,把对象变成基本类型,再从基本类型转换为对应的 String 或者 Number。
但是对于不同的操作,拆箱转换的内部实现也有所区别,正如上面的例子所示。
「拆箱转换」的调用规则及顺序如下:
来看一下第一种情况:
const b = { [Symbol.toPrimitive] (hint) { console.log(`hint: ${hint}`); return {}; }, toString () { console.log('toString'); return 1; }, valueOf () { console.log('valueOf'); return 2; }};alert(b); // hint: string b + ''; // hint: defaultb + 500; // hint: default+b; // hint: numberb * 1; // hint: number第二、三种情况:
const c = { toString () { console.log('toString'); return 1; }, valueOf () { console.log('valueOf'); return 2; }};alert(c); // 打印出 toString 并 alert 出 1c + ''; // 先后打印出 valueOf,"2"c + 500; // 先后打印出 valueOf,502+c; // 先后打印出 valueOf,2c * 1; // 先后打印出 valueOf,2那么关于 hint 可取的三种值,都有什么含义?又什么情况对应什么值?
确定 hint 取值
string
当在希望是字符串操作,也即发生对象到字符串的转换时,传入内部函数 ToPrimitive 的参数值即为 string:
// outputalert(obj);// using object as a property keyanotherObj[obj] = 123;number
当在希望是数值操作,也即发生对象到数值的转换时,传入内部函数 ToPrimitive 的参数值即为 number:
// explicit conversionlet num = Number(obj);// maths (except binary plus)let n = +obj; // unary pluslet delta = date1 - date2;// less/greater comparisonlet greater = user1 > user2;default
当在一些不确定需要将对象转换成什么基础类型的场景下,传入内部函数 ToPrimitive 的参数值即为 default:
// binary pluslet total = car1 + car2;// obj == string/number/symbolif (user == 1) { ... };结语
如果亲爱的读者们在本文中发现了什么错误,或者有什么不同的意见,还请留言,一起讨论,一起将隐藏的、晦涩的点提出来,然后解决掉。
参考链接
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
首先看一看什么是装箱和拆箱?简单的来说:装箱就是值类型转换为引用类型;拆箱就是引用类型转换为值类型。值类型,包括原类型(Sbyte、Byte、Short、Ush
装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。1.装箱在值类型向引用类型转换时发生2.拆箱在引用类型向值类型转换时发生光上述两句话不难理解,但是往深处
本文以一个简单实例讲述了C#装箱和拆箱操作的实现方法,简单来说装箱是将值类型转换为引用类型;拆箱是将引用类型转换为值类型,是涉及栈和堆的使用方面的东西,学过C#
疑问都知道C#有装箱和拆箱的操作,听闻也都是讲int类型转换成object类型就是装箱,将object类型再转回int类型就是拆箱。描述的通俗点:装箱将值类型转
本文实例讲述了C#中简单的拆箱操作用法。分享给大家供大家参考。具体如下:C#中拆箱是允许将引用作为值类型的进行处理的过程。下面这段代码实现将object转换成i