「回顾2022,展望2023,我正在参与2022年终总结征文大赛活动」
前言
在JavaScript语言中,你是否分的清什么时候是深仿制,什么时候是浅仿制呢?究竟咱们仿制完一个方针后,怎样的仿制会导致新方针引起原方针改动,怎样的仿制不会导致原方针随新方针改动呢?下面我就来介绍一下深浅仿制吧。
浅仿制的界说
望文生义,浅仿制仿制出来的原方针里边的值会随着新方针改动而改动,也便是说浅仿制是将引证地址仿制给一个新的方针,所以当引证地址对应的值发生改变时,原方针和新方针都会改动。简而言之便是两个方针共用一个引证地址。
深仿制的界说
当咱们知道了浅仿制的界说后,那深仿制既是仿制出两个如出一辙的两个方针,并且这两个方针更改自己的值不会影响另外一个方针里边的值,也便是说深仿制的两个方针不共用一个引证地址。
完成深or浅仿制的办法
浅仿制
1、赋值
let a = {
age: 1
}
let b = a
a.age = 2
console.log(b.age); // 2
b.age = 3
console.log(a.age); // 3
赋值便是一个很典型的浅仿制,由于两个方针运用的是同一个引证地址,所以当值改动时,两个方针都会改动。
2. Object.assign()
let a = {
like:{
n1:'reading',
n2:'runding'
}
}
let b = Object.assign({},a)
a.like = { //深仿制 {like: { n1: 'reading', n2: 'runding' } }
n3:'coding'
}
a.like.n1 = 'coding' //浅仿制 {like: { n1: 'coding', n2: 'runding' } }
console.log(b);
当咱们运用Object.assign()
仿制一个方针后,原方针第一层值改变时,新方针的值不会改动,为深仿制。原方针非第一层值改变时,新方针的值会改动,为浅仿制。
3. 解构
let a = {
age: 1,
like: {
n1: 'reading',
n2: 'runding'
}
}
let b = { ...a }
a.age = 2 //深仿制
a.like.n1 = 'coding' //浅仿制
console.log(b);
解构
办法与Object.assign()
十分类似,能够参照Object.assign()
的解释
深仿制
1. JSON.parse() 和 JSON.stringify()
let a = {
age: 1
}
let c = JSON.parse(JSON.stringify(a))
a.age = 3
console.log(c.age); // 1
当咱们运用JSON.parse()
和 JSON.stringify()
和对c
赋值时,当原方针改动时,新方针不会随之改动。
留意
let obj = {
a:1,
b:{
c:2,
d:3
},
e:undefined,
f:Symbol('hello'),
g:function(){}
}
let newobj = JSON.parse(JSON.stringify(obj))
console.log(newobj); //{ a: 1, b: { c: 2, d: 3 } }
还有一点要留意的便是JSON.parse() 和 JSON.stringify()
不能仿制undefined、Symbol类型、函数。
可深可浅办法
let arr = ['old', 1, true, null, undefined]
let newArr = arr.concat() //深仿制
let newArr1 = arr.slice() //深仿制
arr[0] = 'new'
console.log(newArr); // [ 'old', 1, true, null, undefined ]
console.log(newArr1); // [ 'old', 1, true, null, undefined ]
let arr = [{old:'old'},['old']]
let newArr = arr.concat() //浅仿制
let newArr1 = arr.slice() //浅仿制
arr[0].old = 'new'
arr[1][0] = 'new'
console.log(newArr);
console.log(newArr1);
当arr为原始类型时,即为深仿制,为引证类型时,即为浅仿制。(和Object.assign()
的原理很类似。)
手写深or浅仿制的办法
浅仿制
function shallowCopy(obj) {
if(typeof obj !== 'object') return
var newObj = obj instanceof Array ? [] : {}
for(let i in obj){
if(obj.hasOwnProperty(i)){
newObj[i] = obj[i]
}
}
return newObj
}
let a =[{c:1},2,3,[2]]
let b = shallowCopy(a)
a[0].c = 222
console.log(b); // [ { c: 222 }, 2, 3, [ 2 ] ]
这里有一点咱们要留意的便是,在浅仿制的办法里,原始类型仍是为深仿制。
深仿制
function deepCopy(obj) {
if (typeof obj !== 'object') return //递归完毕条件
let newObj = Array.isArray(obj) ? [] : {}; // 判断类型
for (let i in obj) {
if(obj.hasOwnProperty(i)){
newObj[i] = typeof obj[i] === 'object' ? deepCopy(obj[i]) : obj[i] // 递归办法,进行仿制
}
}
return newObj;
}
let a =[{c:1},2,3,[2]]
let b = deepCopy(a)
a[0].c = 222
console.log(b);
深仿制即时一层一层递归进行仿制仿制,完成了不会随原始值改变而改变的深仿制。
jQuery的extend办法
1. 介绍
jQuery.extend()
函数用于 将一个或多个方针的内容兼并到方针方针。这一点与Object.assign()
办法类似。
但extend办法还有一个特色便是 能够经过第一个参数操控兼并方针时为深仿制仍是浅仿制。
语法: $ .extend( [deep ], target, object1 [, objectN ] )
deep | 可选。 Boolean类型 指示是否深度兼并方针,默以为false。如果该值为true,且多个方针的某个同名特点也都是方针,则该”特点方针”的特点也将进行兼并。 |
---|---|
target | Object类型 方针方针,其他方针的成员特点将被附加到该方针上。 |
object1 | 可选。 Object类型 第一个被兼并的方针。 |
objectN | 可选。 Object类型 第N个被兼并的方针。 |
2.完成
function extend() {
let deep = false // 默以为浅仿制
let length = arguments.length
let target = arguments[0] || {}
let i = 1
let options;
//用户开启了深仿制
if(typeof target == 'boolean') {
deep = target
target = arguments[i] || {}
i++
}
if(typeof target !== 'object') {
target = {}
}
for(;i< length; i++){
options = arguments[i]
if(options != null) {
for(let key in options) {
//方针特点值
let src = target[key]
//要仿制的方针特点值
let copy = options[key]
if(deep && copy && typeof copy == 'object'){
target[key] = extend(deep,src,copy) // 深仿制
}else if (copy !== undefined){
target[key] = copy // 浅仿制
}
}
}
}
return target
}
let obj1 = {
a: 1,
b:{b1:1,b2:2},
e:{d:2}
}
let obj2 = {
b:{b1:3,b2:4},
c:3
}
let obj3 = {
d:4
}
let newObj = extend(false, {},obj1, obj2, obj3) //浅仿制
let newObj1 = extend(true, {},obj1, obj2, obj3) // 深仿制
obj2.b.b1 = 33
obj2.b.b2 = 33
obj1.e.d = 0
console.log(newObj); // { a: 1, b: { b1: 33, b2: 33 }, e: { d: 0 }, c: 3, d: 4 }
console.log(newObj1); // { a: 1, b: { b1: 3, b2: 4 }, e: { d: 2 }, c: 3, d: 4 }