Boolean
一、属性
二、方法
2.1 boolean.toString()
toString()
方法返回表示指定的布尔对象的字符串。
Boolean
对象覆盖了 Object
对象的 toString
方法。并没有继承 Object.prototype.toString()
。对于布尔对象,toString
方法返回一个表示该对象的字符串。
语法
const boolean = new Boolaen(true);
console.log(boolean.toString());
2.2 boolean.valueOf()
valueOf()
方法返回一个Boolean
对象的原始值。
语法
const bool = true;
console.log(bool.toString()); // true
console.log(typeof bool.toString()); // string
console.log(bool.toString() === bool); // false
三、构造函数
3.1 Boolean()
Boolean()
将参数强制转换为 Boolean
类型
!!value
与 Boolean(value)
作用相同,因为它们使用的算法规则相同
语法
const result = Boolean(value)
const result = !!value
规则
-
对于
Boolean
类型: 则总是返回自己const value = true;
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean -
对于
undefined
类型: 返回false
const value = undefined;
console.log(Boolean(value), typeof Boolean(value)); // false boolean
console.log(!!value, typeof !!value); // false boolean -
对于
null
类型: 返回false
const value = null;
console.log(Boolean(value), typeof Boolean(value)); // false boolean
console.log(!!value, typeof !!value); // false boolean -
对于
String
类型:const value = "";
console.log(Boolean(value), typeof Boolean(value)); // false boolean
console.log(!!value, typeof !!value); // false boolean
const value = "aa";
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean -
对于
Number
类型:const value = 1;
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean
const value = 0;
console.log(Boolean(value), typeof Boolean(value)); // false boolean
console.log(!!value, typeof !!value); // false boolean -
对于
Object
类型:const value = {};
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean
过程分析:
1. ToBoolean (Object) , 返回 true -
对于
Array
类型:const value = [];
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean
过程分析:
1. ToBoolean (Array) , 返回 true -
对于
Function
类型:const value = function(){};
console.log(Boolean(value), typeof Boolean(value)); // true boolean
console.log(!!value, typeof !!value); // true boolean
过程分析:
1. ToBoolean (Function) , 返回 true
3.2 new Boolean()
new Boolean(value)
创建一个 Boolean
类型的包装对象
语法
const boolean = new Boolean(true)
console.log(boolean);
返回值
返回一个 Boolean
类型的包装对象, 如下所示:
Boolean {true}
[[Prototype]]: Boolean
[[PrimitiveValue]]: true
四、存储结构
在JavaScript
的第一个版本中,单个值在栈中占据32
位的存储单元。存储单元分为两个部分:一部分是标记位,另一部分是数据。标记位为110
表示Boolean
类型
五、类型检测
5.1、方式一、通过 typeof 检测
console.log(typeof 1); // number
console.log(typeof 1); // string
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof NaN); // number
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof function (){}); // function
5.2、方式二、通过Object.prototype.toString.call()检测
通过slice
function typeOf (x){
return Object.prototype.toString.call(x).slice(8,-1).toLowerCase();
}
console.log(typeOf(1)); // number
console.log(typeOf('1')); // string
console.log(typeOf(true)); // boolean
console.log(typeOf(undefined)); // undefined
console.log(typeOf(null)); // null
console.log(typeOf(NaN)); // number
console.log(typeOf({})); // object
console.log(typeOf([])); // array
console.log(typeOf(function (){})); // function
通过replace
function getType(data) {
return Object.prototype.toString
.call(data)
.replace(/^\[object (.*)\]/, "$1")
.toLowerCase();
}
const num = 3;
console.log(getType(num) === "number");
六、类型转换
6.1 规则
6.2 分类
-
隐式类型转换: 在执行过程中当js内部期望得到某种类型的值,而实际在那里的值是其他的类型,就会发生隐式类型转换。系统内部会自动调用我们前面说
ToBoolean ( argument )
、ToNumber ( argument )
、ToString ( argument )
,尝试转换成期望的数据类型。 -
显示类型转换: 手动调用
Boolean(value)
、Number(value)
、String(value)
完成的类型转换。
6.3 原理
-
ToPrimitive ( input [ , PreferredType ] ):
ToPrimitive
将input
装换为基本数据类型,PreferredType
要么不传,要么是number
、string
。-
PreferredType
为number
:-
如果
input
本身就是原始类型,直接返回input
。 -
调用
input.valueOf()
,如果结果是原始类型,则返回这个结果。-
number.valueOf()
:console.log((1).valueOf(), typeof (1).valueOf()); // 1 number
-
string.valueOf()
:console.log("1".valueOf(), typeof "1".valueOf()); // 1 string
-
boolean.valueOf()
:console.log((true).valueOf(), typeof (true).valueOf()); // true boolean
-
object.valueOf()
:console.log({}.valueOf(), typeof {}.valueOf()); // {} object
console.log({ a: 1 }.valueOf(), typeof { a: 1 }.valueOf()); // { a: 1 } object -
array.valueOf()
:console.log([].valueOf(), typeof [].valueOf()); // [] object
console.log([1, 2].valueOf(), typeof [1, 2].valueOf()); // [ 1, 2 ] object -
function.valueOf()
:console.log(function () {}.valueOf(), typeof function () {}.valueOf()); // [Function (anonymous)] function
-
-
调用
input.toString()
,如果结果是原始类型,则返回这个结果。-
number.toString()
:console.log((1).toString(), typeof (1).toString()); // 1 string
-
string.toString()
:console.log("1".toString(), typeof "1".toString()); // 1 string
-
boolean.toString()
:console.log((true).toString(), typeof (true).toString()); // true string
-
object.toString()
:console.log({}.toString(), typeof {}.toString()); // [object Object] string
console.log({ a: 1 }.toString(), typeof { a: 1 }.toString()); // [object Object] string -
array.toString()
:console.log([].toString(), typeof [].toString()); // "" string
console.log([1, 2].toString(), typeof [1, 2].toString()); // "1,2" string -
function.toString()
:console.log(function () {}.toString(), typeof function () {}.toString()); // "function () {}" string
-
-
抛出
TypeError
异常。
-
-
PreferredType
为string
:-
如果
input
本身就是原始类型,直接返回input
。 -
调用
input.toString()
,如果结果是原始类型,则返回这个结果。-
number.toString()
:console.log((1).toString(), typeof (1).toString()); // 1 string
-
string.toString()
:console.log("1".toString(), typeof "1".toString()); // 1 string
-
boolean.toString()
:console.log((true).toString(), typeof (true).toString()); // true string
-
object.toString()
:console.log({}.toString(), typeof {}.toString()); // [object Object] string
console.log({ a: 1 }.toString(), typeof { a: 1 }.toString()); // [object Object] string -
array.toString()
:console.log([].toString(), typeof [].toString()); // "" string
console.log([1, 2].toString(), typeof [1, 2].toString()); // "1,2" string -
function.toString()
:console.log(function () {}.toString(), typeof function () {}.toString()); // "function () {}" string
-
-
调用
input.valueOf()
,如果结果是原始类型,则返回这个结果。-
number.valueOf()
:console.log((1).valueOf(), typeof (1).valueOf()); // 1 number
-
string.valueOf()
:console.log("1".valueOf(), typeof "1".valueOf()); // 1 string
-
boolean.valueOf()
:console.log((true).valueOf(), typeof (true).valueOf()); // true boolean
-
object.valueOf()
:console.log({}.valueOf(), typeof {}.valueOf()); // {} object
console.log({ a: 1 }.valueOf(), typeof { a: 1 }.valueOf()); // { a: 1 } object -
array.valueOf()
:console.log([].valueOf(), typeof [].valueOf()); // [] object
console.log([1, 2].valueOf(), typeof [1, 2].valueOf()); // [ 1, 2 ] object -
function.valueOf()
:console.log(function () {}.valueOf(), typeof function () {}.valueOf()); // [Function (anonymous)] function
-
-
抛出
TypeError
异常。
-
-
PreferredType
不传入-
如果
input
是内置的Date
类型,PreferredType
视为String
-
否则
PreferredType
视为 ``Number。
-
-
-
ToBoolean ( argument )
Preview -
ToNumber( argument )
Preview -
ToString( argument )
Preview
6.4 问题
-
({}) + 1
的结果? :-
思路:
+
运算符规则如下加法运算符(
+
)为两种不同的运算重载: 数字加法和字符串连接。在求值时,它首先将两个操作数强制转换为基本类型。然后,检查两个操作数的类型:-
如果有一方是字符串,另一方则会被转换为字符串,并且它们连接起来。
-
如果双方都是
BigInt
,则执行BigInt
加法。如果一方是BigInt
而另一方不是,会抛出TypeError
。 -
否则,双方都会被转换为数字,执行数字加法。
-
-
过程:
{}
和1
都会调用ToPrimitive
,1原始类型直接返回{}
内部调用DefaultNumber
,使用valueOf
方法,返回object
- 在调用
toString
方法,返回[object, object]
- 所以最后的结果就是
[object, object]1
-
-
String({a: 1})
的结果?:- 执行转换
String({a: 1})
- 执行内部的
ToString({a: 1})
{a: 1}
不是原始类型,执行ToPrimitive({a: 1}, hint string)
- 调用
toString
方法,返回"[object, object]"
- 执行
ToString("[object, object]")
,返回"[object, object]"
- 执行转换
-
{} + []
的结果?:-
思路:
+
运算符规则如下加法运算符(
+
)为两种不同的运算重载: 数字加法和字符串连接。在求值时,它首先将两个操作数强制转换为基本类型。然后,检查两个操作数的类型:-
如果有一方是字符串,另一方则会被转换为字符串,并且它们连接起来。
-
如果双方都是
BigInt
,则执行BigInt
加法。如果一方是BigInt
而另一方不是,会抛出TypeError
。 -
否则,双方都会被转换为数字,执行数字加法。
-
-
过程:
-
{} + []
==>{}.ToPrimitive({},default) + [].ToPrimitive([],default)
,[].ToPrimitive([],default)
会尝试调用valueOf()
和toString()
转化成基础类型。由+
运算规则可知, 优先调用valueOf()
-
{} + []
===>{}.valueOf() + [].valueOf()
,{}.valueOf()
结果为{}
,[].valueOf()
结果为[]
, 不为基础类型,继续调用toString()
尝试转化 -
{} + []
===>{}.toString() + [].toString()
,{}.toString()
结果为[object Object]
,[].toString()
结果为""
, 所以结果为[object Object]
-
-
[] + []
的结果?-
思路:
+
运算符规则如下加法运算符(
+
)为两种不同的运算重载: 数字加法和字符串连接。在求值时,它首先将两个操作数强制转换为基本类型。然后,检查两个操作数的类型:-
如果有一方是字符串,另一方则会被转换为字符串,并且它们连接起来。
-
如果双方都是
BigInt
,则执行BigInt
加法。如果一方是BigInt
而另一方不是,会抛出TypeError
。 -
否则,双方都会被转换为数字,执行数字加法。
-
-
过程:
-
[] + []
==>[].ToPrimitive([], default) + [].ToPrimitive([], default)
, 其中[].ToPrimitive([], default)
结果不为基础类型,优先调用[].valueOf()
继续尝试转换基础类型 -
[] + []
==>[].valueOf() + [].valueOf()
, 其中[].valueOf()
结果不为基础类型,继续调用[].toString()
继续尝试转换为基础类型 -
[] + []
==>[].toString() + [].toString()
, 其中[].toString()
结果为""
,所以结果为""
-
-
-
6.5 总结
-
{}
转换原始数据的过程:-
{}
转换为String
: 类型转换为String
的时候优先调用toString
,如果结果不是原始数据类型,那么继续调用valueOf()
-
result = ToPrimitive({}, String)
,ToPrimitive
的过程-
对象类型
{}
不为原始类型, 优先尝试调用toString()
-
优先尝试调用
{}.toString()
,{}.toString()
结果为字符串类型 "[object,Object]"
, 为原始类型, 返回"[object,Object]"
-
-
得出
result = "[object Object]"
-
-
{}
转换为Number
: 类型转换为Number
的时候优先调用valueOf
,如果结果不是原始数据类型,那么继续调用toString()
-
result = ToPrimitive({}, Number)
,ToPrimitive
的过程-
对象类型
{}
不为原始类型, 优先尝试调用valueOf()
-
优先尝试调用
{}.valueOf()
,{}.valueOf()
结果为对象类型 {}
, 为对象类型, 继续尝试调用{}.toString()
-
继续尝试调用
{}.toString()
,{}.toString()
字符串类型 "[object,Object]"
, 为原始类型, 返回"[object,Object]"
-
-
得出
result = "[object Object]"
-
-
{}
转换为Boolean
: 同上执行过程
-
-
{ a:1 }
转换原始数据的过程:-
{ a:1 }
转换为String
: 类型转换为String
的时候优先调用toString
,如果结果不是原始数据类型,那么继续调用valueOf()
-
result = ToPrimitive({ a:1 }, String)
,ToPrimitive
的过程-
对象类型
{ a:1 }
不为原始类型, 优先尝试调用toString()
-
优先尝试调用
{ a:1 }.toString()
,{ a:1 }.toString()
结果为字符串类型 "[object,Object]"
, 为原始类型, 返回"[object,Object]"
-
-
得出
result = "[object Object]"
-
{ a:1 }
转换为Number
: 类型转换为Number
的时候优先调用valueOf
,如果结果不是原始数据类型,那么继续调用toString()
-
result = ToPrimitive({ a:1 }, Number)
,ToPrimitive
的过程-
对象类型
{ a:1 }
不为原始类型, 优先尝试调用valueOf()
-
优先尝试调用
{ a:1 }.valueOf()
,{ a:1 }.valueOf()
结果为对象类型 { a:1 }
, 为对象类型, 继续尝试调用{}.toString()
-
继续尝试调用
{ a: 1 }.toString()
,{ a:1 }.toString()
字符串类型 "[object,Object]"
, 为原始类型, 返回"[object,Object]"
-
-
得出
result = "[object Object]"
-
-
{ a:1 }
转换为Boolean
: 同上执行过程
-
-
[]
转换原始数据的过程:-
[]
转换为String
: 类型转换为String
的时候优先调用toString
,如果结果不是原始数据类型,那么继续调用valueOf()
-
result = ToPrimitive([], String)
,ToPrimitive
的过程-
对象类型
[]
不为原始类型, 优先尝试调用toString()
-
优先尝试调用
[].toString()
,[].toString()
结果为字符串类型 ""
, 为原始类型, 返回""
-
-
得出
result = ""
-
[]
转换为Number
: 类型转换为Number
的时候优先调用valueOf
,如果结果不是原始数据类型,那么继续调用toString()
-
result = ToPrimitive([], Number)
,ToPrimitive
的过程-
对象类型
[]
不为原始类型, 优先尝试调用valueOf()
-
优先尝试调用
[].valueOf()
,[].valueOf()
结果为对象类型 []
, 为对象类型, 继续尝试调用[].toString()
-
继续尝试调用
[].toString()
,[].toString()
字符串类型 ""
, 为原始类型, 返回""
-
-
得出
result = ""
-
-
[]
转换为Boolean
: 同上执行过程
-
-
[ 1,2 ]
转换原始数据的过程:-
[ 1,2 ]
转换为String
: 类型转换为String
的时候优先调用toString
,如果结果不是原始数据类型,那么继续调用valueOf()
-
result = ToPrimitive([ 1,2 ], String)
,ToPrimitive
的过程-
对象类型
[ 1,2 ]
不为原始类型, 优先尝试调用toString()
-
优先尝试调用
[ 1,2 ].toString()
,[ 1,2 ].toString()
结果为字符串类型 "1,2"
, 为原始类型, 返回"1,2"
-
-
得出
result = "1,2"
-
[ 1,2 ]
转换为Number
: 类型转换为Number
的时候优先调用valueOf
,如果结果不是原始数据类型,那么继续调用toString()
-
result = ToPrimitive([ 1,2 ], Number)
,ToPrimitive
的过程-
对象类型
[ 1,2 ]
不为原始类型, 优先尝试调用valueOf()
-
优先尝试调用
[ 1,2 ].valueOf()
,[ 1,2 ].valueOf()
结果为对象类型 [ 1,2 ]
, 为对象类型, 继续尝试调用[ 1,2 ].toString()
-
继续尝试调用
[ 1,2 ].toString()
,[ 1,2 ].toString()
字符串类型 "1,2"
, 为原始类型, 返回"1,2"
-
-
得出
result = "1,2"
-
-
[ 1,2 ]
转换为Boolean
: 同上执行过程
-
6.6 方案
-
方案一、通过JSON.parse()转换
背景:
JavaScript
中的字符串"false"
,”false"
经过如下转换结果是为**true
**-
通过
!!
转换为true
const result = !!'false'
console.log(result); // true -
通过
Boolean
转换为true
const result = Boolean('false')
console.log(result); // true
解决: 那么如何快速将字符串的
false
转换为布尔类型的false
? ===> 通过JSON.parse()
console.log(JSON.parse("true"), typeof JSON.parse("true")); // true boolean
console.log(JSON.parse("false"), typeof JSON.parse("false")); // false boolean -
-
方案二、通过操作符隐式类型转换
当使用以下操作符获取
Boolean
结果时,在过程中JavaScript
内部会先进行隐式类型转换,再使用转换后的结果进行对比,最终确定为true
、false
。4 > 3 // 4 > 3 // true
'4' > 3 // Number('4') > 3 // 4 > 3 // true
'a' > 'b' // 'a'.codePointAt() > 'b'.codePointAt() // 97 > 98 // false
true > 2 // Number(true) > 2 // 1 > 2 // false
undefined > 0 // Number(undefined) > 0 // NaN > 0 // false
null > 0 // Number(null) > 0 // NaN > 0 // false
new Date() > 100 // new Date().valueOf() > 100 // 1587608237665 > 100 // true
if (1) { } // Boolean(1) // true
if (!(1 > '10')) { } // !(1 > Number('10')) // !(1 > 10) //!false // true
1 && 2 // 2 // 取最后一个为 true 的值
1 || 2 // 1 // 取第一个为 true 的值 -
方案三、通过操作符显示类型转换
全等操作符在进行对比出
Boolean
结果时不会进行隐式类型转换,为了避免因隐式类型转换带来的预期之外的情况,推荐在实际项目中使用全等操作符来进行对比。'1' == 1 // Number('1') == 1 // 1 == 1 // true
'1' === 1 // false
true != 1 // Number(true) != 1 // 1 != 1 // false
true !== 1 // true -
方案四、通过
!
逻辑非运算符显示类型转换原理: 单个
! 逻辑非运算符
会将变量强制转换为Boolean
值,并进行取反操作。规则
console.log(!"") // true
console.log(!0) // true
console.log(!null) // true
console.log(!"aa") // false
console.log(!undefined) // true
console.log(!NaN) //true
console.log(!null) // true
console.log(!{}) // false
console.log(![]) // false
console.log(!function(){}) // false -
方案五、
!!
双逻辑非运算符显示类型转换原理: 两个
! 逻辑非操作符
,用于将转换的布尔值取反,成为了这个值真正的Boolean
值(作用相当于Boolean()
))规则:
console.log(!!"") // false
console.log(!!0) // false
console.log(!!null) // false
console.log(!!"aa") // true
console.log(!!undefined) // false
console.log(!!NaN) //false
console.log(!!null) // false
console.log(!!{}) // true
console.log(!![]) // true
console.log(!!function(){}) // true
七、包装对象
JavaScript 自动装箱机制
在JavaScript
中,只有引用类型才有属性或者方法,基础数据类型理论上没有属性或者方法。String、Number、Boolean 作为基本数据类型,能够调用一些属性或者方法的原因是: JavaScript 自动装箱机制
为了方便操作基本数据类型, ECMAScript
还提供了三个特殊的引用类型,基本包装类型,String
、Boolean
、Number
。有了这三个类型,在需要的时候,原始类型会自动转换成相应的包装对象(这个过程叫自动装箱)。自动装箱就是临时创建一个包装对象,将原始类型的值封装起来,以便调用包装对象的函数。但是原来那个变量的值不会有任何变化!
以下是介绍手动装箱的方案
7.1 方式一、通过**Object()**创建包装对象
const wrappedBool = Object(true);
console.log(wrappedBool); // Boolean {true}
7.2 方式二、通过**new Boolaen()**创建包装对象
const wrappedBool = new Boolean(true);
console.log(wrappedBool); // Boolean {true}