ifeees / articles

“前端晚自修”公众号文章备份
3 stars 0 forks source link

了解一下,JavaScript中的自动装箱和自动拆箱。 #15

Open Yatoo2018 opened 6 years ago

Yatoo2018 commented 6 years ago

先来一个例子,看看什么是自动装箱和自动拆箱:

var num = 4; 
num.toString();

控制台看看效果: image

我们用上面例子感受了一下这个自动装箱和自动拆箱,有人可能会问,哪里有装箱?

更清晰的案例

对于常年接触js的人可能有人看了上面的例子,觉得在正常不过了;
不过对于常年接触OOP语言(比如Java或者重度TypeScript)的同学感受就不一样了,num是一个数值类型,为什么可以像对象一样调用方法,难道num是一个对象?

上述例子如果不够明显,我再来一个例子:

4..toString()

image

这个例子非常清晰了,一个数值竟然可以调用方法,还能正常返回结果,客官,是不是有点意思了。

注意

  1. 这里用了俩个点调用方法,不是什么黑科技,就是在JavaScript中所有的数值都是浮点型,所以引擎在解析数值类型数据时,从左边第一个点会当成小数点来处理,第二个点才是属性访问符
  2. 4.转换为string之后返回了4而不是4.0, 这是因为,在JavaScript中,整数要比浮点数存在许多优点,比如,节省空间,进行运算更加准确等,所以引擎遇到这种可以转换为整数的浮点数都会转换为整数存储。

解析原理

  1. 当然是基本类型值。而下一行调用了 4. 的toString() 方法。我们知道,基本类型值不是对象,因而从逻辑上讲它们不应该有方法。其实,为了让我们实现这种直观的操作,JavaScript解析器后台已经自动完成了一系列的处理。当第二行代码访问 4. 时,访问过程处于一种读取模式,也就是要从内存中读取这个数值。而在读取模式中,后台都会自动完成下列处理。

(1) 创建 Number 类型的一个实例;(装箱过程,后台操作,对开发不可见) (2) 在实例上调用指定的toString方法;(方法调用,开发指定的方法调用) (3) 销毁这个实例。(自动拆箱,后台操作,对开发不可见)

经过此番处理,基本的数值就变得跟对象一样了。而且,上面这三个步骤也分别适用于 Boolean 和 String 类型对应的布尔值和数字值。

规范中的说明

属性访问规范 https://www.ecma-international.org/ecma-262/9.0/index.html#sec-property-accessors-runtime-semantics-evaluation

我们使用的是.访问符 image

其中使用到的requireobjectcoercible方法 https://www.ecma-international.org/ecma-262/9.0/index.html#sec-requireobjectcoercible

image

其中又使用了toobject https://www.ecma-international.org/ecma-262/9.0/index.html#sec-toobject

image

至此,可以看到,调用方法的初始值被转换为一个包含原始值的对象。

自动装箱和自动拆箱原来一点也不神秘,就是利用ToObject方法返回一个对应初始值类型的包装对象,通过包装对象来访问方法

你get到了吗?

Junting-Liu commented 5 years ago

你好。「整数要比浮点数存在许多优点,比如,节省空间」,对这句话有些疑问。整数和小数都是双精度浮点,为什么会节省内存? https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Numbers_and_dates

EmiyaYang commented 4 years ago

写测试用例的时候惊到了。传参 false 竟然提示 false.split() is not a function...,然后就搜装箱这玩意儿跑这来了。