witch@&*weaves

拷贝

js的数据结构是可变的,而Js里面拷贝有这么多类型的根本原因是内存,而需求不同也会导致有时候不需要节省那么多内存,需要不变增加内存来换稳定性。


对于拷贝,这里主要说的是拷贝对象,基本数据类型就是直接在内存里开个新空间赋值进去了,新空间和旧空间是不一样的两个空间,而拷贝对象有四种情况,一种是基础类型拷贝,一种是赋值,一种是浅拷贝,一种是深拷贝,而深拷贝又可以分为JSON深拷贝,和递归深拷贝。

拷贝方式 第一层 第二层+ 函数 循环引用
赋值 地址 地址 保留 安全
浅拷贝 值 地址 保留 安全
JSON深拷贝 值 值 丢失 报错
递归深拷贝 值 值 保留 需处理
方面 赋值 浅拷贝 深拷贝
内存地址 完全共享 对象本身地址不同
引用属性地址相同
完全新建
基础类型 共享修改 独立修改 独立修改
引用类型 共享修改 共享修改 独立修改
内存占用 最小 中等 最大
性能 最快 较快 较慢
// 场景1:需要共享状态 - 用赋值
let globalConfig = { theme: "dark", language: "zh" };
let headerConfig = globalConfig;  // 共享配置
let footerConfig = globalConfig;

// 场景2:需要部分独立 - 用浅拷贝  
let userTemplate = { name: "", settings: { theme: "light" } };
let user1 = { ...userTemplate, name: "张三" }; // 独立名字,共享设置
let user2 = { ...userTemplate, name: "李四" };

// 场景3:需要完全独立 - 用深拷贝
let criticalData = { sensitive: true, records: [1, 2, 3] };
let backup = JSON.parse(JSON.stringify(criticalData)); // 完全独立备份

方式

赋值

全部拷贝地址。

浅拷贝

第一层拷贝值,深层拷贝地址

- - 扩展运算符(...) - Object.assign() - Array.prototype.slice() - Array.prototype.concat() - Array.from()

深拷贝

全部拷贝值。

- JSON.stringify() + JSON.parse() - structuredClone()

扩展运算符(...)

扩展运算符,可以在函数调用/数组构造时,将数组表达式或者 string 在语法层面展开;还可以在构造字面量对象时,将对象表达式按 key-value 的方式展开

适用对象:Object/Array

用于取出参数对象里的所有可遍历属性,拷贝到当前对象中。

let obj = {a:1,b:2}
let obj2 = {...obj}

//等于

let obj = {a:1,b:2}
let obj2 = Object.assign({},obj)

Object.assign

Object.assign()方法用于将一个或多个源对象的属性复制到目标对象中。

它拷贝的是对象的属性的引用,而不是对象本身.

语法:

Object.assign(_target_, _source(s)_)
参数 描述
target 必需。目标对象。
source 必需。一个或多个源对象(被复制对象)
const dog = {
    sound : 'Wof',
    walkDay: ['Mon','Wed',['morning']],
    food : function(){
        console.log(`${this.sound}!Need some meat!`);
        
    }
}

const dog2 = Object.assign({},dog)

dog2.sound = 'changed';

console.log(dog.sound); //Wof——证明是浅拷贝
console.log(dog2.food()); //Wof!Need some meat!

针对数组的浅拷贝

slice

slice() 方法返回一个新的数组对象,这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin不包括 end )。原始数组不会被改变

适用对象:Array

concat

concat() 方法用于合并两个或多个数组。此方法不会改变现有数组,而是返回一个新数组

适用对象:Array

#code