前端初学必会,你真的知道深浅拷贝么

arguments.callee

  在函数内部有两个特殊对象:this和arguments,其中,arguments主要用于保存函数的参数,但这个对象还有一个名叫callee的属性,该属性是个指针,指向拥有这个arguments对象的函数。

  arguments.callee一般用于递归算法,如果函数有名字,而且名字以后不会变的情况下直接递归调用函数即可。否则使用arguments.callee较好。

function factorial(num){    
   if (num <=1) {         
     return 1;     
   } else {         
     //return num * factorial(num-1)  
     return num * arguments.callee(num-1)   
   } 
}  

  但是现在已经不推荐使用arguments.callee了,访问arguments对象是非常昂贵的操作,它是一个很大的对象,每次递归调用访问它的时候都会重新创建,影响现代浏览器的性能,还会影响闭包。

  接受参数n=5,不用for循环输出数组【1,2,3,4,5】,这就会想到递归

function show(num){    
  let arr=[]
  return (function fn(){
      arr.unshift(num)
      num--
      if(num!=0)
        //arguments.callee()
        fn()
      return arr
    })
}  

数据类型的复制

  首先我们都知道基本数据类型是保存在栈内存中的,引用数据类型是保存在堆内存中的。也就是说,如果是基本数据类型,则按值访问;如果是引用数据类型,我们只是通过变量中保存的引用数据类型的地址进行访问的。

var a=1
var obj={
  name:"TOM"
}

在这里插入图片描述

  1. 基本类型的复制
var a=1
var b=a
console.log(b)
a=2
console.log(b)

  赋值的时候,在栈内存中开辟新的内存空间,存放变量b,所以在栈内存中分别存放着变量a、b各自的值,修改时互不影响。

  1. 引用类型的复制
var color1 = ['red','green'];
var color2 = color1;//复制
console.log(color2)//['red','green'];
color1.push('black') ;//改变color1的值
console.log(color2)//['red','green','black']

  color1与color2指向堆内存中同一地址的同一对象,复制的只是引用地址。

浅拷贝

   浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。浅拷贝只是拷贝基本类型的数据,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,因此存在父对象被篡改的可能,浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。

var Nation = {  
    nation: '中国'
};
function extendCopy(p) {  
    var c = {};  
    for (var i in p) {    
        c[i] = p[i];  
    }  
    return c;
}
var Doctor = extendCopy(Nation);
Doctor.career = '医生';
Doctor.nation = '美国';
console.log(Doctor.nation); // 美国
console.log(Nation.nation); // 中国
console.log(Doctor.career); // 医生
console.log(Doctor.__proto_ === Nation.__proto_) // true
// 这里涉及到使用拷贝父对象的属性实现继承

var obj = {
  a: "hello",
  b:{
      a: "world",
      b: 21
    },
  c:["Bob", "Tom", "Jenny"],
  d:function() {
      alert("hello world");
    }
}
       
var obj1 = simpleClone(obj);
console.log('obj1=>>>',obj1);
// 1、浅拷贝时,改变对象中的整个属性,不会影响原数据
obj1.c = ['mm', "Tom", "Jenny"]; // 一层,作为整体,重写,全改变;改变属性值,不改变原对象
console.log('obj=>>>',obj); //obj.c => ["Bob", "Tom", "Jenny"]
// 2、浅拷贝时,改变对象中某个属性的属性值,改变原对象
obj1.c[0] = 'mm'; // 浅拷贝时,改变属性的属性值,改变原对象
console.log('obj=>>>',obj); //obj.c => ["mm", "Tom", "Jenny"]

浅拷贝函数:

function simpleClone(initalObj) {    
  var obj = {};    
  for ( var i in initalObj) {
    obj[i] = initalObj[i];
  }    
  return obj;
}

深拷贝

  与浅拷贝不同的是,深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。深拷贝就是能够实现真正意义上的数组和对象的拷贝。递归调用"浅拷贝"。(深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象)。

深拷贝函数:

function deepClone(initalObj, finalObj) {
  var obj = finalObj || {};
  for (var i in initalObj) {
      var prop = initalObj[i];

      // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况
      if(prop === obj) {
          continue;
      }
      //判断是否为数组、对象
      if (typeof prop === 'object') {
          //判断为数组还是对象
          //obj[i] = (prop.constructor === Array) ? [] : {};
          //arguments.callee(prop, obj[i]);
          obj[i] = (prop.constructor === Array) ? [] :  Object.create(prop);
      } else {
          obj[i] = prop;
      }
  }
  return obj;
}

  也可以通过利用 JSON 对象中的 parse 和 stringify 方法,将一个对象转换为字符串,赋给新的对象,再转回JSON对象。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值