除了对象之外,JavaScript有5个原始值类型:布尔值、数字、字符串、null和undefined。
(令人困惑的是, 对null类型进行typeof操作得到的结果为”object”)
我们创建一个String对象,封装一个字符串。
var s = new String("hello");
我们可以进行字符串连接或者提取其索引的子字符串
s + " world"; // "hello world"
s[4]; // "o"
但不同于原始字符串,String对象是一个真正的对象
typeof "hello"; // "string"
typeof s; // "object"
这意味着我们不能够使用内置操作符来比较两个截然不同的string对象内容。
var s1 = new String("hello");
var s2 = new String("hello");
s1 === s2; // false
由于这些封装行为并不十分正确,用处不大。其存在的理由是他们的实用方法。结合另外的隐式转换,JavaScript使得我们可以方便地使用这些实用方法因为这里有另一个隐式转换。例如:
"hello".toUpperCase(); // "HELLO"
toUpperCase方法是String的原型对象方法,我们可以对原始字符串调用这个方法。
这种隐式封装的一个奇怪后果是我们可以对原始值设置属性,但是对其丝毫没有影响。
"hello".someProperty = 17;
"hello".someProperty; // undefined
因为每次隐式封装都会产生一个新的String对象,更新第一个封装对象并不会造成持久的影响。对原始值设置属性的确是没有意义的,但是发现这种行为是值得的。
我们自己来模拟一下隐式封装的过程,例如:
function oString () {
this.text = 'hello';
}
var hello = new oString();
hello .someProperty = 17;
hello .someProperty // 17
var hello = new oString();
hello.someProperty // undefined
事实证明,这是JavaScript隐藏类型错误的又一种情形。
本来想给一个对象设置属性,但没注意其实它是个原始值,程序只是忽略更新而继续运行。这容易导致一些难以发现的错误,并且难以诊断。
提示
- 当做相等比较时, 原始类型的封装对象与其原始值行为不一样。
- 获取和设置原始值类型值的属性会隐性地创建对象。