js 对象深拷贝与浅拷贝
2018-09-22 本文已影响25人
igor_d140
js基本数据类型与对象指针(引用地址)存放在栈内存,对象实际存放在堆内存。
变量标志符和值(基本数据和指针)保存在栈内存
链接:关于JS堆栈与拷贝(基本数据类型新增symbol)
链接:react渲染效率--深复制 immutable
链接:React 的性能优化(一)当PureComponent 遇上ImmutableJS
对象赋值、浅拷贝与深拷贝
浅拷贝(存在关联)与深拷贝(不存在关联)的区别是克隆对象与原始对象是否存在关联
类型 | 实质 | 表现 | 方法 |
---|---|---|---|
浅拷贝赋值
|
指针(引用地址)相等,指向同一对象和内存空间(克隆对象即原始对象)
|
克隆对象属性值变化原始对象跟着变化 | 赋值var a = b = { a: 1 } (a == b)
|
浅拷贝不完全深拷贝
|
引用地址不相等,对象部分数据重新开辟新空间 | 克隆对象部分属性值变化原始对象跟着变化 | Object.assign(target, ...source) |
深拷贝 | 引用地址完全不同,数据存在于重新开辟的新空间 | 克隆对象与原始对象无关联 |
浅拷贝
var obj = {
a: 1,
b: 2,
c: [1, 2, 3]
}
var cloneObj = {}
Object.assign(cloneObj, obj)
// var cloneObj = Object.assign({}, obj) // ES6
// var cloneObj = {...obj} //ES7
cloneObj.c[0] = 101
console.log(obj.c[0]) //101
cloneObj.a = 10
console.log(obj.a) // 1
深拷贝
- 方法一
递归
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<button></button>
<script>
const nodes = document.getElementsByTagName('button')
const element = document.createElement('button')
const eles = cloneDeep(element)
const eless = [eles, eles, eles, eles]
const tips = () => {
console.log(1)
}
function Person(name, age) {
return {
name: name,
age: age
}
}
var obj = {
a: 2,
isEnble: true,
c: () => {
console.log('fn')
},
Person: Person,
dom: nodes,
element: element,
eles: eles,
eless: eless,
d: tips,
yy: new Date(),
b: {
b: 3,
c: {
c: 8,
d: {
d:9,
e: {
e:10,
f: [1,2 ,3, 4]
}
}
}
}
}
// JSON.parse(JSON.stringify(new Date))
// "2018-09-21T15:47:40.671Z"
// Object.prototype.toString.call(params)
// "[object Date]"
// "[object Array]"
// "[object Object]"
// "[object Function]"
// "[object Symbol]"
// "[object Null]"
// "[object Undefined]"
// "[object Number]"
// "[object Boolean]"
// "[object String]"
// "[object HTMLCollection]"
function isObject(value) {
var type = Object.prototype.toString.call(value)
return value !== null && type === '[object Object]' || type === '[object Arrary]'
}
const isArray = Array.isArray
function baseclone(value){
var __obj = {}
for(let key in value){
let attr = value[key]
if(!isObject(attr)){
__obj[key] = attr
}else{
if(isArray(attr))
__obj[key] = Array.prototype.slice.call(attr, 0)
else
__obj[key] = baseclone(attr)
}
}
return __obj
}
function cloneDeep(value) {
if(!isObject(value)){
return value
}else{
if(isArray(value))
return Array.prototype.slice.call(value, 0)
else
return baseclone(value)
}
}
</script>
</body>
</html>
- 方法二
序列化
有缺陷:数据有函数,日期,DOM节点等不适用
var obj = .... //同上
var c = JSON.parse(JSON.stringify(obj))