-
原始值类型「值类型/基本数据类型」
- number 数字
- string 字符串
- boolean 布尔
- null 空对象指针
- undefined 未定义
- symbol 唯一值
- bigint 大数
-
对象类型「引用数据类型」
- 标准普通对象 object
- 标准特殊对象 Array、RegExp、Date、Math、Error……
- 非标准特殊对象 Number、String、Boolean……
- 可调用/执行对象「函数」function
-
特点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');
}