引用值的复制、浅拷贝、深拷贝

2020-09-14  本文已影响0人  云凡的云凡
vue 中父组件通过 v-bind 属性 给子组件传值,子组件通过 props(可以是对象或者数组) 接收,子组件不能修改父组件传过来的值,可以在 data 函数中 新定义一个变量,把传过来的值拷贝到新定义的变量上。当遇到对象时候,就用深拷贝靠谱点。
所以我们来说说引用值的复制、浅拷贝、深拷贝

1.复制 :其中一个改变,其它跟着变(只是多了一个变量指向那个空间)

 var cat1 = {
            name: '天天',
            Borth: 2019,
            hobby: 'eat fish',
            friends: '大黑',
            son: {
                oone: '小花',
                two: '小淘气',
                girlFriend: {
                    name: '一一',
                    age: 25
                },
                car: '本田'
            }
        }
       // 1.复制
        var cat2 = cat1
        console.log(cat1 === cat2);  //true
        console.log(cat1 == cat2);   //true
        //因为对象是传址的,var cat2 = cat1 只是把对象 cat1 的指针传给 cat2 ,
        // 它们指向的是同一块内存区域,所以 cat1 和 cat2 的值和类型都相等


        cat2.name = '王王'
        cat2.son.oone = '小李'
        console.log(cat1 === cat2);   //true
        console.log(cat1 == cat2);  //true
        // 当cat2 改变,cat1也会跟着改变。当改变 cat1 时,cat2 也会改变,所以他们的值和类型还是一样。

2.浅拷贝:并没有把对象的引用值处理,值处理了第一层的属性,并没有处理下面的引用值。

    <script>
       Object.prototype.num = 1
        var cat1 = {
            name: '天天',
            Borth: 2019,
            hobby: 'eat fish',
            friends: '大黑',
            son: {
                oone: '小花',
                two: '小淘气',
                girlFriend: {
                    name: '一一',
                    age: 25
                },
                car: '本田'
            }
        }


        var cat2 = {}
        // 2.浅拷贝
        simpleClone(cat1, cat2)
        function simpleClone(origin, target) {
             // var target = target || {}
            for (var key in cat1) {
               //把原型剔除出去
                if (origin.hasOwnProperty(key)) {
                    target[key] = origin[key]
                }
            }
        }
     
        console.log(cat1 === cat2);  //false
        console.log(cat1 == cat2);  //false

        // 当改变对象里面引用值的时候:另一个会跟着改变
        cat1.son.two = '淘气'
        console.log(cat1.son.two); //淘气
        console.log(cat2.son.two);  //淘气
        console.log(cat1 === cat2);   //false
        console.log(cat1 == cat2);       //false

        // 当改变对象里的基础类型:另一个不会跟着改变
        cat1.Borth = 2020
        console.log(cat1.Borth);  //2020
        console.log(cat2.Borth);  //2019
        console.log(cat1 === cat2);   //false
        console.log(cat1 == cat2);   //false
    </script>

3.深拷贝:有引用值的时候就要做一系列遍历,在循环的时候去判断里面的每一项键值对是不是引用值,是引用值的时候再判断是数组函数对象,用一个递归的克隆函数来进行再处理。

 <script>
        Object.prototype.num = 1
        var cat1 = {
            name: '天天',
            Borth: 2019,
            hobby: 'eat fish',
            friends: '大黑',
            son: {
                oone: '小花',
                two: '小淘气',
                girlFriend: {
                    name: '一一',
                    age: 25
                },
                car: '本田'
            }
        }

        var cat2 = deepClone(cat1)
        console.log(cat2);
        cat2.name = 'zhangsan'
        cat2.son.two = '李四'
        console.log(cat1);
        console.log(cat2);

        function deepClone(origin, target) {
            var target = target || {}
            toStr = Object.prototype.toString
            arrType = '[object Array]'
            for (var key in origin) {
                if (origin.hasOwnProperty(key)) {
                    if (typeof (origin[key] === 'object') && origin[key] !== null) {
                        if (toStr.call(origin[key]) === arrType) {
                            target[key] = []
                        } else {
                            target[key] = {}
                        }
                        deepClone(origin[key], target[key])
                    } else {
                        target[key] = origin[key]
                    }
                }
            }
            return target
        }
    </script>

或者

export const getObjType = obj => {
    let toString = Object.prototype.toString
    let 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)]
}

export const deepClone = data => {
    let type = getObjType(data)
    let obj
    if (type === 'array') {
        obj = []
    } else if (type === 'object') {
        obj = {}
    } else {
        // 不再具有下一层次
        return data
    }
    if (type === 'array') {
        for (let i = 0, len = data.length; i < len; i++) {
            obj.push(deepClone(data[i]))
        }
    } else if (type === 'object') {
        for (let key in data) {
            obj[key] = deepClone(data[key])
        }
    }
    return obj
}

4.json深拷贝:不常用,因为json数据没有方法

 <script>
        var cat1 = {
            name: '张三',
            Borth: 2019,
            hobby: '乒乓球',
            friends: '李四',
            son: {
                oone: '小花',
                two: '小淘气',
                girlFriend: {
                    name: '一一',
                    age: 25
                },
                car: '本田'
            },
            eat: ['鱼', '胡萝卜', '玉米']
        }
        var str = JSON.stringify(cat1)  //把对象转换成字符串,这样就不是引用值了
        var cat2 = JSON.parse(str)
        cat2.name = '王五'
        cat2.eat.push('土豆')
        var cat2 = JSON.parse(str)
        console.log(cat1, cat2)
        console.log(cat1 === cat2); //false
        console.log(cat1 == cat2); //false
    </script>
上一篇下一篇

猜你喜欢

热点阅读