实现深浅拷贝的几种方式


实现浅拷贝(6种)

1、ES6:object.assign()

Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。(如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性)。

  • 语法:
Object.assign(target(目标对象), ...sources(源对象))
  • 实例:
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
  • Object.assign使用注意事项:
  1. 只拷贝源对象的自身属性(不拷贝继承属性)

  2. 不会拷贝对象不可枚举的属性

  3. undefined和null无法转成对象,他们不能作为Object.assign参数,但是可以作为源对象

  4. 属性名为Symbol 值的属性,可以被Object.assign拷贝

2、通过for in方法

for…in 语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。
for … in 循环中的代码每执行一次,就会对数组的元素或者对象的属性进行一次操作。

  • 语法:
    for (变量 in 对象)
    {
      在此执行代码
    }
  • 实例:
    var obj = { a: 1, b: 2 }
    var b = {}
    for (var key in obj) {
    b[key] = obj[key]
    }
    console.log(b) //{ a: 1, b: 2 }

3.通过Es6 扩展运算符…方法

对象中的扩展运算符(…)用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中,如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

let bar = { a: 1, b: 2 };
let baz = { ...bar }; // { a: 1, b: 2 }

上述方法实际上等价于:

let bar = { a: 1, b: 2 };
let baz = Object.assign({}, bar); // { a: 1, b: 2 }

4.直接用赋值运算符(=)

let a=[0,1,2,3,4],
    b=a;
a[0]=1;
console.log(a,b);//[ 1, 1, 2, 3, 4 ] [ 1, 1, 2, 3, 4 ]

5.用数组方法slice

slice() 方法可从已有的数组中返回选定的元素。

  • 语法
arrayObject.slice(start,end)

start: 必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。

end :可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

  • 返回值:

返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

  • 实例
let array = [{a:1},{b:2}]
let array1 = array.slice(0);
console.log(array1)//[ { a: 1 }, { b: 2 } ]

6.用数组方法concat

concat() 方法用于连接两个或多个数组。

  • 语法
arrayObject.concat(arrayX,arrayX,......,arrayX)

arrayX 必需。该参数可以是具体的值,也可以是数组对象。可以是任意多个。

  • 返回值
    返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。
  • 实例
let array = [{a:1},{b:2}]
let array1 = [].concat(array)
console.log(array1)//[ { a: 1 }, { b: 2 } ]

但是浅拷贝存在一个问题,那就时拷贝的地址存在共享问题,属性值发生改变时,两者都会受影响,那么深拷贝就来了

实现深拷贝(5种)

1.通过JSON.parse( )和JSON.stringify( )

JSON.parse() 方法用于将一个 JSON 字符串转换为对象。

  • 语法
    JSON.parse(text[, reviver])
  • 参数说明:

text:必需, 一个有效的 JSON 字符串。
reviver: 可选,一个转换结果的函数, 将为对象的每个成员调用此函数。

  • 返回值:
    返回给定 JSON 字符串转换后的对象。
  • 实例:
let obj = {
    a: '张三',
    b: '李四',
}

let obj1 = JSON.parse(JSON.stringify(obj))
obj1.a = "王五"
console.log(obj,obj1)

结果:


console.log(obj) 
//{ a: '张三', b: '李四' } 
console.log(obj1) 
// {"a":"王五","b":"李四"}

补充:JSON.stringify()

JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串。

  • 语法
JSON.stringify(value[, replacer[, space]])

value:必需, 要转换的 JavaScript 值(通常为对象或数组)。

  • 缺点:
  • 无法实现对对象中方法的深拷贝,会显示为undefined

2.手动实现深拷贝

let obj = {
   a: 1,
   b: 2
}
let newObj = {
   a: obj.a,
   b: obj.b
}
newObj.a = 3;
console.log(obj.a); //1
console.log(newObj.a); //3

3.使用扩展运算符实现深拷贝

var obj = { a: 1,b: 2}
var newObj = { ...obj, b:3 }
console.log(obj,newObj);//{ a: 1, b: 2 } { a: 1, b: 3 }

4.用slice实现对数组的深拷贝


var arr1 = [1,2,3]; 
var arr2 = arr1.slice(0);
arr2[1] = 4;
console.log("数组的原始值:" + arr1 );
//数组的原始值:1,2,3
console.log("数组的新值:" + arr2 );
//数组的新值:1,4,3

5.concat实现对数组的深拷贝

当数组里面的值是基本数据类型,比如String,Number,Boolean时,属于深拷贝

var arr1 = [1,3,5];
var arr2 = arr1.concat();
arr2[1] = 2;
console.log("数组的原始值:" + arr1 );
//数组的原始值:1,3,5

console.log("数组的新值:" + arr2 );
//数组的新值:1,2,5

文章作者: BiLiang
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 BiLiang !
评论
  目录