最近在看winter大大的《重学前端》,收获颇多。在看到Javascript类型的时候看到类型转换地方有个装箱和拆箱操作,好像似成相识的感觉,于是打开了《Javascript高级程序设计》果不其然里面讲到了基本包装类型
装箱操作
每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据,比如我们常进行的字符串操作
var s1 = 'some text';
var s2 = s1.substr(2);
字符串属于基本类型,而基本类型不是对象,理应没有方法存在的,但是事实并不是我们想的这样,它们确实有方法。其实为了让我们实现这种直观的操作,后台已经自动完成了一系列的处理,即装箱操作,具体步骤差不多如下
- 创建String类型的一个实例;
- 在实例上调用指定方法;
- 销毁这个实例; 上面三步用代码表示一下
var s1 = 'some text';
var temp = new String(s1);
var s2 = temp.substr(2);
temp = null;
这样一看我们能调用基本类型方法却不能给基本类型添加属性就很好解释了
var s1 = 'text';
s1.name = 'a';
console.log(s1.name); // undefined
上面代码其实等价于
var s1 = 'text';
var temp = new String(s1);
temp.name = 'a';
temp = null;
console.log(s1.name);
boolean和number也遵循上面的操作原则
Boolean、Number、String这三个构造器是两用的,和new搭配时返回对象,直接调用表示强制类型转换,这应该是很基础的东西了,顺带着提一下
拆箱操作
拆箱操作即对象类型到基本类型的转换,在Javascript标准中有规定ToPrimitive
函数,ToPrimitive 在执行时会传入一个参数hint,hint表示转换的目标类型可选参数string / number / default (未知)
对象转换为String和Number都遵循先拆箱后转换的规则,通过拆箱操作转换为基本类型,在转换为对应的String或者Number,拆箱时候使用Javascript内部函数ToPrimitive
,在ES6中也可以用对象Symbol.toPrimitive方法覆盖默认行为具体步骤如下
- 检查对象是否有定义
Symbol.toPrimitive
方法,如果有直接调用,若没有则调用原生ToPrimitive
- 调用原生
ToPrimitive
判断传入的hint - 如果为string、顺序调用对象的
toString
和valueOf
方法,直到返回原始数据类型为止,若两个方法都没返回原始数据类型,则会报错(TypeError
) - 如果不为string(number/default)则顺序调用对象的
valueOf
和toString
方法,直到返回原始数据类型为止,若两个方法都没返回原始数据类型,则会报错(TypeError
)
原始数据类型:Number、Sring、Undefined、Null、Boolean, 参考链接,Symbol其实也算,但是它并不能在ToPrimitive中使用、查阅了下为啥,然后得到的答案是标准如此?(后期深究)
下面就需要实践一把啦
var a = {
valueOf () {
console.log('valueOf');
return {}
},
toString () {
console.log('toString');
return {}
}
}
console.log(a + 1);
// hint值为default
// valueOf
// toString
// Uncaught TypeError
console.log(a + '');
// hint值为default
// valueOf
// toString
// Uncaught TypeError
console.log(a * 1);
// hint值为number
// valueOf
// toString
// Uncaught TypeError
alert(a)
// hint值为string
// toString
// valueOf
// Uncaught TypeError
valueOf和toString中随便返回一个值,结果则会先用这个返回的值转换为目标类型,再进行运算
var a = {
valueOf(){
console.log('valueOf');
return 1
},
toString(){
console.log('toString');
return '1'
}
}
console.log(a + 1);
// valueOf
// 2
console.log(a * 1);
// valueOf
// 1
alert(a);
// toString
// 1
Symbol.toPrimitive
我们可以指定对象的Symbol.toPrimitive属性,覆盖默认的ToPrimitive方法
var a = {
[Symbol.toPrimitive] (hint) {
console.log(hint);
if (hint === 'string') {
return '1';
} else {
return 1;
}
}
}
console.log(a + 1);
//default
//2
console.log(a * 1);
//number
//1
alert(a)
//string
//1
以上就是我所了解到的装箱拆箱操作啦,如发现问题,欢迎指正哦!