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() 方法返回一个新的数组对象,这一对象是一个由 beginend 决定的原数组的浅拷贝(包括 begin不包括 end )。原始数组不会被改变

适用对象:Array

concat

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

适用对象:Array

#code