关于
Javascript 深拷贝
javascript深拷贝是初学者甚至有经验的开发者,都会经常遇到问题,并不能很好的理解javascript的深拷贝。
深拷贝(deepClone)?
与深拷贝相对的就是浅拷贝,很多
HTML5课程
初学者在接触这个感念的时候,是很懵逼的。
为啥要用深拷贝?
在很多情况下,我们都需要给变量赋值,给内存地址赋予一个值,但是在赋值引用值类型的时候,只是共享一个内存区域,导致赋值的时候,还跟之前的值保持一直性。
看一个具体的例子
JavaScript
// 给test赋值了一个对象
var test = {
a: 'a',
b: 'b'
};
// 将test赋值给test2
// 此时test和test2是共享了同一块内存对象,这也就是浅拷贝
var test2 = test;
test2.a = 'a2';
test.a === 'a2'// 为true
// 给test赋值了一个对象
var test = {
a: 'a',
b: 'b'
};
// 将test赋值给test2
// 此时test和test2是共享了同一块内存对象,这也就是浅拷贝
var test2 = test;
test2.a = 'a2';
test.a === 'a2'// 为true
这下就很好理解为什么引用值类型数据相互影响问题。
实现
实现一个深拷贝函数,就不得不说javascript的数值类型。
判断javascript类型
javascript中有以下基本类型
类型
描述
undefinedundefined类型只有一个值undefined,它是变量未被赋值时的值
nullnull类型也只有一个值null, 它是一个空的对象引用
BooleanBoolean有两种取值true和false
String它表示文本信息
Number它表示数字信息
Object它是一系列属性的无序集合, 包括函数Function和数组Array
使用typeof是无法判断function和array的,这里使用Object.prototype.toString方法。 默认情况下,每个对象都会从Object上继承到toString()方法,如果这个方法没有被这个对象自身或者更接近的上层原型上的同名方法覆盖(遮蔽),则调用该对象的toString()方法时会返回”[object type]”,这里的字符串type表示了一个对象类型
JavaScript
function type(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
return map[toString.call(obj)];
}
function type(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
return map[toString.call(obj)];
}
实现deepClone
对于非引用值类型的数值,直接赋值,而对于引用值类型(object)还需要再次遍历,递归赋值。
JavaScript
function deepClone(data) {
var t = type(data), o, i, ni;
if(t === 'array') {
o = [];
}else if( t === 'object') {
o = {};
}else {
return data;
}
if(t === 'array') {
for (i = 0, ni = data.length; i < ni; i++) {
o.push(deepClone(data[i]));
}
return o;
}else if( t === 'object') {
for( i in data) {
o[i] = deepClone(data[i]);
}
return o;
}
}
function deepClone(data) {
var t = type(data), o, i, ni;
if(t === 'array') {
o = [];
}else if( t === 'object') {
o = {};
}else {
return data;
}
if(t === 'array') {
for (i = 0, ni = data.length; i < ni; i++) {
o.push(deepClone(data[i]));
}
return o;
}else if( t === 'object') {
for( i in data) {
o[i] = deepClone(data[i]);
}
return o;
}
}
这里有个点大家要注意下,对于function类型,博主这里是直接赋值的,还是共享一个内存值。这是因为函数更多的是完成某些功能,有个输入值和返回值,而且对于上层业务而言更多的是完成业务功能,并不需要真正将函数深拷贝。
但是function类型要怎么拷贝呢?
其实博主只想到了用new来操作一下,但是function就会执行一遍,不敢想象会有什么执行结果哦!其它暂时还没有什么好的想法,欢迎大家指导哦!
到这里差不多也就实现完了深拷贝,又有人觉的怎么没有实现浅拷贝呢?
浅拷贝?
对于浅拷贝而言,可以理解为只操作一个共同的内存区域!这里会存在危险!。
如果直接操作这个共享的数据,不做控制的话,会经常出现数据异常,被其它部分更改。所以应该不要直接操作数据源,给数据源封装一些方法,来对数据来进行CURD操作。
到这里估计就差不多了,但是作为一个前端,不仅仅考虑javascript本身,还得考虑到dom、浏览器等。
Element类型
来看下面代码,结果会返回啥呢?
JavaScript
Object.prototype.toString.call(document.getElementsByTagName('div')[0])
1
Object.prototype.toString.call(document.getElementsByTagName('div')[0])
答案是[object HTMLDivElement]
有时候保存了dom元素, 一不小心进行深拷贝,上面的深拷贝函数就缺少了对Element元素的判断。而判断Element元素要使用instanceof来判断。因为对于不同的标签,tostring会返回对应不同的标签的构造函数。
JavaScript
function type(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
if(obj instanceof Element) {
return 'element';
}
return map[toString.call(obj)];
}
function type(obj) {
var toString = Object.prototype.toString;
var map = {
'[object Boolean]' : 'boolean',
'[object Number]' : 'number',
'[object String]' : 'string',
'[object Function]' : 'function',
'[object Array]' : 'array',
'[object Date]' : 'date',
'[object RegExp]' : 'regExp',
'[object Undefined]': 'undefined',
'[object Null]' : 'null',
'[object Object]' : 'object'
};
if(obj instanceof Element) {
return 'element';
}
return map[toString.call(obj)];
}
分享到:
相关推荐
javascript深拷贝demo,有封装好的深拷贝函数和调用的demo
js考虑最完善的深拷贝函数,可以深拷贝引用对象和基本对象
JavaScript深拷贝的一些踩坑记录 之前去一家公司面试的时候,面试官问了我一个问题,说:"如何才能深拷贝一个对象"。当时我心里有些窃喜,这么简单的问题还用想吗?于是脱口而出:"平时常用的有两种办法,第一种用...
本文给大家详细讲述了javascript深拷贝、浅拷贝和循环引用的相关知识点,对此有兴趣需求的朋友学习下。
本文实例讲述了JavaScript深拷贝和浅拷贝概念与用法。分享给大家供大家参考,具体如下: js中的浅拷贝和深拷贝,只是针对复杂数据类型(Objcet,Array)的复制问题。简单来讲浅拷贝和深拷贝都可以实现在原有对象的基础...
深入了解JavaScript中的浅拷贝和深拷贝
深入剖析javascript中的深拷贝和浅拷贝1
主要介绍了javascript深拷贝(deepClone)详解的相关资料,需要的朋友可以参考下
因此对 JavaScript 中的复杂数据类型(object)来说,也会有浅拷贝和深拷贝的概念:浅拷贝指两个不同的变量存的是同一个对象的地址,即两个变量指向同一块内存区域;深拷贝则是重新分配了一块内
主要介绍了javascript深拷贝的原理与实现方法,简单分析了值传递和引用传递的原理与实现方法,并结合实例形式给出了深拷贝的具体实现技巧,需要的朋友可以参考下
目录 变量类型与存储空间栈内存和堆内存基本数据类型引用类型图解存储空间引用类型的赋值深拷贝和浅拷贝深拷贝浅拷贝对象的赋值三者对比浅拷贝的常用的五种方法Object.assign()扩展运算符Array.prototype.slice...
今天的学习笔记写在了自己的网页笔记本上,没有记录到博客,但是学到一个有关深拷贝的实现方法,为加深印象,这里给大家分享一下: 深拷贝:就是拷贝到最底层的属性。 function deepCopy(object){ //这里传入一个...
通过递归方式实现的深拷贝,支持对象和数组的深拷贝,其他类型数据会浅拷贝;支持父子元素循环引用
本文主要介绍了javascript深拷贝和浅拷贝的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
javascript中数组深拷贝途径及对象数组深拷贝 什么是浅拷贝 在js当中,我们常常遇到数组复制的的情况,许多人一般都会使用“=”来直接把一个数组赋值给一个变量,如: var a=[1,2,3]; var b=a; console.log(b); ...
深拷贝-ts 用于 typescript/javascript 的递归深拷贝、克隆和浅拷贝函数基于 MIT 和 LGPL 许可证可用。