跳到主要内容

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 类型

注意

!!valueBoolean(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 规则

Preview

6.2 分类

  • 隐式类型转换: 在执行过程中当js内部期望得到某种类型的值,而实际在那里的值是其他的类型,就会发生隐式类型转换。系统内部会自动调用我们前面说ToBoolean ( argument )ToNumber ( argument )ToString ( argument ),尝试转换成期望的数据类型。

  • 显示类型转换: 手动调用Boolean(value)Number(value)String(value)完成的类型转换。

6.3 原理

  • ToPrimitive ( input [ , PreferredType ] ): ToPrimitiveinput装换为基本数据类型,PreferredType要么不传,要么是numberstring

    • PreferredTypenumber:

      • 如果 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 异常。

    • PreferredTypestring:

      • 如果 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内部会先进行隐式类型转换,再使用转换后的结果进行对比,最终确定为 truefalse

    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中,只有引用类型才有属性或者方法,基础数据类型理论上没有属性或者方法。StringNumberBoolean 作为基本数据类型,能够调用一些属性或者方法的原因是: JavaScript 自动装箱机制

为了方便操作基本数据类型, ECMAScript还提供了三个特殊的引用类型,基本包装类型,StringBooleanNumber。有了这三个类型,在需要的时候,原始类型会自动转换成相应的包装对象(这个过程叫自动装箱)。自动装箱就是临时创建一个包装对象,将原始类型的值封装起来,以便调用包装对象的函数。但是原来那个变量的值不会有任何变化!

以下是介绍手动装箱的方案

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}