js数据类型
- 基本类型
字符串(String) 数字(Number) 布尔(Boolean)
空(Null) 未定义(Undefined) 记号(Symbol)
大整数(BigInt) - 引用数据类型
对象(Object) 数组(Array) 函数(Function)
正则(RegExp) 日期(Date)等
检查数据类型
- typeof
用于判断数据类型,返回值一共有8个字符串,分别为:string,number,boolean,object,undefined,symbol,function,bigint
console.log(typeof 1) //number
console.log(typeof true) //boolean
console.log(typeof null) //object
console.log(typeof undefined) //undefined
console.log(typeof Symbol('f')) //symbol
console.log(typeof {}) //object
console.log(typeof []) //object
console.log(typeof function(){}) //function
console.log(typeof 1n) //bigint
console.log(typeof new RegExp("\\w+")) //object
console.log(typeof new Date()) //object
可以看到,typeof无法区分null,数组、对象、正则和日期。
借助==比较的特点可以筛选出null
console.log(null==undefined) // true
console.log(null==null) // true
console.log(null==[]) // false
console.log(null=={}) // false
null除了和null、undefined进行==的结果为true以外,和其他任何类型==都为false,可以区别出null
2. instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
用法: obj instanceof Fn
obj._proto_._proto_...=>Fn.prototype,
沿着obj的原型链查找是否存在对象Fn.prototype,如果存在则返回true,如果找到obj原型链的终点Object.prototype都没有找到Fn.prototype,则返回false
通过instanceof可以对数组、对象、RegExp、Date进行区分:
console.log({} instanceof Object) // true
console.log([] instanceof Array) // true
console.log(new RegExp("\\w+") instanceof RegExp) // true
console.log(new Date() instanceof Date) // true
- Object.prototype.toString.call()
Object.prototype.toString() 方法,会返回一个形如 "[object xxx]" 的字符串。但是不少对象的toString都进行了重写,比如数组:
console.log([1].toString()) // 1
数组重写了toString方法,直接调用数组对象的toString方法,实际调用到的是重写后的方法,并不是Object.prototype中的toString方法。 Object.prototype.toString.call()能对每一种数据类型进行精准的调用toString实现返回:
console.log(Object.prototype.toString.call('demo')) //[object String]
console.log(Object.prototype.toString.call(1)) //[object Number]
console.log(Object.prototype.toString.call( true)) //[object Boolean]
console.log(Object.prototype.toString.call( null)) //[object Null]
console.log(Object.prototype.toString.call( undefined)) //[object Undefined]
console.log(Object.prototype.toString.call( Symbol('f'))) //[object Symbol]
console.log(Object.prototype.toString.call( {})) //[object Object]
console.log(Object.prototype.toString.call( [])) //[object Array]
console.log(Object.prototype.toString.call( function(){})) //[object Function]
console.log(Object.prototype.toString.call( 1n)) //[object BigInt]
console.log(Object.prototype.toString.call(new RegExp("\\w+"))) // [object RegExp]
console.log(Object.prototype.toString.call(new Date())) // [object Date]
浅拷贝和深拷贝
对于基本数据类型的数据,深拷贝和浅拷贝的结果一样,拷贝后的数据与原始数据没有关系。深拷贝与浅拷贝只针对引用数据类型。
1.浅拷贝
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。最简单的浅拷贝就直接使用=赋值即可,浅拷贝以后的数据和原始数据指向同一个对象,对对象数据的修改会彼此影响
2. 深拷贝
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
拷贝实现
- 实现拷贝的内置函数
- Object.assign()
let objSrc = {
a: {
b: 1
}
}
let objDest = Object.assign({}, objSrc);
Object.assign只能处理深度只有一层的对象,如果要复制的对象只有一层的话可以考虑使用它。
2. JSON.stringify
let objSrc = {
a: {
b: 1
}
}
let objDest = JSON.parse(JSON.stringify(objSrc))
JSON.stringify能正确处理的对象只有 Number, String, Boolean, Array这些能够转成JSON格式的对象才可以这样用,像function、RegExp没办法转成JSON则无法使用
- 手写深拷贝
function deepClone(obj) {
if (typeof obj !== 'object' || obj==null) {
return obj
}
if (obj instanceof RegExp) {
return new RegExp(obj.source, obj.flags)
}
if (obj instanceof Date) {
return new Date(obj.getTime())
}
let result
if (Array.isArray(obj)) {
result = []
} else {
result = {}
}
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
result[key] = deepClone(obj[key])
}
}
return result
}