JavaScript基础教程 JavaScript深拷贝详解
沉沙 2018-07-23 来源 : 阅读 1100 评论 0

摘要:JavaScript深拷贝是初学者甚至有经验的开发者,都会经常遇到问题,希望阅读本篇文章以后大家有所收获,帮助大家对JavaScript的理解更加深入。

javascript深拷贝是初学者甚至有经验的开发者,都会经常遇到问题,并不能很好的理解javascript的深拷贝。

深拷贝(deepClone)?

与深拷贝相对的就是浅拷贝,很多初学者在接触这个感念的时候,是很懵逼的。

为啥要用深拷贝?

在很多情况下,我们都需要给变量赋值,给内存地址赋予一个值,但是在赋值引用值类型的时候,只是共享一个内存区域,导致赋值的时候,还跟之前的值保持一直性。

看一个具体的例子

// 给test赋值了一个对象

var test = {

a: 'a',

b: 'b'

};

 

// 将test赋值给test2

// 此时test和test2是共享了同一块内存对象,这也就是浅拷贝

var test2 = test;

 

test2.a = 'a2';

 

test.a === 'a2'// 为true

   

图解:

 

这下就很好理解为什么引用值类型数据相互影响问题。

实现

实现一个深拷贝函数,就不得不说javascript的数值类型。

判断javascript类型

使用typeof是无法判断function和array的,这里使用Object.prototype.toString方法。 默认情况下,每个对象都会从Object上继承到toString()方法,如果这个方法没有被这个对象自身或者更接近的上层原型上的同名方法覆盖(遮蔽),则调用该对象的toString()方法时会返回”[object type]”,这里的字符串type表示了一个对象类型

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)还需要再次遍历,递归赋值。

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就会执行一遍,不敢想象会有什么执行结果哦!o(╯□╰)o!其它暂时还没有什么好的想法,欢迎大家指导哦!

到这里差不多也就实现完了深拷贝,又有人觉的怎么没有实现浅拷贝呢?

浅拷贝?

对于浅拷贝而言,可以理解为只操作一个共同的内存区域!这里会存在危险!(。﹏。*) 。

如果直接操作这个共享的数据,不做控制的话,会经常出现数据异常,被其它部分更改。所以应该不要直接操作数据源,给数据源封装一些方法,来对数据来进行CURD操作。

到这里估计就差不多了,但是作为一个前端,不仅仅考虑javascript本身,还得考虑到dom、浏览器等。

Element类型

来看下面代码,结果会返回啥呢?

Object.prototype.toString.call(document.getElementsByTagName('div')[0])

   

答案是[object HTMLDivElement]

有时候保存了dom元素, 一不小心进行深拷贝,上面的深拷贝函数就缺少了对Element元素的判断。而判断Element元素要使用instanceof来判断。因为对于不同的标签,tostring会返回对应不同的标签的构造函数。

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)];

}

   

本文由职坐标整理发布,欢迎关注职坐标WEB前端JavaScript频道,获取更多JavaScript知识!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程