js 装箱与拆箱

71 阅读2分钟

基本数据类型与引用类型转化原理。

一 基本概念

js 中有三种包装对象:String、Number、Object。

装箱:把基本数据类型转化为引用数据类型的操作。

拆箱:将引用类型对象转化为基本数据类型对象。

二 装箱

var str = 'aa' // 字面量形式
var strObject = new String('aa'); // 构造函数形式

typeof(str) // string
typeof(strObject) // object

字面量如何拥有构造函数才有的方法,但我们调用 str.split('') ,js 内部做了以下操作:

var str = new String('aa'); // 1 创建构造函数实列
var str2 = str.split(''); // 2 通过实例调用方法
str = null; // 3 销毁实例
return str2; // 4 返回值

三 拆箱

js 有个内部方法 toPrimitiv(input, type) , 大致流程如下:

1 判断输入值 input 是否是基本类型的值,如果是,直接返回
2 如果不是,判断 input.valueOf() 的值是否有基本类型,如果有,返回 input.valueOf();如果没有,返回对象本身,继续下面步骤。
3 执行 input.toString() ,将 input 转成字符串,如果是对象返回的是 '[object Object]'、'[object Array]'、'[object String]' 等。

案列:

[] + []	// ""
{} + {}	// "[object Object][object Object]"
[] + {}	// "[object Object]"
{} + []	// 0 或 "[object Object]"(不同浏览器结果有差异)

分析:

(1)[] + [] , [] 自身是一个空数组,即是一个对象,[] 会先被 valueOf() 检测返回自身,还是 [] , 然后使用 toString() 检测返回空字符 "",实际最终是 "" + "",所以最终结果还是一个 ""。

(2){} + {},在 js 中 {} 可以表示一个代码块,也可以表示一个对象。在此处作为一个对象来运算,({}).valueOf() 检测结果为自身,继续检测,({}).toString() 检测结果为 "[object Object]",所以 {} + {} 相当于 "[object Object]" + "[object Object]",故结果为 "[object Object][object Object]" 。

(3)[] + {} ,从上面分析可以知道,这个相当于 "" + "[object Object]",所以结果为 "[object Object]" 。

(4){} + [],上面三个或许大多数人都能明白,但这个估计就会有人有疑问了,为什么会是 0 呢?首先,这里的 {} 被当做了代码块,由于编译原理底层一些机制,会涉及到词法分析、语法分析、语义分析、代码生成这些知识,这里 +[] 相当于 +"",因为运算符 + 的原因,会将 +"" 隐式转换为 +0 ,所以结果最终为 0。


[参考]:blog.csdn.net/DLGDark/art…