深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
? ? ? ? ①基本类型:拷贝的就是基本类型的值
? ? ? ? ②引用类型:拷贝的就是内存地址(新旧对象共享同一块内存,如果改了新对象的值也是会影响旧对象的值的)
? ? ? ? 赋值:一个对象赋值给一个新变量的时候,赋值的是对象在栈中的地址,而不是堆中的数据,两个对象是相互影响联动的。
? ? ? ? 浅拷贝:按位拷贝对象,它会创建一个新的对象,这个对象有着原始对象属性值的一份精确拷贝。但只是复制对象空间而不复制资源。
// 对象赋值
let obj1 = {
name: 'Chen',
age: 18,
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = obj1;
obj2.name = 'Forever';
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj2===>', obj2);
// 浅拷贝
let obj1 = {
name: 'Chen',
age: 18,
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj3 = {...obj1};
obj3.name = 'Forever';
obj3.hobby[1] = 'swim';
obj3.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
console.log('obj3===>', obj3);
// 展开运算符... 实现浅拷贝
let obj1 = {
name: 'Chen',
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = {...obj1};
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
obj2.name = 'Forever';
console.log('obj1===>', obj1); // obj1===> { name: 'Chen',hobby: [ 'see a film', 'swim','alpinism', 'tourism']}
console.log('obj2===>', obj2); // obj2===> { name: 'Forever',hobby: [ 'see a film', 'swim','alpinism', 'tourism']}
// Object.assign() 实现浅拷贝
let obj1 = {
name: "Chen",
hobby: ["see a film", "write the code", "play basketball", "tourism"],
};
let obj2 = Object.assign({}, obj1);
obj2.hobby[1] = "swim";
obj2.hobby[2] = "alpinism";
obj2.name = "Forever";
console.log("obj1===>", obj1); // obj1===> {name: 'Chen',hobby: [ 'see a film', 'swim', 'alpinism', 'tourism' ]}
console.log("obj2===>", obj2); // obj2===> {name: 'Forever',hobby: [ 'see a film', 'swim', 'alpinism', 'tourism' ]}
?
// Array.prototype.concat() 实现浅拷贝
let arr1 = [
{
name: 'Chen'
},
'see a film',
'write the code',
'play basketball',
'tourism'
];
let arr2 = arr1.concat([]);
arr2[0].name = 'Forever';
arr2[1] = 'play games';
console.log('arr1===>', arr1); // arr1===> [{ name: 'Forever' },'see a film','write the code','play basketball', 'tourism']
console.log('arr2===>', arr2); // arr2===> [{ name: 'Forever' },'play games','write the code', 'play basketball', 'tourism']
// Array.prototype.concat() 实现浅拷贝
let arr1 = [
{
name: 'Chen'
},
'see a film',
'write the code',
'play basketball',
'tourism'
];
let arr2 = arr1.slice();
arr2[0].name = 'Forever';
arr2[1] = 'play games';
console.log('arr1===>', arr1); // arr1===> [{ name: 'Forever' },'see a film','write the code','play basketball', 'tourism']
console.log('arr2===>', arr2); // arr2===> [{ name: 'Forever' },'play games','write the code', 'play basketball', 'tourism']
// JSON.parse(JSON.stringify())实现深拷贝Object
let obj1 = {
name: 'Chen',
hobby: ['see a film', 'write the code', 'play basketball', 'tourism']
}
let obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj1 === obj2); // false
obj2.name = 'Forever';
obj2.hobby[1] = 'swim';
obj2.hobby[2] = 'alpinism';
console.log('obj1===>', obj1);
// obj1===> { name: 'Chen',hobby: ['see a film', 'write the code', 'play basketball', 'tourism']}
console.log('obj2===>', obj2);
// obj2===> { name: 'Forever',hobby: ['see a film', 'swim', 'alpinism', 'tourism']}
undefined
、任意的函数以及 symbol 值,在序列化过程中会被忽略(出现在非数组对象的属性值中时)或者被转换成?null
(出现在数组中时)。函数、undefined 被单独转换时,会返回 undefined,如JSON.stringify(function(){})
?or?JSON.stringify(undefined)
.replacer
?参数中强制指定包含了它们。JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify({ x: 5 }); // '{"x":5}'
JSON.stringify({ x: 5, y: 6 });
// "{"x":5,"y":6}"
JSON.stringify([new Number(1), new String("false"), new Boolean(false)]);
// '[1,"false",false]'
JSON.stringify({ x: undefined, y: Object, z: Symbol("") });
// '{}'
JSON.stringify([undefined, Object, Symbol("")]);
// '[null,null,null]'
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, [Symbol.for("foo")]);
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, function (k, v) {
if (typeof k === "symbol") {
return "a symbol";
}
});
// undefined
// 不可枚举的属性默认会被忽略:
JSON.stringify(
Object.create(null, {
x: { value: "x", enumerable: false },
y: { value: "y", enumerable: true },
}),
);
// "{"y":"y"}"
// 浅拷贝
let shalldowCopy = (obj) => {
// 只拷贝引用类型
if (typeof obj !== 'object' || obj == null) return
let objCopy = obj instanceof Array ? [] : {}
for (let key in obj){
//不要隐式
if (obj.hasOwnProperty(key)){
objCopy[key] = obj[key]
}
}
return objCopy
}
//测试
let obj = {
name: '小黑子',
age: 18,
hobby: {
type: 'coding'
}
}
let arr = ['a', {n: 1}, 1, undefined, null]
let newObj = shalldowCopy(obj)
let newArr = shalldowCopy(arr)
obj.age = 20
obj.hobby.type = 'swimming'
arr[0] = 'b'
arr[1].n = 2
console.log(newObj);
// { name: '小黑子', age: 18, hobby: { type: 'swimming' } }
console.log(newArr);
// [ 'a', { n: 2 }, 1, undefined, null ]
let deepCopy = (obj) => {
if(typeof obj!== 'object' || obj == null) return
let objCopy = obj instanceof Array ? [] : {}
for (let key in obj){
if(obj.hasOwnProperty(key)){
// 与浅拷贝相比只是这里有差异其余原理都一样
if(obj[key] instanceof Object){
objCopy[key] = deepCopy(obj[key])
} else {
objCopy[key] = obj[key]
}
}
}
return objCopy
}
// 测试
const obj5 = {
name:'你好',
age:18,
like:{
type:'coding'
}
}
const res = deepCopy(obj5)
console.log(res) // { name: '你好', age: 18, like: { type: 'coding' } }
obj5.like.type = 'sleeping'
console.log(res) // { name: '你好', age: 18, like: { type: 'coding' } }