概念
JavaScript 的类型分为两种:原始数据类型(Primitive data types)和对象类型(Object types)。
原始数据类型包括:布尔值、数值、字符串、null、undefined 以及 ES6 中的新类型 Symbol,在这里我们需要记住一点:所有的原始数据类型都没有属性(property)。
如上所述,在 JavaScript 中字符串被视为原始数据类型而不是对象类型,但是我们来看下面一段代码。
let text='hello';
console.log(text.toUpperCase()); // HELLO
这里很明显可以看出 text 有一个 toUpperCase 的属性(property)。那么是否上述结论不正确呢?如果 text 不是对象类型,为什么它具有 toUpperCase,toLowerCase 等属性呢?
先来一个简单的结论:JavaScript 会在原始数据类型和对象类型之间做一个迅速的强制性切换。
针对上述代码的详细解释就是:当我们试图访问 text 的 toUpperCase 属性时,JavaScript 会通过 new String(text) 来强制将字符串的值转换为一个对象类型,这个对象就是包装对象(wrapper object)。
它继承了 string 的所有方法,并且被用于获取其属性(property)上的引用(reference)。一旦属性被调用后,这个包装对象就会被废弃。
所以上述代码可以理解为实际是执行了如下操作:
let text = (new String('hello')).toUpperCase();
TypeScript 中类型声明时需要关注的包装对象问题
在之前的学习中,我们已经知道 TypeScript 拥有强大的类型系统,但是在赋值的时候,我们要注意如下问题。
let isDoing: boolean = true; // 编译通过
let isTesting: boolean = Boolean(1) // 编译通过
let isDone: boolean = new Boolean(1); // 编译失败
第三行代码会编译出错,这是为什么呢?有了上面提到的包装对象概念,相信大家也就能理解了,因为通过 new Boolean() 生成的值实际上是一个包装对象,并非原始数据类型。此处我们期望的 isDone 是一个原始数据类型,所以 TypeScript 会编译失败。
数值和字符串的赋值与上述代情况类似,就不再赘述。