JavaScript深拷贝、浅拷贝和负值区别

深、浅拷贝和赋值

首先说明一下,深拷贝、浅拷贝和等号负值的区别是建立在对引用数据类型(对象,数组)进行拷贝时候的说法。然后说明一下拷贝,这里的拷贝指的你想创建一个新的数据b,这个数据b除了名字不一样和其他的原数据a一模一样,注意两个点:
(1)创建一个新数据b,b和a是两个独立的个体。
(2)a和b的所包含的内容完全一致。
再然后举个例子说明一下深拷贝、浅拷贝和等号负值的区别。

话说
尼古拉斯赵四是象牙山响当当的人物,舞步独步天下。
于是乎人们为他起了各种绰号,亚洲舞王、象牙山郭富城等等。亚洲舞王是赵四的一个代号,就像他的本名赵四一样,都可以指代他。换句话来说,赵四、亚洲舞王、象牙山郭富城指的是同一个人,你去刘老根大舞台说找赵四、找尼古拉斯赵四、找亚洲舞王,最终找到的都是同一人。当你为赵四起名亚洲舞王的过程,就相当于等号负值

let ZhaoSi = {
	name: 'zhaosi',
	hobby: 'dance',
	mind:[‘舞步1,‘舞步2,‘舞步3]};
//等号赋值(给赵四起名亚洲舞王)
let AsiaDancer = ZhaoSi;

这个过程中只有赵四一人,没有新的人产生,你只是为他起了个能找到他的新名字。即:此时AsiaDancer 中保存的是ZhaoSi这个对象的引用,AsiaDancer和ZhaoSi两者指的是同一个对象。
现在出现了一个问题:假若有一天赵四这个人会不跳舞了,他喜好变为唱歌,此时不管是你使用赵四还是亚洲舞王找到的这个人,都无法从他的hobby中找到dance了,即:

let ZhaoSi = {
	name: 'zhaosi',
	hobby: 'dance',
	mind:[‘舞步1,‘舞步2,‘舞步3]};
//等号赋值(给赵四起名亚洲舞王)
let AsiaDancer = ZhaoSi;
// 修改爱好为唱歌
ZhaoSi.hobby = 'sing';
console.log(ZhaoSi.hobby); // sing
console.log(AsiaDancer.hobby); // sing

可以看到console.log的输出结果均为sing,因为AsiaDancer和ZhaoSi所指向的数据是同一个对象,这个对象本身改变了。
··································································································
然后看第二段故事-----浅拷贝
话说,
赵四凭借着卓越的舞技,成为很多娱乐公司的红人。为了更好分发挥赵四的舞蹈天分,科学家为赵四打造了几台仿生躯体(就叫做复制体1,复制体2…等),这些躯体严格按照赵四相貌身材去打造,从外观上看和赵四一模一样,这些机器人没有大脑,无法读取到各种舞蹈的舞步,但是他们的内部有接受信号的芯片,可以连接到赵四的大脑,赵四可以通过自身大脑中的各种舞步记忆来控制机器复制体们跳出跟他自己一样卓越的舞步,从此可以让多个地区的观众一饱舞王的眼福。注意,这个故事中的机器人都是赵四的复制体,他们是半独立的,他们的外表和躯体都和赵四完全一样,但是没有内部,内部其实都还是链接到赵四本人的。注意:此时的复制体都是新的个体,但是他们和主体赵四和存在联系,不能独立的进行舞蹈行为。这个过程类似于浅拷贝。 浅拷贝真正拷贝复制的是引用数据类型的第一层,再往下便不会复制(复制体只有赵四一样的躯体和外表,并没有赵四的大脑和脑中的各种舞步)。此时若是修改数据除了第一层以外内容(比如第二层),所有复制数据都会受影响,但修改第一层的内容不会,上代码:

let ZhaoSi = {
	name: 'zhaosi',
	hobby: 'dance',
	mind:[‘舞步1,‘舞步2,‘舞步3]};
// 浅拷贝方法
function shallowCopy(src) {
    var dst = {};
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            dst[prop] = src[prop];
        }
    } 
    return dst;
}
var copyMan1 = shallowCopy(ZhaoSi ); // 使用浅拷贝创建复制体1

copyMan1.hobby = 'sing';
console.log(ZhaoSi.hobby); // dance  未变
console.log(copyMan1.hobby); // sing 变了

copyMan1.mind[1]= '舞步10086';
console.log(ZhaoSi.mind); // [‘舞步1’,‘舞步10086’,‘舞步3’]  变了
console.log(copyMan1.mind); // [‘舞步1’,‘舞步10086’,‘舞步3’]  变了

上述代码中我们可以清楚的看到两次修改后变化的不同。
··································································································
第三段故事-----深拷贝
科学家们觉得故事二中的复制体们并不完美,于是他们利用超越复制技术的更高深的技术,制造了几个真正的克隆体(姑且叫做赵四1、赵四2…)。这几个克隆体不仅从外表身躯上和赵四一致,连大脑、思考和灵魂都与赵四一样。赵四1、赵四2这些克隆体是全新的个体,他们可以独立的跳舞,他们拥有赵四所有的舞步记忆和天赋,而且当赵四1学习了新舞步10010替换掉舞步3后,并不影响赵四和赵四2继续跳舞步3,这个过程类似于深拷贝,看代码:

let ZhaoSi = {
	name: 'zhaosi',
	hobby: 'dance',
	mind:[‘舞步1,‘舞步2,‘舞步3]};
// 深拷贝方法
function deepClone(obj) {
    let copy = obj instanceof Array? [] : {};
    for (let i in obj) {
        if (obj.hasOwnProperty(i)) { // 过滤掉继承属性
            copy[i] = typeof copy[i] === 'object'? deepClone(copy[i]) : copy[i];
        }
    } 
    return copy;
}
var cloneMan1 = deepClone(ZhaoSi ); // 使用深拷贝创建克隆体1
var cloneMan2 = deepClone(ZhaoSi ); // 使用深拷贝创建克隆体2

cloneMan1.hobby = 'sing';
console.log(ZhaoSi.hobby ); // dance  未变
console.log(cloneMan1.hobby ); // sing  变了
console.log(cloneMan2.hobby ); //dance  未变

cloneMan1.mind[2] = '舞步10010';
console.log(ZhaoSi.mind); // [‘舞步1’,‘舞步2’,‘舞步3’]  没变
console.log(cloneMan1.mind); // [‘舞步1’,‘舞步2’,‘舞步10010’]  变了
console.log(cloneMan2.mind); // [‘舞步1’,‘舞步2’,‘舞步3’]  没变

可以看到无论是对cloneMan1中第一层内容hobby的修改,还是对第二层内容mind中舞步的修改,都不会影响到赵四本身和其他克隆体的内容。每一个克隆体都是独立且完整的赵四复刻体。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这时有同学会问这是什么原理呢?在实际情况中,当你创建一个引用数据类型(比如一个对象a)的时候,系统会在堆中开辟一块内存从来存储对象a,在栈中会有对象a的引用。当你进行深拷贝的时候,即var b = deepClone(a );执行后,系统会新开辟一块内存,新开辟的内存中保存着和之前 a对象中所有内容,然后让b去指向这个新开辟的内存。此时a和b指向的是两个不同的内存区域,所以他们之间相互独立,只是存储的信息相同而已。同样,等号赋值和浅拷贝二层及以上层内容仅仅是拷贝了一个引用,并没有开辟新的内存区域来存放数据。

浅拷贝实现方法

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

var obj = { a: {a: "kobe", b: 39} };
var initalObj = 
Object.assign({}, obj);
initalObj.a.a = "wade";
console.log(obj.a.a); //wade

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

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

2、Array.prototype.concat()

let arr = [1, 3, {    username: 'kobe'    }];
let arr2=arr.concat();    

深拷贝实现方法

1、JSON.parse(JSON.stringify())

let arr = [1, 3, {    username: ' kobe'}];
let arrCopy = JSON.parse(JSON.stringify(arr));

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

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

//定义检测数据类型的功能函数
    
function checkedType(target) {
    return Object.prototype.toString.call(target).slice(8, -1)
}
    
//实现深度克隆---对象/数组
    
function clone(target) {
      
    //判断拷贝的数据类型
      
    //初始化变量result 成为最终克隆的数据
      
    let result, targetType = checkedType(target)
      
    if (targetType === 'object') {
        result = {}
     } else if (targetType === 'Array') {
        result = []
      } else {
        return target
      }
      
    //遍历目标数据
    for (let i in target) {
        //获取遍历数据结构的每一项值。
        let value = target[i]
        //判断目标结构里的每一值是否存在对象/数组
        if (checkedType(value) === 'Object' ||
          checkedType(value) === 'Array') { //对象/数组里嵌套了对象/数组
          //继续遍历获取到value值
          result[i] = clone(value)
        } else { //获取到value值是基本的数据类型或者是函数。
          result[i] = value;
        }
      }
      return result
}

如有错误,欢迎指正

智慧旅游解决方案利用云计算、物联网和移动互联网技术,通过便携终端设备,实现对旅游资源、经济、活动和旅游者信息的智能感知和发布。这种技术的应用旨在提升游客在旅游各个环节的体验,使他们能够轻松获取信息、规划行程、预订票务和安排食宿。智慧旅游平台为旅游管理部门、企业和游客提供服务,包括政策发布、行政管理、景区安全、游客流量统计分析、投诉反馈等。此外,平台还提供广告促销、库存信息、景点介绍、电子门票、社交互动等功能。 智慧旅游的建设规划得到了国家政策的支持,如《国家中长期科技发展规划纲要》和国务院的《关于加快发展旅游业的意见》,这些政策强调了旅游信息服务平台的建设和信息化服务的重要性。随着技术的成熟和政策环境的优化,智慧旅游的时机已经到来。 智慧旅游平台采用SaaS、PaaS和IaaS等云服务模式,提供简化的软件开发、测试和部署环境,实现资源的按需配置和快速部署。这些服务模式支持旅游企业、消费者和管理部门开发高性能、高可扩展的应用服务。平台还整合了旅游信息资源,提供了丰富的旅游产品创意平台和统一的旅游综合信息库。 智慧旅游融合应用面向游客和景区景点主管机构,提供无线城市门户、智能导游、智能门票及优惠券、景区综合安防、车辆及停车场管理等服务。这些应用通过物联网和云计算技术,实现了旅游服务的智能化、个性化和协同化,提高了旅游服务的自由度和信息共享的动态性。 智慧旅游的发展标志着旅游信息化建设的智能化和应用多样化趋势,多种技术和应用交叉渗透至旅游行业的各个方面,预示着全面的智慧旅游时代已经到来。智慧旅游不仅提升了游客的旅游体验,也为旅游管理和服务提供了高效的技术支持。
智慧旅游解决方案利用云计算、物联网和移动互联网技术,通过便携终端设备,实现对旅游资源、经济、活动和旅游者信息的智能感知和发布。这种技术的应用旨在提升游客在旅游各个环节的体验,使他们能够轻松获取信息、规划行程、预订票务和安排食宿。智慧旅游平台为旅游管理部门、企业和游客提供服务,包括政策发布、行政管理、景区安全、游客流量统计分析、投诉反馈等。此外,平台还提供广告促销、库存信息、景点介绍、电子门票、社交互动等功能。 智慧旅游的建设规划得到了国家政策的支持,如《国家中长期科技发展规划纲要》和国务院的《关于加快发展旅游业的意见》,这些政策强调了旅游信息服务平台的建设和信息化服务的重要性。随着技术的成熟和政策环境的优化,智慧旅游的时机已经到来。 智慧旅游平台采用SaaS、PaaS和IaaS等云服务模式,提供简化的软件开发、测试和部署环境,实现资源的按需配置和快速部署。这些服务模式支持旅游企业、消费者和管理部门开发高性能、高可扩展的应用服务。平台还整合了旅游信息资源,提供了丰富的旅游产品创意平台和统一的旅游综合信息库。 智慧旅游融合应用面向游客和景区景点主管机构,提供无线城市门户、智能导游、智能门票及优惠券、景区综合安防、车辆及停车场管理等服务。这些应用通过物联网和云计算技术,实现了旅游服务的智能化、个性化和协同化,提高了旅游服务的自由度和信息共享的动态性。 智慧旅游的发展标志着旅游信息化建设的智能化和应用多样化趋势,多种技术和应用交叉渗透至旅游行业的各个方面,预示着全面的智慧旅游时代已经到来。智慧旅游不仅提升了游客的旅游体验,也为旅游管理和服务提供了高效的技术支持。
深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值