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

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

  1. 浅拷贝(Shallow Copy):
  • 通过方法把某个对象完整拷贝后,原对象的修改会影响新对象
  • 常见的浅拷贝方法:
    1. Object.create(obj)
    2. Object.assign({},obj)
    3. [].concat()
    4. 数组解构
    5. 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 对象转换为可以传输、存储或与其他编程语言交互的字符串时非常有用。

相关推荐
蓝染-惣右介12 分钟前
【若依RuoYi-Vue | 项目实战】帝可得后台管理系统(二)
java·前端·后端·vue·springboot
我码玄黄38 分钟前
HTML翻牌器:用CSS和HTML元素创造动态数字展示
前端·css·html
-草莓星球杯1 小时前
若依VUE项目安全kind-of postcss vite漏洞扫描和修复
前端·javascript·vue.js
LJ小番茄1 小时前
关于wordPress中的用户登录注册等问题
前端·javascript·css·html·wordpress
小郝同学(恩师白云)1 小时前
SpringMVC后续4
java·服务器·前端
优联前端2 小时前
uni-app-通过vue-cli命令行快速上手
开发语言·前端·vue.js·uni-app·优联前端
点燃银河尽头的篝火(●'◡'●)3 小时前
【BurpSuite】Cross-site scripting (XSS 学徒部分:1-9)
前端·web安全·网络安全·xss
Jiaberrr3 小时前
手把手教你:微信小程序实现语音留言功能
前端·微信小程序·小程序·语音·录音
熊猫在哪3 小时前
安装nuxt3
前端·nuxt.js
安冬的码畜日常4 小时前
【CSS in Depth 2 精译_036】5.6 Grid 网格布局中与对齐相关的属性 + 5.7本章小结
前端·css·css3·html5·网格布局·grid·css网格