Javascript Boolean对象与布尔值之间的差异
我们都知道javascript中一些基本类型(boolean,string,number)都有自己的构造函数,我们称之为基本包装类型,但是基本包装类型和基本类型不是一回事。
以boolean类型为例,在大多数代码中,我们使用boolean值像这样:
var primitiveTrue = true;
var primitiveFalse = false;
当然,还有Boolean函数,它可以被用作一个布尔函数,它返回一个布尔值。
var functionTrue = Boolean(true);
var functionFalse = Boolean(false);
同时Boolean函数也可以被用作一个构造函数,使用new关键字:
var constructorTrue = new Boolean(true);
var constructorFalse = new Boolean(false);
奇怪是是Boolean被用作一个构造函数时,它返回的不是一个boolean值,而是一个对象:
// Outputs: true
console.log(primitiveTrue);
// Outputs: true
console.log(functionTrue);
// Outputs: Boolean {}
console.log(constructorTrue);
//Outputs boolean
console.log(typeof primitiveTrue);
// Outputs: object
console.log(typeof constructorTrue);
事实证明,使用布尔构造函数是相当危险的。为什么呢?JavaScript有关强制类型转换是想当激进的。如果您尝试把一个字符串和一个数字相加,这个数字将被强制转换为字符串。
// Outputs: "22"
console.log("2" + 2);
同样,如果您在if语句中尝试使用一个对象,对象将被强制转换为true。
// Outputs: "Objects coerce to true."
if ({}) { console.log("Objects coerce to true."); }
而且,由于Boolean对象是一个对象,它也将强制为true,即使它的值是false。
// Outputs: "My false Boolean object is truthy!"
if (constructorFalse) {
console.log("My false Boolean object is truthy!");
} else {
console.log("My false Boolean object is falsy!");
}
那么我们确实需要布尔值的时候该怎么办呢?我们可以使用valueOf()方法:
// Outputs: "The value of my false Boolean object is falsy!"
if (constructorFalse.valueOf()) {
console.log("The value of my false Boolean object is truthy!");
} else {
console.log("The value of my false Boolean object is falsy!");
}
由于存在这样的现象,所以我们平时定义boolean、number、string值时,建议使用字面量的形式定义。同时在一些代码检测工具(jshint/jsLint)中,使用构造函数初始化时,会报错。
最后在你强制转换一种类型为boolean类型的时候,建议使用Boolean作为一个普通函数,或者进行两次取非操作。
// Two approaches to coercing 0 into false
var byFunction = Boolean(0);
var byNotNot = !!0;
最后给大家留一个问题:
基本包装类型和引用类型有什么区别?