深拷贝及浅拷贝及相关内容

浅拷贝

            只拷贝第一层的值,其他后面拷贝的是地址。

        示例

            使用u盘在一台电脑上拷贝文件,使用浅拷贝拷贝的相当于快捷方式。
            第一层俩个内容不一样,其他每层都是指向同一个文件

        实现浅拷贝的方法

            Object.assign (实现浅拷贝)

                
               let obj = {
                    user:{
                        name:"jack"
                    }
                }
                //assign实现浅拷贝
                let copyObj = Object.assign({},obj)
                copyObj.user.name = 'tom'
                console.log(obj.user.name);
                console.log(copyObj.user == obj.user);//true    

 

            Array.prototype.concat

                
               let arr = [
                    {name:'jack'}
                ]
                //利用concat方法实现对应的浅拷贝
                let copyArr = arr.concat()
                console.log(arr[0] == copyArr[0]);
                console.log(copyArr == arr); //false

            Array.prototype.slice

              
               //slice 截取方法
                let sliceArr = arr.slice(0)
                console.log(arr[0] == sliceArr[0]);
                console.log(sliceArr == arr); //false

 

            ...扩展运算符实现

                
                //开辟一个新的变量
                let newArr = [...arr]
                console.log(newArr[0] == arr[0]);
                console.log(newArr == arr); //false

 

            使用第三方的插件 lodash.js _.clone方法实现

                
                 //实现浅拷贝
                let obj1 = {
                    user:{
                        name:"jack"
                    }
                }
                let copyObj1 = _.clone(obj1)
                console.log(copyObj1.user == obj1.user);//true
                console.log(copyObj1 == obj1);//false

 

深拷贝

            每层都进行值拷贝

        示例

            使用u盘在一台电脑上拷贝文件,将文件所有复制一份,在粘贴一份。这俩份文件除了值是一致的,其他都不一样。俩者的地址是独立的。

        实现方式

            使用字符串转换(序列化 JSON.stringify 和反序列化 JSON.parse)

               
               let obj = {
                    users:[{
                        name:'jack'
                    }]
                }
                //每层都只拷贝值 每层的地址都不一样
                // 字符串转换 序列化和反序列化
                let copyObj = JSON.parse(JSON.stringify(obj))
                console.log(copyObj == obj); //false
                console.log(copyObj.users == obj.users); //false
                console.log(copyObj.users[0] == obj.users[0]); //false
                console.log(copyObj.users[0].name == obj.users[0].name); //true    

 

            使用lodash 里面_.cloneDeep

               
                //使用第三方lodash _.cloneDeep方法实现
                let cloneObj = _.cloneDeep(obj)
                console.log(cloneObj == obj); //false
                console.log(cloneObj.users == obj.users); //false
                console.log(cloneObj.users[0] == obj.users[0]); //false
                console.log(cloneObj.users[0].name == obj.users[0].name); //true

 

            使用递归实现对应的深拷贝(面试题)

            思路

                根据传入的对象 进行判断 如果不是对象直接赋值
                如果是对象就要先创建一个对象 那么就需要判断是数组还是对象 如果是数组创建数组 如果是对象就创建对象
                如果是数组获或者是对象 取出里面的值进行递归赋值
               
              function deepClone(target) {
                    //如果传入的目标对象是空就直接返回
                    if (!target) return {}
                    let copyObj = {} //接收拷贝好的对象
                    //根据typeOf的返回值进行判断 判断是否为对象
                    if (typeof target == 'object') {
                        //判断是否为数组
                        copyObj = target instanceof Array ? [] : {}
                        //遍历所有的key加入到对应的copyObj里面
                        for (let key in target) {
                            //将对应的值和key加入到对应的copyObj里面
                            copyObj[key] = deepClone(target[key])
                        }
                    } else {
                        copyObj = target //直接赋值
                    }
                    return copyObj
                }      

 

Vue底层代码梳理

            虚拟dom(是一个对象)

                虚拟dom替代了dom节点,减少了对实际dom操作。(重绘和回流)。根据虚拟dom生成对应的实体dom

            diff 算法 (用于比对的算法)

                一个页面其中一个内容发送变化,按理来说应该只改这一个部分的渲染内容,而不应该进行整体渲染。
                那么你需要知道其中一个发送了变化,才能完成相关的操作。diff算法就用来比对出发生变化的部分。
                在虚拟dom里面进行比对。核心就是在虚拟dom里面进行比对对应的变化,从控制变化内容的渲染。

            数据驱动(mvvm model 数据 view 视图 viewModel 视图模型用控制对应的视图和数据的交互)

                通过改变的对应的数据,来改变对应的视图。双向绑定 从改视图从而改变对应的数据。viewModel完成
                这个一系列的操作。这个vm对象其实就是我们的vue对象。    

            vue怎么完成对应的视图和数据的交互

                vue2使用了Object.defineProperty和观察者模式来实现的。
                vue3使用proxy来实现的。

            diff算法的比对流程

                利用了pacth,来打补丁包。他去对应比对节点对于发生变化的节点打补丁包。vue对这些补丁的地方会进行重新渲染。
                他先比较的是key ,对于没有key的内容 先比较元素节点,再比较文本节点。比较完就会进行打补丁包
                (抽象的虚拟dom对象),对于这个补丁包他会将他合并到对于的虚拟dom上,再进行渲染。

            简易版的vue

                主要利用的object.defineProperty进行对应的数据劫持操作
                提取对应的dom中的命令及相关的内容形成新的dom对象进行相关操作
                通过对于数据的劫持控制对应的内容发生变化(重新渲染)

            v-click 处理点击事件 里面填入对应的vue里面methods里面方法 (原生vue不存在 原生vue中 v-on:click)

            v-for 循环渲染对应的数据 里面填入data里面的数组或者对象 (里面的值为 (value,key) in 数组)

              
                item表示对应的值 key表示对应的下标
                <p class="a" v-for="(item,key) in options">{{item}}</p>
                如果不需要对应的key那么可以省略key
                <p class="a" v-for="item in options">{{item}}</p>

 

            v-model 双向绑定操作 用于表单元素 里面填入data里面的数据

            v-html 将对应的data里面的数值渲染到对应的标签内(innerHTML)

              
               <div id="app">
                    <div>
                        <button class="a" v-for="(item,key) in options" v-click="getIndex(key)">{{item}}</button>
                    </div>
                    <input type="text" v-model="number1">
                    <span v-html="ys">+</span>
                    <input type="text" v-model="number2">
                    <button v-click="computed">=</button>
                    <input type="text" v-model="result">
                </div>
                <script src="./my_vue.js"></script>
                <script>
                    new Vue({
                        el: '#app',
                        data: {
                            number1: '',
                            number2: '',
                            result: '',
                            options: ['+', '-', '*', '/'],
                            ys: '+'
                        },
                        methods: {
                            computed() {
                                switch (this.ys) {
                                    case '+':
                                        this.result = Number(this.number1) + Number(this.number2)
                                        break
                                    case '-':
                                        this.result = Number(this.number1) - Number(this.number2)
                                        break
                                    case '*':
                                        this.result = Number(this.number1) * Number(this.number2)
                                        break
                                    case '/':
                                        this.result = Number(this.number1) / Number(this.number2)
                                        break
                                }
                            },
                            getIndex(index) {
                                this.ys = this.options[index]
                            }
                        },
                    })
                </script>

 

posted @ 2022-08-26 20:19  一对7  阅读(27)  评论(0编辑  收藏  举报