【前端面试宝典】js浅拷贝深拷贝

写在前面

CSDN话题挑战赛第1期

  • 活动详情地址:CSDN

  • 参赛话题:前端面试宝典

  • 话题描述:欢迎各位加入话题创作得小伙伴,如果我没有猜错得话,我觉得你是应该同我一样是一位前端人。如今前端在IT事业中的占比越来越重,已经成为不可缺少的部分,前端技术也是层出不穷,各种技术类、技术框架也蜂拥而出,前端面试的难度也随之增加,如果我们拥有一套前端面试宝典。如果你是应聘者:你就可以从容的solo面试官,如果你是面试官:你就可以将应聘者拷问到骨子里!
    总之我们大家一起将自己的面试经验以及学习到的知识点汇聚于此,形成一套体系的前端面试宝典。让读者无论是面试还是学习都能够有非常大的收获。就让我们携手共筑前端面试宝典吧!!!

携手共筑前端面试宝典

题目一

JavaScript深浅拷贝的理解

考点

深浅拷贝的理解

答案

浅拷贝

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>		
		<script type="text/javascript">		
		    // ----------------------------------------------浅拷贝
		    // 只是把对象的属性和属性值拷贝到另一个对象中
		    var obj1 = {
		      a: {
		        a1: { a2: 1 },
		        a10: { a11: 123, a111: { a1111: 123123 } }
		      },
		      b: 123,
		      c: "123"
		    }
		    // 方式1
		    function shallowClone1(o) {
		      let obj = {}
		
		      for (let i in o) {
		        obj[i] = o[i]
		      }
		      return obj
		    }
				
				let shallowObj = shallowClone1(obj1);
				console.log(shallowObj);
				
		    // 方式2
		    var shallowObj2 = { ...obj1 }
				console.log(shallowObj2)
				
		    // 方式3
		    var shallowObj3 = Object.assign({}, obj1)
		
			
		    obj1.a.a1 = 999
		    obj1.b = true;
		
		    console.log(obj1);  //第一层的没有被改变,一层以下就被改变了		
		</script>
	</body>
</html>

深拷贝 

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<script type="text/javascript">
		
		// ----------------------------------------------深拷贝
		
		    // 简易版  
		    function deepClone(o) {
		      let obj = {}
		      for (var i in o) {
		        // if(o.hasOwnProperty(i)){
		        if (typeof o[i] === "object") {
		          obj[i] = deepClone(o[i])
		        } else {
		          obj[i] = o[i]
		        }
		        // }
		      }
		      return obj
		    }		
		
		    var myObj = {
		      a: {
		        a1: { a2: 1 },
		        a10: { a11: 123, a111: { a1111: 123123 } }
		      },
		      b: 123,
		      c: "123"
		    }
		
		    var deepObj1 = deepClone(myObj)
		    deepObj1.a.a1 = 999
		    deepObj1.b = false
		    console.log(myObj);	
		
		
		    // 简易版存在的问题:参数没有做检验,传入的可能是 Array、null、regExp、Date
		    function deepClone2(o) {
		      if (Object.prototype.toString.call(o) === "[object Object]") {  //检测是否为对象
		        let obj = {}
		        for (var i in o) {
		          if (o.hasOwnProperty(i)) {
		            if (typeof o[i] === "object") {
		              obj[i] = deepClone(o[i])
		            } else {
		              obj[i] = o[i]
		            }
		          }
		        }
		        return obj
		      } else {
		        return o
		      }
		    }
		
		    function isObject(o) {
		      return Object.prototype.toString.call(o) === "[object Object]" || Object.prototype.toString.call(o) === "[object Array]"
		    }
		
		    // 继续升级,没有考虑到数组,以及ES6中的map、set、weakset、weakmap
		    function deepClone3(o) {
		      if (isObject(o)) {//检测是否为对象或者数组
		        let obj = Array.isArray(o) ? [] : {}
		        for (let i in o) {
		          if (isObject(o[i])) {
		            obj[i] = deepClone(o[i])
		          } else {
		            obj[i] = o[i]
		          }
		        }
		        return obj
		      } else {
		        return o
		      }
		    }		
		
		    // 有可能碰到循环引用问题  var a = {}; a.a = a; clone(a);//会造成一个死循环
		    // 循环检测
		    // 继续升级
		    function deepClone4(o, hash = new map()) {
		      if (!isObject(o)) return o//检测是否为对象或者数组
		      if (hash.has(o)) return hash.get(o)
		      let obj = Array.isArray(o) ? [] : {}
		
		      hash.set(o, obj)
		      for (let i in o) {
		        if (isObject(o[i])) {
		          obj[i] = deepClone4(o[i], hash)
		        } else {
		          obj[i] = o[i]
		        }
		      }
		      return obj
		    }
		
		    // 递归易出现爆栈问题
		    //  将递归改为循环,就不会出现爆栈问题了
		    var a1 = { a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' };
		    var b1 = { b: { c: { d: 1 } } }
		    function cloneLoop(x) {
		      const root = {};
		      // 栈 
		      const loopList = [  //->[]->[{parent:{a:1,b:2},key:c,data:{ c1: 3, c2: { c21: 4, c22: 5 } }}]
		        {
		          parent: root,
		          key: undefined,
		          data: x,
		        }
		      ];
		      while (loopList.length) {
		        // 深度优先
		        const node = loopList.pop();
		        const parent = node.parent; //{} //{a:1,b:2}
		        const key = node.key; //undefined //c
		        const data = node.data; //{ a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' }  //{ c1: 3, c2: { c21: 4, c22: 5 } }}
		        // 初始化赋值目标,key 为 undefined 则拷贝到父元素,否则拷贝到子元素
		        let res = parent; //{}->{a:1,b:2,d:'asd'} //{a:1,b:2}->{}
		        if (typeof key !== 'undefined') {
		          res = parent[key] = {};
		        }
		        for (let k in data) {
		          if (data.hasOwnProperty(k)) {
		            if (typeof data[k] === 'object') {
		              // 下一次循环 
		              loopList.push({
		                parent: res,
		                key: k,
		                data: data[k],
		              })
		            } else {
		              res[k] = data[k];
		            }
		          }
		        }
		      }
		      return root
		    }		
		
		    function deepClone5(o) {
		      let result = {}
		      let loopList = [
		        {
		          parent: result,
		          key: undefined,
		          data: o
		        }
		      ]
		
		      while (loopList.length) {
		        let node = loopList.pop()
		        let { parent, key, data } = node
		        let anoPar = parent
		        if (typeof key !== 'undefined') {
		          anoPar = parent[key] = {}
		        }
		
		        for (let i in data) {
		          if (typeof data[i] === 'object') {
		            loopList.push({
		              parent: anoPar,
		              key: i,
		              data: data[i]
		            })
		          } else {
		            anoPar[i] = data[i]
		          }
		        }
		      }
		      return result
		    }		
		
		    let cloneA1 = deepClone5(a1)
		    cloneA1.c.c2.c22 = 5555555
		    console.log(a1);
		    console.log(cloneA1);		
		
		    // ------------------------------------------JSON.stringify()实现深拷贝
		
		    function cloneJson(o) {
		      return JSON.parse(JSON.stringify(o))
		    }
		
		    // let obj = { a: { c: 1 }, b: {} };
		    // obj.b = obj;
		    // console.log(JSON.parse(JSON.stringify(obj))) // 报错 // Converting circular structure to JSON		
		
		</script>
	</body>
</html>

写在最后

CSDN话题挑战赛第1期

  • 活动详情地址:CSDN
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值