Object.assign()
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象 。它将返回目标对象。
const target = {a:1,b:2};
const source = {b:4,c:5}
const returnTarget = Object.assign(target,source )
展开运算符
展开运算符:将一个数组转为逗号分隔的参数序列
- 合并数组
let a= [1,2,3]
let b=[4,5,6]
let c=[...a,..b]//[1,2,3,4,5,6]
- 替代apply
// 以下三种结果相同
function f(a,b,c){
console.log(a,b,c)
}
let args = [1,2,3];
f.apply(null,args)
f(...args)
f(1,2,3) //[1,2,3]
或者
function f2(...args){
console.log(args)
}
f2(1,2,3) //[1,2,3]
或者
function f3(){
console.log(Array.from(arguments))
}
f3(1,2,3)
- Array.from ()创建数组对象
let a =[1,2,3];
let b = [4,5,6];
Array.prototype.push.apply(a,b);
或者
a.push(...b)
解构赋值
let a = [1,2,3,4,5,6];
let [c,...d]=a
console.log(a);//1
console.log(d);//[2,3,4,5,6]
浅拷贝和深拷贝
对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一地址,修改其中一个对象的属性,则另一个对象的属性也会改变,而深复制则是开辟新的栈,复制了所有层级,两个对象对应两个不同的地址,修改一个对象的属性不会改变另一个对象的属性。
浅复制实现
var obj ={a:1,arr:[2,3]};
var shallowObj = shallowCopy(obj);
function shallowCopy(src){
var dst = {};
for(var prop in src){
if(src.hasOwnProperty(prop)){
dst[prop]= src[prop]
}
}
return dst;
}
因为浅拷贝只会将各个属性进行依次复制,并不会递归复制,而JavaScript存储对象都是存地址的,所有浅拷贝的obj.arr和shallowObj.arr指向同一块内存地址, 导致的结果就是
shallowObj.arr[1]=5;
obj.arr[1]=5
而深复制不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在上面obj和shallowObj的arr属性指向同一对象的问题。
- 第一种使用递归
function deepClone(data){
const type = this.judgeType(data);
let obj=null;
if(type=='array'){
obj==[];
for(let i =0;i<data.length;i++){
obj.push(this.deepClone(data[i]))
}
}else if(type == 'object'){
obj={}
for(let key in data){
if(data.hasOwnProperty(key)){
obj[key] = this.deepClone(data[key])
}
}
}else{
return data
}
return obj
}
function judgeType(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',
};
if(obj instance Element){
return 'element'
}
return map[toString.call(obj)]
};
const test = {
name:'a',
date:[1,2,3]
}
console.log(deepClone(test))
test.data[0]=6;
console.log(test)
- 第二种使用 JSON.parse(JSON.stringfy(xxx))
var test = {
name:{
xing:{
first:'张',
second:'李'
},
ming:'老头'
},
age:40,
friend:['老王','宋经纪','同事']
}
var result =JSON.parse(JSON.stringfy(test))
result.age = 30
result.name.xing.push('testttt')
console.dir(test)
console.dir(result)
使用JSON解析注意点
一般用来深拷贝,其过程说白了就是利用JSON.stringify将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象。
-
如果obj里面有时间对象,则JSON.stringfy再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象。
-
如果obj里有RegExp,Error对象,则序列化的结果将得到空对象。
-
如果obj里面有函数,undefined,则系列化的结果会把函数或undefined丢失
-
如果obj里有NaN、Infinity和-infinity,则序列化的结果会变成null
-
JSON.stringfy()只能序列化对象的可枚举的自有属性,例如如果obj中的的对象是有构造函数生成的,则使用JSON.parse(JSON.stringify(obj))深拷贝后。会丢失对象的contructor
-
如果对象中存在循环引用的情况也无法实现深拷贝
涉及到上面的情况就使用递归
-
参考