关于
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中的深拷贝是开发过程中常见且重要的概念,主要用于创建一个与原对象具有相同属性和值的新对象,但不会因改变原始对象而影响复制对象。然而,深拷贝并不总是那么简单,尤其在处理特殊类型的对象时,可能会...
JavaScript中的深拷贝和浅拷贝是编程中常见的概念,主要涉及到对象和数组的复制。在JavaScript中,数据类型分为基本数据类型(如Number、String、Boolean等)和引用数据类型(如Object、Array等)。基本类型直接存储...
JavaScript中的深拷贝和浅拷贝是编程面试中常见的概念,尤其在处理对象和数组时至关重要。它们主要涉及的是变量赋值时数据的复制方式。简单来说,浅拷贝是创建了一个新对象,但它的属性仍然是对原对象属性的引用,而...
在JavaScript编程中,深拷贝和浅拷贝是两种常见的数据复制方法。深拷贝创建了一个新对象,这个新对象复制了原始对象的所有属性,并且这些属性的值都是原始对象属性值的副本,包括嵌套的对象和数组。这意味着对深拷贝...
本文实例讲述了JavaScript深拷贝和浅拷贝概念与用法。分享给大家供大家参考,具体如下: js中的浅拷贝和深拷贝,只是针对复杂数据类型(Objcet,Array)的复制问题。简单来讲浅拷贝和深拷贝都可以实现在原有对象的基础...
在JavaScript中,数组的深拷贝是一个常见的需求,它涉及到数据结构的复制,尤其是在处理复杂对象和嵌套数据时。深拷贝与浅拷贝不同,浅拷贝只是复制引用,而深拷贝会创建一个新的对象,包含原始数组的所有元素,并...
深入了解JavaScript中的浅拷贝和深拷贝
JavaScript中的深拷贝(Deep Clone)是编程中一个重要的概念,尤其在处理复杂的数据结构时。深拷贝意味着创建一个全新的对象,这个新对象包含了原对象的所有属性和子对象,而且这些属性和子对象也是独立的,修改新...
这篇博客“浅拷贝深拷贝之jQuery中的$.extend分析”深入探讨了`$.extend`在浅拷贝和深拷贝场景下的工作原理,这对于理解JavaScript对象的复制机制至关重要。 浅拷贝是指创建一个新对象,然后将源对象的引用属性复制...
JavaScript中的深拷贝是创建一个全新的对象,这个新对象与其原始对象具有相同的属性和值,但它们在内存中是独立的,互不影响。这与浅拷贝不同,浅拷贝只复制对象的引用,而不是创建完全独立的副本。在JavaScript中,...
浅拷贝和深拷贝各有适用场景。浅拷贝适用于只需复制对象第一层属性且不涉及修改引用类型属性的场景,而深拷贝适用于需要完全独立的数据副本,尤其是处理嵌套对象或数组时。在选择拷贝方法时,应根据实际需求和性能...
2. 手写深拷贝函数:可以通过递归遍历对象的每个属性,如果属性是对象,则继续调用深拷贝函数,从而实现深拷贝。这种方法可以处理更复杂的对象结构,但效率较低。 3. 使用第三方库如lodash的`_.cloneDeep()`:这类库...
在JavaScript编程中,"深拷贝"是一个非常重要的概念,特别是在处理复杂的数据结构时。深拷贝是指创建一个新对象,该对象复制了原始对象的所有属性,并且如果原始对象包含引用类型(如数组或对象),那么这些引用类型...
总结来说,浅拷贝和深拷贝是JavaScript中处理对象复制的关键概念,它们在处理复杂数据结构时尤为重要,特别是在需要保持原始数据不变性的场景下。了解和掌握这两种拷贝方式,能够帮助开发者更好地理解和控制对象之间...
总结一下,"deep-copy-ts"是一个专门针对typescript和javascript的深拷贝工具,它实现了递归深拷贝和浅拷贝功能,适用于处理复杂的对象和数组结构,同时兼容两种语言。通过使用这个库,开发者可以更轻松地管理对象的...