目录一.数据类型二.浅拷贝与深拷贝三.赋值和浅拷贝的区别四.浅拷贝的实现方式五.深拷贝的实现方式一.数据类型

  数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。

  基本数据类型:

  访问:基本数据类型的值是按值访问的。

  存储:基本类型的变量是存放在栈内存(Stack)里的。

  图解 : 栈内存中包括了变量的标示符和变量的值。

  引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

  引用数据类型在栈中储存了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获取实体。

  访问:引用类型的值是按引用访问的。

  存储:引用类型的值是保存在堆内存(Heap)中的对象(Object)。

  图解:

  栈内存中包含了变量的标示符和指向堆内存中该对象的指针

  堆内存中包含了对象的内容

  image

  JavaScript 不能直接操作对象的内存空间(堆内存)一.浅拷贝与深拷贝

  深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。

  深拷贝和浅拷贝的示意图大致如下:

  image

  浅拷贝只复制指向某个对象的指针,而不是复制对象本身 新旧对象还是共享同一块内存。

  但深拷贝会另外创造一个一摸一样的对象, 新对象跟原对象不共享内存,修改新对象不会改到原对象。三.赋值和浅拷贝的区别

   // 对象赋值

 var obj1 = {
  'name' : 'zhangsan',
  'age' :  '18',
  'language' : [1,[2,3],[4,5]],
 };
 var obj2 = obj1;
 obj2.name = "lisi";
 obj2.language[1] = ["二","三"];
 console.log('obj1',obj1)
 console.log('obj2',obj2)

  image

   // 浅拷贝

 var obj1 = {
  'name' : 'zhangsan',
  'age' :  '18',
  'language' : [1,[2,3],[4,5]],
 };
  var obj3 = shallowCopy(obj1);
  obj3.name = "lisi";
  obj3.language[1] = ["二","三"];
  function shallowCopy(src) {
  var dst = {};
  for (var prop in src) {
if (src.hasOwnProperty(prop)) {
 dst[prop] = src[prop];
}
  }
  return dst;
 }
 console.log('obj1',obj1)
 console.log('obj3',obj3)

  image

  上面例子中,obj1是原始数据,obj2是赋值操作得到,而obj3浅拷贝得到。我们可以很清晰看到对原始数据的影响,具体请看下表:

  image

  四.浅拷贝的实现方式

  1.Object.assign()

  Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象js array slice 浅拷贝,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

  (知识点)化学实验基本内存的实现方式与图解

   var obj = { a: {a: "xxxc", b: 19} };

 var initalObj = Object.assign({}, obj);
 initalObj.a.a = "wewd";
 console.log(obj.a.a); //wewd

  注意:当object只有一层的时候js array slice 浅拷贝,是深拷贝

   let obj = {

 username: 'jsx'
  };
 let obj2 = Object.assign({},obj);
 obj2.username = 'wawa';
 console.log(obj);//{username: "jsx"}

  2.Array.prototype.concat()

   let arr = [1, 3, {

 username: 'kobe'
  }];
 let arr2=arr.concat(); 
 arr2[2].username = 'wade';
 console.log(arr);

  修改新对象会改到原对象:

  example

  3.Array.prototype.slice()

   let arr = [1, 3, {

 username: ' kobe'
  }];
 let arr3 = arr.slice();
 arr3[2].username = 'wade'
 console.log(arr);

  修改新对象会改到原对象:

  image

  Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。

  原数组的元素会按照下述规则拷贝:

   let arr = [1, 3, {

 username: ' kobe'
  }];
 let arr3 = arr.slice();
 arr3[1] = 2
 console.log(arr,arr3);

  image

  五.深拷贝的实现方式

  1.递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝

   var deepCopy = function(obj) {

 if (typeof obj !== 'object') return obj //判断不是object就直接返回
  var newObj = (Object.prototype.toString.call(obj) === '[object Array]') ? [] : {} //判断复制的目标是数组还是对象
  for (var key in obj) {
if (obj.hasOwnProperty(key)) {
 newObj[key] = (typeof obj[key] !== 'object') ? obj[key]: deepCopy(obj[key]) // 如果值是对象,就递归一下。 如果不是,就直接赋值
}
  }
  return newObj
 }

  就这么简单。

  (知识点)化学实验基本内存的实现方式与图解

  类似的方法都是挺雷同的

   function deepClone(source){

const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
for(let keys in source){ // 遍历目标
  if(source.hasOwnProperty(keys)){
 if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
 }else{ // 如果不是,就直接赋值
targetObj[keys] = source[keys];
 }
  }
}
return targetObj;
 }  
 /*原理都一样*/
 var  deepClone=function(source) {
if (!source && typeof source !== 'object') {
  throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
  if (source[keys] && typeof source[keys] === 'object') {
 targetObj[keys] = deepClone(source[keys])
  } else {
 targetObj[keys] = source[keys]
  }
})
return targetObj
 }

  2.除此之外还有 函数库 lodash

  该函数库也有提供_.cloneDeep用来做 Deep Copy

   var _ = require('lodash');

 var obj1 = {
  a: 1,
  b: { f: { g: 1 } },
  c: [1, 2, 3]
 };
 var obj2 = _.cloneDeep(obj1);
 console.log(obj1.b.f === obj2.b.f);
 // false

  JSON.parse(JSON.stringfify(obj))

  3.JSON.parse(JSON.stringfify(obj))

  原理:

  用JSON.stringify将对象转成JSON字符串,

  再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

  可以实现数组或对象深拷贝,但不能处理函数

  因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数

  可以自行试验 就不做图例了,太懒了

TAGS:js array slice 浅拷贝 js深拷贝和浅拷贝的区别 js深拷贝和浅拷贝 拷贝
!如链接失效请在下方留言。本站所有资源均来源于网络,版权属于原作者!仅供学习参考,本站不对您的使用负任何责任。如果有侵权之处请第一时间联系我们删除,敬请谅解!