引用值的复制、浅拷贝、深拷贝
2020-09-14 本文已影响0人
云凡的云凡
vue 中父组件通过 v-bind 属性 给子组件传值,子组件通过 props(可以是对象或者数组) 接收,子组件不能修改父组件传过来的值,可以在 data 函数中 新定义一个变量,把传过来的值拷贝到新定义的变量上。当遇到对象时候,就用深拷贝靠谱点。
所以我们来说说引用值的复制、浅拷贝、深拷贝
1.复制 :其中一个改变,其它跟着变(只是多了一个变量指向那个空间)
var cat1 = {
name: '天天',
Borth: 2019,
hobby: 'eat fish',
friends: '大黑',
son: {
oone: '小花',
two: '小淘气',
girlFriend: {
name: '一一',
age: 25
},
car: '本田'
}
}
// 1.复制
var cat2 = cat1
console.log(cat1 === cat2); //true
console.log(cat1 == cat2); //true
//因为对象是传址的,var cat2 = cat1 只是把对象 cat1 的指针传给 cat2 ,
// 它们指向的是同一块内存区域,所以 cat1 和 cat2 的值和类型都相等
cat2.name = '王王'
cat2.son.oone = '小李'
console.log(cat1 === cat2); //true
console.log(cat1 == cat2); //true
// 当cat2 改变,cat1也会跟着改变。当改变 cat1 时,cat2 也会改变,所以他们的值和类型还是一样。
2.浅拷贝:并没有把对象的引用值处理,值处理了第一层的属性,并没有处理下面的引用值。
<script>
Object.prototype.num = 1
var cat1 = {
name: '天天',
Borth: 2019,
hobby: 'eat fish',
friends: '大黑',
son: {
oone: '小花',
two: '小淘气',
girlFriend: {
name: '一一',
age: 25
},
car: '本田'
}
}
var cat2 = {}
// 2.浅拷贝
simpleClone(cat1, cat2)
function simpleClone(origin, target) {
// var target = target || {}
for (var key in cat1) {
//把原型剔除出去
if (origin.hasOwnProperty(key)) {
target[key] = origin[key]
}
}
}
console.log(cat1 === cat2); //false
console.log(cat1 == cat2); //false
// 当改变对象里面引用值的时候:另一个会跟着改变
cat1.son.two = '淘气'
console.log(cat1.son.two); //淘气
console.log(cat2.son.two); //淘气
console.log(cat1 === cat2); //false
console.log(cat1 == cat2); //false
// 当改变对象里的基础类型:另一个不会跟着改变
cat1.Borth = 2020
console.log(cat1.Borth); //2020
console.log(cat2.Borth); //2019
console.log(cat1 === cat2); //false
console.log(cat1 == cat2); //false
</script>
3.深拷贝:有引用值的时候就要做一系列遍历,在循环的时候去判断里面的每一项键值对是不是引用值,是引用值的时候再判断是数组函数对象,用一个递归的克隆函数来进行再处理。
<script>
Object.prototype.num = 1
var cat1 = {
name: '天天',
Borth: 2019,
hobby: 'eat fish',
friends: '大黑',
son: {
oone: '小花',
two: '小淘气',
girlFriend: {
name: '一一',
age: 25
},
car: '本田'
}
}
var cat2 = deepClone(cat1)
console.log(cat2);
cat2.name = 'zhangsan'
cat2.son.two = '李四'
console.log(cat1);
console.log(cat2);
function deepClone(origin, target) {
var target = target || {}
toStr = Object.prototype.toString
arrType = '[object Array]'
for (var key in origin) {
if (origin.hasOwnProperty(key)) {
if (typeof (origin[key] === 'object') && origin[key] !== null) {
if (toStr.call(origin[key]) === arrType) {
target[key] = []
} else {
target[key] = {}
}
deepClone(origin[key], target[key])
} else {
target[key] = origin[key]
}
}
}
return target
}
</script>
或者
export const getObjType = obj => {
let toString = Object.prototype.toString
let 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 instanceof Element) {
return 'element'
}
return map[toString.call(obj)]
}
export const deepClone = data => {
let type = getObjType(data)
let obj
if (type === 'array') {
obj = []
} else if (type === 'object') {
obj = {}
} else {
// 不再具有下一层次
return data
}
if (type === 'array') {
for (let i = 0, len = data.length; i < len; i++) {
obj.push(deepClone(data[i]))
}
} else if (type === 'object') {
for (let key in data) {
obj[key] = deepClone(data[key])
}
}
return obj
}
4.json深拷贝:不常用,因为json数据没有方法
<script>
var cat1 = {
name: '张三',
Borth: 2019,
hobby: '乒乓球',
friends: '李四',
son: {
oone: '小花',
two: '小淘气',
girlFriend: {
name: '一一',
age: 25
},
car: '本田'
},
eat: ['鱼', '胡萝卜', '玉米']
}
var str = JSON.stringify(cat1) //把对象转换成字符串,这样就不是引用值了
var cat2 = JSON.parse(str)
cat2.name = '王五'
cat2.eat.push('土豆')
var cat2 = JSON.parse(str)
console.log(cat1, cat2)
console.log(cat1 === cat2); //false
console.log(cat1 == cat2); //false
</script>