浅拷贝和深拷贝的方法


js数据类型

  • 基本数据类型(存放在栈空间)
  • 引用数据类型(存放在堆空间)
    js里面的对象是引用类型,我们在把变量a赋值给变量b的时候,赋值过去的其实是a的引用地址,b有了相同的引用地址,那a跟b指向的都是同一块内存空间,操作b的属性,其实就是操作了这块内存,因为a也指向这块内存,所以a的属性也变了。这其实就是一个浅拷贝。
  • 拷贝的栈中的地址。修改拷贝后的数据,原数据会改变
  • 拷贝的是堆中的数据。

浅拷贝

方式1: 遍历

let target = {
  name: 'John',
  age: 20,
  friend: {
    name: 'lee',
    age: 30
  }
}
const shallowCopy = (obj) => {
  // 判断参数是数组还是对象
  const result = Array.isArray(obj) ? [] : {};
  for (let key in obj) {
    // 使用hasOwnProperty来判断是否是自身属性
    // 只拷贝自身属性,不拷贝原型链上的属性,即继承属性
    if (obj.hasOwnProperty(key)) {
      result[key] = obj[key];
    }
  }

  return result;
}

let newObj = shallowCopy(target);
newObj.age = 50;
console.log(target.age, newObj.age); //20, 50

方式2:

ES6: Object.assign()

let target = {
  name: 'John',
  age: 20,
  friend: {
    name: 'lee',
    age: 30
  }
}
const newObj=Object.assign({},target)
newObj.friend.name = 'baba'
console.log(newObj);  //{ name: 'John', age: 20, friend: { name: 'baba', age: 30 } }

方式3: 扩展运算符...
let target = {
  name: 'John',
  age: 20,
  friend: {
    name: 'lee',
    age: 30
  }
}
let newObj ={...target}
newObj.friend.age = 18
console.log(newObj) //{ name: 'John', age: 20, friend: { name: 'lee', age: 18 } }

深拷贝

方式1:
序列化与反序列化

var obj = {
           name: "jack",
           age: 18,
           hobby: ["sing", 'dance']
       }
   //  :
   var str = JSON.stringify(obj)
   var o   = JSON.parse(str)
     o.hobby[0] = 'code'
     console.log(o); //{ name: 'jack', age: 18, hobby: [ 'code', 'dance' ] }
     console.log(obj);//{ name: 'jack', age: 18, hobby: [ 'sing', 'dance' ] }

方式2:
引入loadsh.js

<script src="https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.js">
</script>
var obj = {
name: "jack",
age: 18,
hobby: ["sing", 'dance']
}
let o = _.cloneDeep(obj)
o.hobby[0] = 'code'
console.log(o);
console.log(obj);

方式3:

引入underscore.js,这个库里有一个pick函数
可以实现深拷贝

<script src="https://cdn.bootcdn.net/ajax/libs/underscore.js/1.13.2/underscore-min.js"></script>
let obj = {
name: 'Jhon',
age: 25
}

let age = _.pick(obj, 'age');
console.log(age); // {age: 25}
方式4: 递归遍历
var oldObj = {
  name: "Baba",
  age: 20,
  weather: {
    today: "sun",
    tomorrow: "rain"
  }
}
var newObj = {};

function deepClone(newObj, oldObj) {
  for (let k in oldObj) {
    let el = oldObj[k];
    if (el instanceof Array) {
      newObj[k] = [];
      deepClone(newObj[k], el);
    } else if (el instanceof Object) {
      newObj[k] = {};
      deepClone(newObj[k], el);
    } else {
      newObj[k] = el;
    }
  }
  return newObj;
}
newObj = deepClone(newObj, oldObj);

console.log(deepClone);
console.dir(deepClone);
console.log("-----------------------------");
newObj.say = "我是新对象:怎么呢?";
newObj.weather.today = "我是新对象:怎么呢?";
console.log(newObj);
console.log(oldObj);

Author: xt_xiong
转载要求: 如有转载请注明出处 :根据 CC BY 4.0 告知来自 xt_xiong !
评论
  标题