JS--数据类型及相互转换

54 阅读4分钟
  • 原始值类型「值类型/基本数据类型」

    • number 数字
    • string 字符串
    • boolean 布尔
    • null 空对象指针
    • undefined 未定义
    • symbol 唯一值
    • bigint 大数
  • 对象类型「引用数据类型」

    • 标准普通对象 object
    • 标准特殊对象 Array、RegExp、Date、Math、Error……
    • 非标准特殊对象 Number、String、Boolean……
    • 可调用/执行对象「函数」function

image.png

  • 特点1:返回的结果是字符串,字符串中包含了对应的数据类型

    • typeof typeof typeof [1,2,3]
  • 特点2:按照计算机底层存储的二进制进行检测「效率高」

    • 计算机科学:计算机原理、进制转化、计算机网络、数据结构和算法……
    • 000 对象
    • 1 整数
    • 010 浮点数
    • 100 字符串
    • 110 布尔
    • 000000…. null
    • -2^30 undefined
    • ……
  • 特点3:typeof null -> “object”

  • 特点4:typeof 对象 -> “object” && typeof 函数 -> “function”

    • 验证是否是对象的判断
  • 特点5:typeof 未被声明的变量 -> “undefined”

    • 插件封装中的暴露API

数据类型间相互转换的权威解读

把其他数据类型转换为Number

Number([val])

  • 一般用于浏览器的隐式转换中

@1 数学运算

@2 isNaN检测

@3 ==比较

...

  • 规则:

@1 字符串转换为数字:空字符串变为0,如果出现任何非有效数字字符,结果都是NaN

@2 把布尔转换为数字:true->1 false->0

@3 null->0 undefined->NaN

@4 Symbol无法转换为数字,会报错:Uncaught TypeError: Cannot convert a Symbol value to a number

@5 BigInt去除“n”(超过安全数字的,会按照科学计数法处理)

@6 把对象转换为数字:

  • 先调用对象的 Symbol.toPrimitive 这个方法,如果不存在这个方法

  • 再调用对象的 valueOf 获取原始值,如果获取的值不是原始值

  • 再调用对象的 toString 把其变为字符串

  • 最后再把字符串基于Number方法转换为数字

parseInt([val],[radix]) parseFloat([val])

  • 一般用于手动转换

  • 规则:[val]值必须是一个字符串,如果不是则先转换为字符串;然后从字符串左侧第一个字符开始找,把找到的有效数字字符最后转换为数字「一个都没找到就是NaN」;遇到一个非有效数字字符,不论后面是否还有有效数字字符,都不再查找了;parseFloat可以多识别一个小数点;

练习题:

let arr = [27.2, 0, '0013', '14px', 123];

arr = arr.map(parseInt);

把其他数据类型转换为String

转化规则:

@1 拿字符串包起来

@2 特殊:Object.prototype.toString

出现情况:

@1 String([val]) 或者 [val].toString()

@2 “+”除数学运算,还可能代表的字符串拼接

  • 有两边,一边是字符串

  • 有两边,一边是对象

  • 只出现在左边

  • ...

...

怎么解决精度问题?
    + 将数字转成整数「扩大系数」
    + 三方库:Math.js 、decimal.js、big.js ...
// JS中有关于小数(浮点数)的计算会出现精准度丢失的问题
//   + JS中所有值都是以2进制在计算机底层进行存储的{浮点数转为二进制,可能出现无限循环的情况}
//   + 在计算机底层存储的时候,最多存储64位「舍弃了一些值,值本身就失去了精准度」
// 浮点数计算的解决方案:
//   @1 toFixed保留小数点后面N位,他自己会四舍五入
//   @2 扩大系数法
const coefficient = function coefficient(num) {
    num = num + '';
    let [, char = ''] = num.split('.'),
        len = char.length;
    return Math.pow(10, len); //-> 10**len
};
const plus = function plus(num1, num2) {
    num1 = +num1;
    num2 = +num2;
    if (isNaN(num1) || isNaN(num2)) return NaN;
    let max = Math.max(coefficient(num1), coefficient(num2));
    return (num1 * max + num2 * max) / max;
};
console.log(plus(0.1, 0.2));

练习题:

let result = 100 + true + 21.2 + null + undefined + "Tencent" + [] + null + 9 + false;

console.log(result);

把其他数据类型转换为Boolean

转换规则:除了“0/NaN/空字符串/null/undefined”五个值是false,其余都是true

出现情况:

@1 Boolean([val]) 或者 !/!!

@2 条件判断

...

“==”比较时候的相互转换规则

“==”相等,两边数据类型不同,需要先转为相同类型,然后再进行比较

@1 对象==字符串 对象转字符串「Symbol.toPrimitive -> valueOf -> toString」

@2 null==undefined -> true null/undefined和其他任何值都不相等

null===undefined -> false

@3 对象==对象 比较的是堆内存地址,地址相同则相等

@4 NaN!==NaN

@5 除了以上情况,只要两边类型不一致,剩下的都是转换为数字,然后再进行比较的

“===”绝对相等,如果两边类型不同,则直接是false,不会转换数据类型「推荐」

练习题:

console.log([] == false);

console.log(![] == false);

综合练习题

var a = ?;

if (a == 1 && a == 2 && a == 3) {

console.log('OK');

}

// 利用==比较会转换数据类型,而对象转数字会经历一个详细步骤「Symbol.toPrimitive->valueOf->toString...」
/* 
var a = {
    i: 0,
    [Symbol.toPrimitive]() {
        // this->a
        return ++this.i;
    }
};
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
} 
*/
/* 
var a = [1, 2, 3];
a.toString = a.shift;
if (a == 1 && a == 2 && a == 3) {
    console.log('OK');
} 
*/

// 全局上下文中,获取a的值:首先看VO(G)中有没有,没有再继续去GO(window)中查找
var i = 0;
Object.defineProperty(window, 'a', {
    get() {
        return ++i;
    }
});
if (a === 1 && a === 2 && a === 3) {
    console.log('OK');
}