0.最新的 ECMAScript 标准定义了哪 8 种数据类型--- 参考
7 种基础类型:
- Boolean、Number、String
- Null、Undefined
- BigInt、Symbol(ES6)
1 种引用类型 :Object
1.null 和 undefined的区别--- 参考
null表示"没有对象",即该处不应该有值
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义
Number(null)
// 0
Number(undefined)
// NaN
2.检查数据类型的方法
1.typeof是检测一个变量是不是基本数据类型的最佳工具
console.log(typeof ""); // string
console.log(typeof 1); // number
console.log(typeof true); // boolean
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof function(){}); // function
2. instanceof 检测当前实例是否隶属于某各类
console.log("1" instanceof String); // false
console.log(1 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log({} instanceof Object); // true
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function) // true
console.log(null instanceof Null); // 报错
console.log(undefined instanceof Undefined); // 报错
3.constructor
console.log(("1").constructor === String); // true
console.log((1).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(({}).constructor === Object); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
4.Object.prototype.toString.call()
console.log(Object.prototype.toString.call("1")); // {object String}
console.log(Object.prototype.toString.call(1)); // {object Number}
console.log(Object.prototype.toString.call(null)); // {object Null}
console.log(Object.prototype.toString.call(undefined)); // {object Undefined}
console.log(Object.prototype.toString.call(true)); // {object Boolean}
console.log(Object.prototype.toString.call({})); // {object Object}
console.log(Object.prototype.toString.call([])); // {object Array}
console.log(Object.prototype.toString.call(function () {}); // {object Fuction}
3.数据类型转换
强制转换
Number()
原始类型:有不能转为数字的,就是NaN
Number(false) => 0
Number(true) => 1
Number(undefined) => NaN
Number(null) => 0
Number("1.2") => 1.2
Number("12") => 12
Number("1.2.3") => NaN
Number(new object()) => NaN
Number(50) => 50
Number({}) => NaN
String()
原始类型值的转换规则
数值:转为相应的字符串。
字符串:转换后还是原来的值。
布尔值:true转为"true",false转为"false"。
undefined:转为"undefined"。
null:转为"null"。
String({a: 1}) => "[object Object]"
String([1, 2, 3]) => "1,2,3"
Boolean()
false
undefined
null
-0
0或+0
NaN
false
''
true
所有对象,包括{}、布尔对象new Boolean(false)
自动转换
场景:
不同类型的数据互相运算
123 + 'abc' => "123abc"
对非布尔值类型的数据求布尔值
if ('abc')
对非数值类型的数据使用一元运算符(即“+”和“-”)
+ {foo: 'bar'} => NaN
本质:
以强制类型为基础,转为需要的number、string、boolean
4.深拷贝和浅拷贝
浅拷贝:浅拷贝通过ES6新特性Object.assign()或者通过扩展运算法...来达到浅拷贝的目的,浅拷贝修改
副本,不会影响原数据,但缺点是浅拷贝只能拷贝第一层的数据,且都是值类型数据,如果有引用型数据,修改
副本会影响原数据。
深拷贝:通过利用JSON.parse(JSON.stringify())来实现深拷贝的目的,但利用JSON拷贝也是有缺点的,
当要拷贝的数据中含有undefined/function/symbol类型是无法进行拷贝的,当然我们想项目开发中需要
深拷贝的数据一般不会含有以上三种类型,如有需要可以自己在封装一个函数来实现。
浅拷贝
首先可以通过 Object.assign 或 展开运算符 ... 来解决这个问题
let a = {
age: 1
}
let b = Object.assign({}, a) // or {...a}
a.age = 2
console.log(b.age) // 1
通常浅拷贝就能解决大部分问题了,但是当我们遇到如下情况就需要使用到深拷贝了
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = {...a}
a.jobs.first = 'native'
console.log(b.jobs.first) // native
深拷贝
let a = {
age: 1,
jobs: {
first: 'FE'
}
}
let b = JSON.parse(JSON.stringify(a))
a.jobs.first = 'native'
console.log(b.jobs.first) // FE
但是该方法也是有局限性的:
- 会忽略 undefined
- 会忽略 symbol
- 不能序列化函数
- 不能解决循环引用的对象
- 在遇到function、 undefined 或者 symbol 的时候,该对象也不能正常的序列化
let a = {
age: undefined,
sex: Symbol('male'),
jobs: function() {},
name: 'wb'
}
let b = JSON.parse(JSON.stringify(a))
console.log(b) // {name: "wb"}
当然如果你的数据中含有以上三种情况下,可以使用递归来实现一个深拷贝方法,因此,这里就封装一个工具函数来供实现深拷贝。
封装工具
// 精准判断类型函数
function typeOf (obj) {
const toString = Object.prototype.toString
const map = {
'[object Boolean]': 'boolean',
'[object Number]': 'number',
'[object String]': 'string',
'[object Function]': 'function',
'[object Array]': 'array',
'[object Date]': 'date',
'[object RegExp]': 'regExp',
'[object Undefined]': 'undefined',
'[object Null]': 'null',
'[object Object]': 'object'
}
return map[toString.call(obj)]
}
// util 深拷贝函数
export function deepClone (data) {
const t = typeOf(data)
let o
if (t === 'array') {
o = []
} else if (t === 'object') {
o = {}
} else {
return data
}
if (t === 'array') {
for (let i = 0; i < data.length; i++) {
o.push(deepCopy(data[i]))
}
} else if (t === 'object') {
for (let i in data) {
o[i] = deepCopy(data[i])
}
}
return o
}