我是靠谱客的博主 老实狗,最近开发中收集的这篇文章主要介绍面试中被问到吐血的js知识点(二):深拷贝和浅拷贝,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

说在前面

这是一个系列的文章,有兴趣的朋友可以查看此系列其它文章(持续更新ing)。本人才疏学浅,若有纰漏还请及时指出,请多指教!

情境描述

面试官:你了解js的深拷贝和浅拷贝吗?
我:深拷贝是连同引用地址和值一起拷贝;浅拷贝是只拷贝引用地址,不拷贝值,共用内存。
面试官:那浅拷贝和深拷贝如何实现?
我:用Object.create()实现深拷贝,(此处过了20秒钟),。。。
面试官:还有吗?
我:uhhhh,。。。忘了。。
面试官:那好,下一个问题。。。
(真想找个地洞钻进去。。。)

上面情景是大多数面试者都经历的事情,可是不能每次都被问倒呀,或许面试结束网上一搜就有解释,可是看一遍怎么会记得住呢?不妨记下来吧。

正题

深拷贝:复制了引用地址和值,相当于复制了一份副本,值相同,地址不同,互不影响。

浅拷贝:仅仅是复制了引用地址,也就是说新变量和旧变量共用内存,彼此的修改会互相影响。

1、如何实现深拷贝?

(1)手动赋值

var obj1 = {a: 1, b: 2};
var obj2 = {a: obj1.a, b: obj1.b};
obj2.a = 0;
console.log(obj1.a);  // 1
obj1.a = 3;
console.log(obj2.a);  // 0

(2)JSON

用JSON.stringify将对象转为字符串,再用JSON.parse将字符串转为对象。

var obj1 = {a: 1, b: 2};
var obj2 = JSON.parse(JSON.stringify(obj1));
console.log(obj2);   //  {a: 1, b: 2}
obj2.a = 3;
console.log(obj1.a);  // 1,不受影响

 ps:只有能被转为json格式的对象才能这样用。

(3)Object.create

var obj1 = {a: 1, b: 2};
var obj2 = Object.create(obj1);
obj2.a = 3;  // 在obj2的原型上访问属性
console.log(obj1.a);  // 1,不受影响

(4)递归拷贝

const deepCopy = (obj) => {
  let newObj = {};
  for(let key in obj){
    let type = typeof obj[key];
    if(obj[key] === null ||type === 'boolean' || type === 'undefined' || type === 'number' || type === 'string' || type === 'function'){
      newObj[key] = obj[key];
    }else if(Array.isArray(obj[key])){
      let temp = new Array();
      for(let j = 0, len = obj[key].length; j < len;j++){
        temp.push(obj[key][j]);
      }
      newObj[key] = temp;
    }
    else{
      newObj[key] = deepCopy(obj[key]);
    }
  }
  return newObj;
};

2、如何实现浅拷贝?

(1)赋值操作符(=)

对于(Boolean、String、Number、Undefined、Null)这五种基本数据类型,它们的复赋值是值传递,而对于对象的赋值是对引用赋值,所以使用“=”赋值对象就是对对象的浅拷贝。

var obj = {
    a: 1,
    b: 2
}
var obj1 = obj;
obj1.a = 3;
console.log(obj.a);  // 3,被改了
obj.b = 0;
console.log(obj1.b); // 0,也被改了

(2)对象的解构赋值

var obj1 = {a: 1, b: {c: 2}};
var obj2 = {...obj1};
obj2.b.c = 3;
console.log(obj1.b.c);  // 3
obj1.b.c = 0;
console.log(obj2.b.c);  // 0

(3)Object.assign()

此方法是ES6中定义的方法,用于将源对象的所有可枚举属性复制到目标对象中,返回值是目标对象。用法如下:

Object.assign(targetObj, sourceObj1, ...sourceObjn);

例子:

let sourceObj = { a: { b: 1}};
let targetObj = {c: 3};
Object.assign(targetObj, sourceObj);
sourceObj.a.b = 2;
console.log(targetObj.a.b);  // 2, 源对象的修改影响到了目标对象
targetObj.a.b = 4;
console.log(sourceObj.a.b);  // 4, 目标对象的修改影响到了源对象

但是我发现一个奇怪的现象,如下所示:

obj的属性a竟然没有被修改,说明对于第一层属性,Object.assign是深拷贝。

参考资料

JSON教程https://www.runoob.com/json/json-tutorial.html
ES6对象https://www.runoob.com/w3cnote/es6-object.html
 

最后

以上就是老实狗为你收集整理的面试中被问到吐血的js知识点(二):深拷贝和浅拷贝的全部内容,希望文章能够帮你解决面试中被问到吐血的js知识点(二):深拷贝和浅拷贝所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(46)

评论列表共有 0 条评论

立即
投稿
返回
顶部