究竟啥是javascript中的装箱操作与拆箱操作

637 阅读3分钟

复习知识点时又一次的一脸懵逼

最近在复习javascript知识点时,又又又忘记了遗忘了一个知识点,还是留下文章来做纪念的好。 当我们转换数据类型时,他们的执行过程因为不同的数据类型,而拥有不同的执行过程,也就是所谓的装箱操作和拆箱操作。一般的解释为,把基本数据类型转换为引用数据类型时,会触发装箱操作。把引用数据类型转换为基本数据类型,会触发拆箱操作。

先来复习数据类型,javascript中的数据类型有Number、String、Boolean、Null、Undefined、Symbol、Biglnt、Object。而我们可以进一步细分为,基本数据类型和引用数据类型。根据MDN的定义来说,除了Object之外都是基本数据类型,特征是值无法被修改,例如:你对一个字符串进行操作,一定是返回给你一个新的字符串,而不是在旧字符串上修改。

引用数据类型 基本数据类型
Object Number
Array String
Date Symbol
RegExp Biglnt
Function Null
Undefined

用内存来区分就是,基本数据类型,存储在内存栈中,修改基本数据类型等于直接修改内存栈。引用数据类型,存储在内存堆中,变量持有内存堆的指针,修改引用类型等于修改内存堆中某一个内存栈的数据。换成人话就是,基本数据类型修改起来会直接给你一个新的女朋友,引用数据类型修改起来只是在旧的女朋友身上点亮技能。

所谓装箱操作,也就是说当基本数据类型转换为引用数据类型时,运行时的表现机制。

装箱操作的具体代码层表现如下:

1: var a = 1;
2: a.x = 2;
3: console.log(a.x); => undefined

运行时步骤2的表现为:

1: var temp = new Number(a);
2: temp.x = 2
3: // 执行流结束,回收temp

运行时步骤3的表现为:

1: var temp = new Number(a);
2: temp.x
3: // 执行流结束,回收temp

首先步骤2和步骤3在执行阶段,创建的运行环境是两个独立的环境,并且在执行完成时都会回收变量,所以导致a.x的值是undefined。也就是基本数据类型是不能添加属性的原因,首先基本数据类型时不可变的,当你试图添加属性时,也会被系统回收你的变量。

所谓拆箱操作,也就是说当引用数据类型转换为基本数据类型时,运行时的表现机制。

拆箱操作的具体代码层表现如下:

1: var num = new Number(4);
2: console.log(num); => 4
3: console.log(num.toString()); => ‘4’
4: console.log(num.valueOf()); => 4

整体观察:

1: 创建变量num,并且赋予new Number(4)
2: 取出num的值
3: 执行toString方法
4: 执行valueOf方法

运行时步骤2、3、4都是一个将引用数据类型转换为基本数据类的过程,拆解步骤2的运行表现如下:

1: var temp = num;
2: temp.valueOf()
3: // 执行流结束,回收temp

这里可以观察到,temp持有的是num的引用,并且调用了Number实例上的valueOf方法,用来返回基本数据类型,最后temp被回收,但是回收的也只是对num的引用,并不会回收num本身。

最后我想说,在我翻阅资料的时候,发现拆箱和装箱操作,跟primitive type function,也就是基础类型方法的概念有一点类似,下次再深入扩展了。


想找我深入py探讨的朋友,可以搜索一下公众号"程序员的vlog"试试呀。(。・ω・。)