Javascript/js 的浅拷贝与深拷贝(复制)学习随笔

js变量的数据类型值分基本类型值和引用类型值。

在ES6(ECMAScript6)以前,基本数据类型包括String、Number、Boolean、Undefined、Null。

基本类型值的复制(拷贝)

从一个变量向另一个变量复制基本类型的值。使用赋值操作符 ‘ = ‘ 即可。

如:

1 var num1 = 1, num2;
2 num2 = num1;

上述代码定义了两个变量num1、num2。num1初始化值是1,num2是undefined。接着把num1赋值给num2。

num1的值与num2的值增删改减完全独立、互不影响。

1 ++num1;
2 num2 = null;
3 // 2 null

拓展:基于基本类型值,ES提供了三个特殊的引用类型。String、Number、Boolean。(基本包装类型)

1 var num3 = 3;
2 var num4 = num3.toFixed(2);
3 console.log(num3, num4); // 3 3.00

如上,变量num3包含一个数字值,数字当然属于基本类型值啦,接着num3调用了toFixed()方法。并将返回结果保存在num4中。最后在控制台输出下。结果是3 3.00。当然了,没有报错。。

一般来理解,基本类型值不是对象,不应该有方法。(但是它们确实有方法.。查看它们有哪些方法的一个办法是在chrome控制台console.log(new Number(1))。其他基本类型值同理。baidu/翻书/强记。do whatever you want)

当第二行代码访问num3时,访问过程处于一种读取模式,也就是从内存中读取这个变量的值。此时,在后台,大概是执行了下列的es代码:

1 var _num3 = new Number(3);// 创建Number类型的一个实例
2 var _num4 = _num3.toFixed(2);// 在实例上调用指定的方法
3 _num3 = null;// 销毁这个实例
4 return _num4;// 可以想象成在一个函数里执行这里的4行代码,函数返回_num4。接着被num4接收。

这也意味着我们可以对基本类型值做一些扩展。比如:

1 var num5 = 1;
2 Number.prototype.addTen = function () {
3   var res = this + 10;
4   return res;
5 };
6 console.log(num5.addTen());// 11    

如上,在Number原型上定义addTen()方法,所有Number类型值都可以调用这个方法。

其他基本类型值同理。

ES6规范引入了一项新特性--symbol,它也是一种基本数据类型,它的功能类似于一种标识唯一性的ID。

调用Symbol函数来创建一个Symbol实例:

1 const S1 = Symbol();
2 // 可以在调用Symbol函数时传入一个参数,相当于给你创建的Symbol实例一个描述信息。参数可选,可以是任意可转化成字符串的值。
3 const S2 = Symbol(‘id9527‘);

引用类型的复制(拷贝)

常见的引用类型包括 Object、Aarry、Date、Function、RegExp...

引用类型值是引用类型的一个实例。

通过赋值操作符‘=’复制的引用类型值。实际上复制的是一个指针(地址)。该指针指向存储在堆中的对象。

1 const obj1 = new Object();
2 const obj2 = obj1;
3 obj1.name = ‘xm‘;
4 console.log(obj2.name);// xm

obj1与obj2指向同一个对象,对obj1的修改,同样作用于obj2。

多数时候这不是我们想要的结果。我们需要的是两个相互独立而又长得一模一样的对象。

由于引用类型值也可能包含引用类型值。由此就派生出了浅拷贝和深拷贝。

浅拷贝

数组的浅拷贝常用方法:

(1)concat方法

1 const arr1 = [‘a‘, ‘b‘, [‘c‘, 4]];
2 const arr2 = arr1.concat([]);
3 console.log(arr2, arr1 == arr2);// [‘a‘, ‘b‘, [‘c‘, 4]] false

(2)slice方法

1 const arr1 = [‘a‘, ‘b‘, [‘c‘, 4]];
2 const arr2 = arr1.slice(0);
3 console.log(arr2, arr1 == arr2);// [‘a‘, ‘b‘, [‘c‘, 4]] false

(3)扩展运算符...方法

1 const arr1 = [‘a‘, ‘b‘, [‘c‘, 4]];
2 const arr2 = [...arr1];
3 // const [...arr2] = arr1; // 等同于上一行
4 console.log(arr2, arr1 == arr2);// [‘a‘, ‘b‘, [‘c‘, 4]] false

(4)map方法

1 const arr1 = [‘a‘, ‘b‘, [‘c‘, 4]];
2 const arr2 = arr1.map(item => item);
3 console.log(arr2, arr1 == arr2);// [‘a‘, ‘b‘, [‘c‘, 4]] false

(5)filter方法 把上面的map改成filter即可。

...for循环、forEach、for of、splice、Object.values等方法均可。

对象的浅拷贝常用方法:

1、for in遍历方法

 1 const obj = {
 2   say(){
 3     console.log(‘hello‘);
 4   }
 5 };
 6 const obj1 = Object.create(obj);
 7 obj1.a = ‘对象‘;
 8 obj1.b = [1, 2, 3];
 9
10 // const obj2 = Object.create(obj); // 继承obj的属性、方法
11 const obj2 = {};
12 for (let p in obj1) {
13   if (obj1.hasOwnProperty(p)) {
14     obj2[p] = obj1[p];
15   }
16 }

如上,obj1的原型对象是obj,浅拷贝一般不需要拷贝原型上的属性和方法,而for in循环可以枚举原型上的属性和方法。使用hasOwnProperty()方法过滤掉原型的属性和方法。

结果如下:

(2)Object.entries()方法

 1 const obj = {
 2   say(){
 3     console.log(‘hello‘);
 4   }
 5 };
 6
 7 const obj1 = Object.create(obj);
 8 obj1.a = ‘对象‘;
 9 obj1.b = [1, 2, 3];
10
11 // const obj2 = Object.create(obj); // 继承obj的属性、方法
12 const obj2 = {};
13 Object.entries(obj1).forEach(([key, value]) => obj2[key] = value);

结果如下:

之所以称为浅拷贝,其原因在于如果引用类型值里包含引用类型值,上述的所有方法,在对里层的引用类型值复制操作时,使用的还是赋值操作符‘=‘。如下所示:

如果修改了obj1.b的值,同样会作用于obj2。

深拷贝

以下是实现对数组、对象深拷贝的一种方法。

采用递归的方式,层层遍历。

 1 const deepClone = function handleDeepClone(obj) {
 2   if (typeof obj !== ‘object‘ || obj === null) {
 3     return obj;
 4   }
 5
 6   let _obj;
 7   if (obj instanceof Array) {
 8     _obj = [];
 9     obj.forEach((item, i) => _obj[i] = handleDeepClone(item));
10   } else {
11     _obj = {};
12     Object.entries(obj).map(([key, value]) => _obj[key] = handleDeepClone(value));
13   }
14
15   return _obj;
16 };

结果如下:

原文地址:https://www.cnblogs.com/caimuguodexiaohongmao/p/11108217.html

时间: 2024-11-10 11:55:29

Javascript/js 的浅拷贝与深拷贝(复制)学习随笔的相关文章

js对象浅拷贝和深拷贝详解

js对象浅拷贝和深拷贝详解 作者:i10630226 字体:[增加 减小] 类型:转载 时间:2016-09-05我要评论 这篇文章主要为大家详细介绍了JavaScript对象的浅拷贝和深拷贝代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var

Javascript中的浅拷贝和深拷贝

很多开发语言中都有浅拷贝和深拷贝的说法,这里简单区分一下它们在Javascript中的区别,以及jQuery中深拷贝的实现. 在谈浅拷贝和深拷贝之前,先要屡清楚Javascript中的按值访问和按引用访问这两个概念. 按值访问是针对基本类型(string.number.boolean.null.undefined).基本类型以值的形式被存放在栈内存中,我们通过变量操作的是栈内存中实际的值. 按引用访问时针对引用类型(Object.Array.Date.RegExp.Function).引用类型以

js实现浅拷贝和深拷贝

浅拷贝和深拷贝都只针对于像Object, Array这样的复杂对象, 区别:浅拷贝只复制对象的第一层属性.深拷贝可以对对象的属性进行递归复制 如果数组元素是基本类型,就会拷贝一份,互不影响,而如果是对象或者数组,就会只拷贝对象和数组的引用,这样我们无论在新旧数组进行了修改,两者都会发生变化,这种叫浅拷贝. 深拷贝就是指完全的拷贝一个对象,即使嵌套了对象,两者也相互分离,修改一个对象的属性,也不会影响另一个. 一.浅拷贝 1.数组的浅拷贝 (1).可用concat.slice返回一个新数组的特性来

js中浅拷贝和深拷贝以及深拷贝的实现

前言:2019年的第一篇分享... 一.什么是基本类型值和引用类型值?ECMAScript包括两个不同类型的值:基本数据类型和引用数据类型.基本数据类型指的是简单的数据段,引用数据类型指的是有多个值构成的对象.当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值. 注:要了解深拷贝和浅拷贝,首先要先理解ECMAScript中的数据类型,其中基本类型值(如undefined.null.number.string.boolean以及es6新增的Symbol), 还有一

小tips:JS之浅拷贝与深拷贝

浅拷贝: function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } return c; } 深拷贝: function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c

JavaScript对象的浅拷贝与深拷贝

1.JS包含两种数据类型: 值类型(基本类型)和引用类型(对象类型) 值类型都是简单的数据段(Number.String .Boolean.Null.Undefined),引用类型是由多个值构成对象(Object .Array .Function .Data等). 我们进行变量赋值时,解析器首先要确认的就是这个值是基本类型还是引用类型. 值类型数据存储在栈(stack)中,栈是内存中一种特殊的数据结构,也称为线性表.变量的位置和变量值的位置是重叠的,也就是说值类型的数据被存储在变量被访问的位置.

JS的浅拷贝与深拷贝

浅拷贝 //这样的拷贝有一个问题.那就是,如果父对象的属性等于数组或另一个对象,//那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能. function extendCopy(o) { var copy = {}; for (var i in o) { cppy[i] = o[i]; } return copy; } 深拷贝 //就是能够实现真正意义上的数组和对象的拷贝.它的实现并不难,只要递归调用"浅拷贝"就行了. function deepCop

js的浅拷贝和深拷贝

转载:http://www.jb51.net/article/91906.htm //深拷贝,并且把合并后的值放到第二个参数里 function deepCopy(p, c) { var c = c || {}; for (var i in p) { if (typeof p[i] === 'object') { c[i] = (p[i].constructor === Array) ? [] : {}; deepCopy(p[i], c[i]); } else { c[i] = p[i]; }

javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法

javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法 前言 在js中,数组和对象的复制假设使用=号来进行复制.那仅仅是浅拷贝. 例如以下图演示: 如上.arr的改动,会影响arr2的值,这显然在绝大多数情况下,并非我们所须要的结果. 因此,数组以及对象的深拷贝就是javascript的一个基本功了. 数组的深拷贝 条条大道通罗马,实现数组的深拷贝.是有好几种方法的.举比例如以下: for 循环实现数组的深拷贝 for循环是很好用的.假设不知道高级方法.通过for循环可以完毕我们