你知道拷贝,但是你会写吗?

在 JavaScript 中,拷贝是将一个对象的值复制到另一个对象的过程。JavaScript 中的拷贝可以分为浅拷贝和深拷贝两种类型。

  1. 浅拷贝(Shallow Copy):
  • 通过方法把某个对象完整拷贝后,原对象的修改会影响新对象
  • 常见的浅拷贝方法:
    1. Object.create(obj)
    2. Object.assign({},obj)
    3. \].concat()

    4. arr.toReversed().reverser()(一种很新的内置函数,我浏览器不行)
  1. 深拷贝(Deep Copy):

    • JSON.parse(JSON.stringify(obj))
      但是这个方法有缺陷:
    1. 不能处理 undefined,function,Symbol

    2. 无法处理循环引用

学习拷贝前我们先来看看一段代码

js 复制代码
let a={
    age:18
}
let b=a
a.age=19   

console.log(b.age);  //19

会输出19是因为v8引擎会创建一个堆,用来存储引用类型,let b=a只是把对象a在堆里的地址赋值给了b,更改了age的值,b的值也会更改,这算浅拷贝。

那看完考考你:

js 复制代码
let a={
    age:18
}
let b=a
 a={   
     age:20
 }
console.log(b.age);  //输出??

第五段代码的a是 新的对象,所有地址不一样,前面a的地址会指向新对象,b地址不变。输出18。

浅拷贝

Object.create(obj)

js 复制代码
let a={
    name:'雨程',
    like:{
        n:'coding'
    }
}
let b=Object.create(a)
a.name ='涛'
a.like.n='run'
console.log(b.like);// { n: 'run' }
console.log(b.name);//涛

使用Object.create(obj)把对象完整拷贝后,原对象的修改会影响新对象。

Object.assign({},obj)

js 复制代码
 let a={
     name:'雨程',
     like:{
         n:'coding'
     }
 }
let b =Object.assign({},a)  //拷贝了a的like的地址
 a.like.n='run'
 console.log(b.like);  //'run'

这里同上

[].concat()

js 复制代码
let arr=[1,2,3,{n:10}]
let newArr=[].concat(arr)
arr[3].n=100
console.log(newArr);  //[ 1, 2, 3, { n: 100 } 

数组里面原始值无法改变,对象会被改变

解构

js 复制代码
let newArr=[...arr]
arr[3].n=100
 console.log(newArr);//[ 1, 2, 3, { n: 100 } ]

浅拷贝函数

如果要你写个浅拷贝函数怎么办?

js 复制代码
let obj={
   name:'刘涛',
   age:18,
   like:{
     n:'run'
   }
}
// let o =Object.create(obj)
// o.sex='boy'

function shalldowCopy(obj){
//不是引用类型就不拷贝
if(!(obj instanceof Object))return;//if(typeof obj!=='object'||obj ==null) return
//如果obj是数组,就创建数组,是对象就创建对象
    let objCopy=obj instanceof Array?[]:{}
for(let key in obj){
    if(obj.hasOwnProperty(key)){  
        objCopy[key]=obj[key]
    }
}
return objCopy
}

let newObj=shalldowCopy(obj)
console.log(newObj);

深拷贝

JSON.parse(JSON.stringify(obj))

js 复制代码
let obj ={
    name:'李总',
    age:18,
    a:{
        n:1
    },
    b:undefined,
    c:null,
    d:Symbol(123),
    e:function(){},
    f:{
        n:100
    }

}

console.log(JSON.stringify(obj));//把对象转换成字符串,花括号也转换成字符串
let str = JSON.stringify(obj)
console.log(JSON.parse(str));

// let obj2 =JSON.parse(JSON.stringify(obj))  //深拷贝  但是需要注意
// obj.age=20
// obj.age.n=10
// console.log(obj2);

上方代码注释部分无法改变对象obj里面的任何值,不能处理 undefined,function,Symbol,无法输出。还无法处理循环引用

js 复制代码
//上方代码加上这一段
obj.e=obj.f
obj.f.n=obj.e//循环引用
console.log(obj);//打印下方
//{
  name: '李总',
  age: 18,
  a: { n: 1 },
  b: undefined,
  c: null,
  d: Symbol(123),
  e: <ref *1> { n: [Circular *1] },
  f: <ref *1> { n: [Circular *1] }
}

深拷贝函数

js 复制代码
function deepCopy(obj) {
    let objCopy = {}
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        // 区分 obj[key] 原始类型和引用类型
        if (obj[key] instanceof Object) { // 不能直接赋值
          objCopy[key] = deepCopy(obj[key]);////遇到对象里的对象就执行递归,遍历里面对象的属性,遍历完回去
        } else {
          objCopy[key] = obj[key]
        }
  
      }
    }
  
    return objCopy
  }
  
  let obj2 = deepCopy(obj);
  obj.a.n = 11
  console.log(obj2);

下方是介绍拷贝出现的方法

Object.assign

Object.assign是JavaScript中常用的一个方法,它可以将一个或多个源对象的属性复制到目标对象中。具体来说,它接受一个目标对象和一个或多个源对象作为参数,然后将所有源对象中的可枚举属性复制到目标对象中,并返回目标对象。

它的语法如下所示:

Copy 复制代码
Object.assign(target, ...sources)

其中,target是目标对象,sources是一个或多个源对象。需要注意的是,如果多个源对象中有相同的属性名,则后面的属性值会覆盖前面的属性值。

除了复制属性外,Object.assign还有一些其他的用途。例如,我们可以使用它来合并多个对象:

Copy 复制代码
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const obj3 = { c: 3 };

const mergedObj = Object.assign({}, obj1, obj2, obj3);
// mergedObj = { a: 1, b: 2, c: 3 }
把所有东西放到空对象,这样第一个对象就不会变
如果去掉空对象:
console.log(obj1);//{ a: 1, b: 2, c: 3 }
console.log(obj2);//{ b: 2 }

在上面的例子中,我们使用了三个源对象obj1、obj2和obj3,将它们的属性合并到一个新的空对象中,并将结果赋给mergedObj。

hasOwnProperty

hasOwnProperty 是 JavaScript 中的一个方法,用于检查对象自身是否包含指定名称的属性。它是从 Object 原型继承而来的方法。这个方法接受一个参数,即要检查的属性名称,如果对象本身具有该属性,并且不是通过原型链继承而来的,就会返回 true,否则返回 false

例如:

javascriptCopy 复制代码
let obj = {
  name: 'Alice',
  age: 25
};

console.log(obj.hasOwnProperty('name')); // 输出 true,因为 'name' 是对象 obj 自身的属性
console.log(obj.hasOwnProperty('toString')); // 输出 false,因为 'toString' 是从原型链继承而来的属性

hasOwnProperty 对于检查对象自身的属性非常有用,特别是当你想知道某个属性是不是对象自己创建的,而不是继承得来的时候。

JSON.stringify()

JSON.stringify() 是 JavaScript 中一个非常有用的函数,用于将 JavaScript 对象转换为 JSON 字符串。这个函数接受一个 JavaScript 对象作为参数,并返回对应的 JSON 字符串表示。

例如:

javascriptCopy 复制代码
let obj = {
  name: 'Alice',
  age: 25,
  interests: ['programming', 'reading']
};

let jsonString = JSON.stringify(obj);
console.log(jsonString);

这将输出类似于以下格式的 JSON 字符串:

css 复制代码
jsonCopy code
{"name":"Alice","age":25,"interests":["programming","reading"]}

JSON.stringify() 还可以接受两个额外的参数,用于更进一步的控制转换过程:

  1. 第二个参数是一个 replacer 函数或者一个数组,用于选择性地过滤和转换结果。这允许你在生成 JSON 字符串时选择性地排除或转换某些属性。
  2. 第三个参数是一个 space 参数,用于添加缩进、空格或换行符,使输出的 JSON 字符串更易读。

这个函数通常在需要将 JavaScript 对象转换为可以传输、存储或与其他编程语言交互的字符串时非常有用。

相关推荐
学渣y几秒前
React状态管理-对state进行保留和重置
javascript·react.js·ecmascript
_龙衣20 分钟前
将 swagger 接口导入 apifox 查看及调试
前端·javascript·css·vue.js·css3
进取星辰1 小时前
25、Tailwind:魔法速记术——React 19 样式新思路
前端·react.js·前端框架
struggle20251 小时前
continue通过我们的开源 IDE 扩展和模型、规则、提示、文档和其他构建块中心,创建、共享和使用自定义 AI 代码助手
javascript·ide·python·typescript·开源
x-cmd2 小时前
[250512] Node.js 24 发布:ClangCL 构建,升级 V8 引擎、集成 npm 11
前端·javascript·windows·npm·node.js
夏之小星星2 小时前
el-tree结合checkbox实现数据回显
前端·javascript·vue.js
crazyme_62 小时前
前端自学入门:HTML 基础详解与学习路线指引
前端·学习·html
撸猫7913 小时前
HttpSession 的运行原理
前端·后端·cookie·httpsession
亦世凡华、3 小时前
Rollup入门与进阶:为现代Web应用构建超小的打包文件
前端·经验分享·rollup·配置项目·前端分享
Bl_a_ck3 小时前
【React】Craco 简介
开发语言·前端·react.js·typescript·前端框架