JavaScript数据类型可以分为 7 种:空(Null)、未定义(Undefined)、数字(Number)、字符串(String)、布尔值(Boolean)、符号(Symbol)、对象(Object)。其中前六种为基础类型,最后一种为引用类型。
基础类型的数据在被引用或者拷贝时,是值传递,也就是说会创建一个完全相等的变量;而引用类型只是创建一个指针指向原有的变量,实际上两个变量是“共享”这个这个数据的,并没有重新创建一个新的数据。
Undefined
Undefined是一个很特殊的数据类型,它只有一个值,也就是undefined。可通过以下几种方式获得:
- 引用已声明但未初始化的变量;
var a; //undefined
- 引用未定义的对象类型;
var o = {};
o.b; //undefined
- 执行无返回值函数;
(()=>{})() //undefined
- 执行void表达式 ;
void 0; //undefined
- 全局常量window.undefined 或 undefined
window.undefined; //undefined
Null
Null 与 Undefined 类似,只有一个值 null,都可以表示空值。Null是JavaScript保留关键字,而undefined只是一个常量。
Boolean
Boolean 数据类型有两个值:true 和 false。注意:0、空字符串、null、undefined 在转换时都会返回 false。
Number
Number 是数值类型。有两个特殊值: NaN 和 Infinity。
NaN (not a number) 通常在计算失败的时候回得到该值。Number,isNaN 方法可以判断一个变量是否为NaN。
Infinity 无穷大,-Infinity 无穷小。在某些场景下比较有用,比如通弄过数值来表示权重或者优先级,I可以表示最高优先级或者最大权重。
进制转换:
parseInt 可将其他进制的整数转换成十进制;将十进制转换成其他进制时可通过 toString 方法;
精度问题:
计算的时候JavaScript引擎会先将十进制转换成二进制,然后再进行加法运算,再将得到的结果转换成十进制。在进制转换的过程中如果小数位是无限的,就会出现误差。
0.1 + 0.2 // 0.30000000000000004
Math.pow(Math.pow(5,1/2),2) //5.000000000000001
解决方法 (消除无限小数位):
- 先转换成整数进行计算,然后再转换回小数。
- 舍弃末尾的小数位。
parseFloat((0.1+0.2).toPrecision(12)) //0.3
String
String 是字符串类型。
Symbol
Symbol是ES6中引入的新数据类型,表示一个唯一的常量,通Symbol 函数来创建对应的数据类型,创建时可以添加变量描述,该变量描述再传入时会被强制转换成字符串进行存储。
var a = Symbol('1'); // symbol(1)
var b = Symbol(1); // symbol(1)
a.description === b.description; // ture 1
var c = Symbol({id:1}); // Symbol([object Object])
c.description; // [object object]
var _a = Symbol('1');
_a == a; //false
优点:
- 避免常量值重复
- 避免对象属性覆盖
Object
简单来说Object数据类型就是键值对的集合,;复杂的说,Object 又包括很多子类型,比如 Date、 Array、Set、RegExg。
对于Object,我们要重点理解深拷贝。
- 由于引用类型在赋值时值传递指针,这种拷贝方式称为浅拷贝。
- 创建一个新的与之相同的引用类型的过程称之为深拷贝。
下边实现一个拷贝函数:
function clone (obj){
let map = new WeakMap();
function deep(data){
let result = {}
const keys = [...Object.getOwnPropertyNames(data),...Object.getOwnPropertySymbols(data)]
if(!keys.length) return data
const exist = map.get(data)
if(exist) return exist
map.set(data,result)
keys.forEach(key => {
let item = data[key]
if(typeof item === 'object' && item){
result[key] = deep(item)
} else {
result[key] = item
}
})
return result
}
return deep(obj)
}