zoukankan      html  css  js  c++  java
  • 【函数】深拷贝和浅拷贝

    目录:

    1、深拷贝与浅拷贝

    2、浅拷贝实现

    3、深拷贝实现

    深拷贝与浅拷贝

    传值与传址

      相关笔记:https://www.cnblogs.com/xiaoxuStudy/p/12185177.html

      原始数据类型的拷贝是传值,应用数据类型的拷贝是传址。

    深拷贝与浅拷贝

      因为原始类型的拷贝是传值,所以对于原始数据类型并没有深浅拷贝的区别。深浅拷贝都是对于引用数据类型而言的。

      深拷贝与浅拷贝的使用场景:1、都是复杂对象,即对象的属性还是对象

      如果要赋值对象的所有属性都不是引用类型的时候,可以使用浅拷贝,遍历并复制。

       

    浅拷贝实现

      浅拷贝只复制一层对象,当对象的属性是引用类型时,实质复制的是其引用,当引用值指向发生改变时,也会跟着改变。

    使用 for-in

      下面实现一个浅拷贝:

    //实现浅拷贝
    let shallowCopy = obj => {
        let rst = {};
        //遍历对象
        for(let key in obj){
            //只复制本身拥有的(非继承过来的)枚举属性
            if(obj.hasOwnProperty(key)){
                rst[key] =  obj[key];
            }
        }
        return rst;
    }
    let star = {
        name:'虞书欣',
        age : 20,
        //又是一个对象
        friend : {
            name : '孔雪儿'
        }
    }
    let otherStar = shallowCopy(star);
    otherStar.name = '刘雨昕';
    otherStar.age = '22';
    otherStar.friend.name = '金子涵';
    console.log( star );
    

     输出:

    { name: '虞书欣', age: 20, friend: { name: '孔雪儿' } }

      上面创建一个 shallowCopy 函数,传入一个对象作为参数,该函数遍历该对象将该对象的属性复制到一个空对象 rst 中,最后返回 rst 对象。创建一个star 对象, 注意这里 star 对象有一个属性 friend, friend 是引用类型,将 star 作为参数传给 shallowCopy 函数,shallowCopy 函数返回一个 rst 对象,otherStar 指向 rst 对象。这里看一下修改 otherStar 会不会影响到 star 。修改 otherStar 的 name 属性、age 属性跟 friend 属性的对象的 name 属性。输出 star 发现 friend 属性改变了,name属性跟age属性都没有变。

      所以,要记得:浅拷贝只复制一层对象,当对象的属性是引用类型时,实质复制的是其引用,当引用值指向发生改变时,也会跟着改变。

      用 Object.assign() 拷贝也是一样。

    使用 Object.assign( )

    let xiaoxu = {
        name:'小许',
        info:{
            gender:'女',
            hobby:'sleep'
        }
    }
    let a = Object.assign( {}, xiaoxu );
    a.name = "nana";
    console.log( xiaoxu.name );         //没变  //输出:小许
    a.info.gender = '男';
    console.log( xiaoxu.info.gender );  //变了  //输出:男

    使用对象的扩展运算符

    扩展运算符的 value 是原始数据类型的时候,是深拷贝。当 value 是引用类型的时候,是浅拷贝。

    let xiaoxu = {
        name:'小许',
        info:{
            gender:'女',
            hobby:'sleep'
        }
    }
    let a = { ...xiaoxu };
    a.name = "nana";
    console.log( xiaoxu.name );         //没变  //输出:小许
    a.info.gender = '男';
    console.log( xiaoxu.info.gender );  //变了  //输出:男
    

      

    深拷贝实现

      深复制递归复制了所有层级。

    使用 JSON.stringify()

    注意:如果需要拷贝的是纯的JSON数据,不需要循环引用,可以使用 JSON.stringify 实现。

    let obj = {
        name : '小明',
        songs : ['想见你想见你想见你', '暮阳少年']
    }
    
    let obj1 = JSON.parse(JSON.stringify(obj));
    obj1.name = '小华';
    obj1.songs[0] = '飘';
    
    let girl = [{
        name : '小许',
        colors : ['black','pink'],
        fn : function(){},
        age : undefined
    }]
    
    let boy = JSON.parse(JSON.stringify(girl));
    console.log(boy);   //输出:[ { name: '小许', colors: [ 'black', 'pink' ] } ]
    

    使用递归

    let deepClone = obj => {
        let newObj = Array.isArray(obj) ? [] : {};
        
        if( obj && typeof obj === 'object' ){
            for( let key in obj ){
                if( obj.hasOwnProperty(key) ){
                    //如果对象的属性是引用类型
                    if( obj[key] && typeof obj[key] ){
                        newObj[key] = deepClone(obj[key]);
                    }else{
                    //如果对象的属性不是引用类型,直接拷贝
                    newObj[key] = obj[key];
                    }
                }
            }
        }
        return newObj;
    }
    let xiaoxu = {
        name :'xiaoxu',
        idols : ['虞书欣','刘雨昕'],
        fn : function(){},
        age : undefined
    }
    let girl = deepClone(xiaoxu);
    girl.name = 'nana';
    girl.idols = ['林宥嘉','JonyJ'];
    girl.fn = '亲一口=3=';
    girl.age = 20;
    console.log(xiaoxu); 
    console.log(girl);
    

     输出:

    混合模式 Mixin

    不通过继承去扩展方法

    let mixin = {
        say(){
            console.log(`${this.name}在说话`);
        },
        sing(){
            console.log(`${this.name}在唱歌`);
        },
        run(){
            console.log(`${this.name}在跑步`);
        }
    }
    
    class Student{
        constructor(name){
            this.name = name;
        }
    }
    
    Object.assign( Student.prototype, mixin );
    let student = new Student('小许');
    student.sing();     //输出:小许在唱歌
    

    为什么要把 mixin 复制到 prototype 上?因为这样子维护性好且减少内存占用。

    Vue 的混入(Mixin)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
        <script src="vue.js"></script>
    </head>
    <body>
        <div id="app">
            <h1>{{name}}..{{age}}</h1>
        </div>
        <script>
            Vue.mixin({
                data(){
                    return{
                        name:'小许'
                    }
                },
                methods:{
                    say(){
                        console.log('hello');
                    }
                }
            })
            new Vue({
                el:'#app',
                data(){
                    return{
                        age:22
                    }
                },
                mounted(){
                    this.say();
                }
            })
        </script>
    </body>
    </html>
    

    使用 pick

    先使用命令 yarn add -D underscore 安装 underscore 依赖

    const _ = require(`underscore`);    //引进underscore
    let obj = {
        name : '小许',
        age : 22
    }
    //返回一个 obj 的副本
    let age = _.pick(obj, 'age');
    console.log( age );     //输出:{ age: 22 }
    console.log( obj );     //输出:{ name: '小许', age: 22 }
    

     

  • 相关阅读:
    ABAP 更改DN外向交货单
    ABAP 参照SO item 创建DN
    ABAP 获取客户供应商的电话,地址,email等相关信息
    ABAP 自定义的ALV导出excel按钮,导出ALV内表中其中某几列的数据
    ABAP 后台JOB布置例子
    ABAP 选择屏幕字段动态隐藏和显示
    ABAP 选择屏幕上的导入模板下载按钮
    ABAP 选择屏幕文件导入时,单元格超50字符怎么处理
    ABAP 选择屏幕字段动态隐藏和显示
    人脸检测数据集
  • 原文地址:https://www.cnblogs.com/xiaoxuStudy/p/12724196.html
Copyright © 2011-2022 走看看