• 前端性能优化——渲染优化


    一、浅拷贝
    1、什么是浅拷贝?

    浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

    浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用

    2、如何实现浅拷贝?

    (1)Object.assign()

    Object.assign({},obj,…)可以接收无限个参数,obj中的引用类型属性会被深拷贝

    // 1、Object.assign()
    let person = {//原数据 { name: 'lucky', hobby: { like: 'running' } }name: 'lucky',hobby: {like: 'running'}
    }
    let copyPerson = Object.assign({}, person)
    copyPerson.name = 'mouse' //name是基本数据类型
    copyPerson.hobby.like = 'singing' //hobby是引用类型
    ​
    console.log(copyPerson); //{ name: 'mouse', hobby: { like: 'singing' } }
    //对比原数据,对象copyPerson的改变影响了对象person的改变
    console.log(person); //{ name: 'lucky', hobby: { like: 'singing' } } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (2)扩展运算符

    扩展运算符(…)类似于Object.assign()

    A.拷贝对象

    // 扩展运算符
    let person = {  //原数据 { name: 'lucky', hobby: { like: 'running' } }name: 'lucky',hobby: {like: 'running'}
    }
    ​
    let copyPerson = {...person
    }
    copyPerson.name = 'dunny'
    copyPerson.hobby.like = 'swimming'
    console.log(person);//{ name: 'lucky', hobby: { like: 'swimming' } }
    //对比原数据,对象copyPerson的改变影响了对象person的改变
    console.log(copyPerson);    //{ name: 'dunny', hobby: { like: 'swimming' } } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    B.拷贝数组

    let arr = ['name', 'hobby', 'person', {//原数据[ 'name', 'hobby', 'person', { age: 19 } ]age: 19
    }]
    ​
    let copyArr = [...arr];
    copyArr[0] = 'nickname';
    copyArr[copyArr.length - 1].age = 20;
    ​
    console.log(copyArr);   //[ 'nickname', 'hobby', 'person', { age: 20 } ]
    //对比原数据,数组copyArr的改变影响了数组arr的改变
    console.log(arr); //[ 'name', 'hobby', 'person', { age: 20 } ] 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    (3)Array.prototype.concat()

    //Array.prototype.concat()
    let myArr = ['old', null, undefined, true, {//原数据[ 'old', null, undefined, true, { hobby: 'undefined' } ]hobby: undefined
    }];
    let copyMyarr1 = myArr.concat();
    ​
    copyMyarr1[0] = 'nickname';
    copyMyarr1[copyMyarr1.length - 1].hobby = 'books'
    ​
    console.log(copyMyarr1); //[ 'nickname', null, undefined, true, { hobby: 'books' } ]
    //对比原数据,数组copyMyarr1的改变影响了数组myArr的改变
    console.log(myArr); //[ 'old', null, undefined, true, { hobby: 'books' } ]
    ​ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    (4)Array.prototype.slice()

    A.demo1

    //Array.prototype.slice()
    let myArr = ['old', null, undefined, true, {hobby: undefined
    }]; //原数据[ 'old', null, undefined, true, { hobby: 'undefined' } ]
    let copyMyarr2 = myArr.slice();
    copyMyarr2[0] = 'nickname';
    copyMyarr2[copyMyarr2.length - 1].hobby = 'books'
    console.log(copyMyarr2); //[ 'nickname', null, undefined, true, { hobby: 'books' } ]
    //对比原数据,数组copyMyarr2的改变影响了数组myArr的改变
    console.log(myArr); //[ 'old', null, undefined, true, { hobby: 'books' } ]
    ​ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    B.demo2

    let newArr = [[{name: 'lucky'}],['age']
    ]
    let copyNewarr = newArr.slice()
    copyNewarr[0].name = 'chicken'
    ​
    console.log(copyNewarr);//[ [ { name: 'lucky' }, name: 'chicken' ], [ 'age' ] ]
    ​ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    二、深拷贝
    1、什么是深拷贝?

    深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象。

    深拷贝拷贝多层,每一级别的数据都会拷贝。

    2、如何实现深拷贝?

    (1)JSON.parse(JSON.stringify(obj))

    JSON.stringify() 将JSON格式的对象转为字符串

    JSON.parse() 将JSON格式的字符串转为对象

    // 1、 JSON.parse(JSON.stringify(obj))
    let student = {name: 'lucky',hobby: {like: 'dancing'},birth: undefined,title: Symbol('Banana'),date: new Date(),regexp: /^A/
    }
    let myStudent = JSON.parse(JSON.stringify(student));
    //会忽略Symbol,undefined和函数
    console.log(myStudent);
    // {
    //   name: 'lucky',
    //   hobby: { like: 'dancing' },
    //   date: '2022-10-11T10:45:21.484Z',
    //   regexp: {}
    // }
    myStudent.name = 'duck';
    myStudent.hobby.like = 'reading'
    ​
    console.log(myStudent);
    // {
    //   name: 'duck',
    //   hobby: { like: 'reading' },
    //   date: '2022-10-11T10:45:21.484Z',
    //   regexp: {}
    // }
    // myStudent的改变不会影响student
    console.log(student);
    // {
    //name: 'lucky',
    //hobby: {
    //like: 'dancing'
    //},
    //birth: undefined,
    //title: Symbol(Banana),
    //date: 2022 - 10 - 11 T10: 49: 10.521 Z,
    //regexp: /^A/
    // } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    缺陷:

    A.会忽略Symbol和undefined和function

    B.不能拷贝循环引用的对象,例如:

    // 循环
    let b = {}
    let a = {b: b
    }
    ​
    b.a = a
    let c = JSON.parse(JSON.stringify(a))//TypeError: Converting circular structure to JSON
    console.log(c); 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    C.不能序列化函数,拷贝出来的对象的属性顺序可能会和源对象不一致

    D.拷贝Date对象,得到的是字符串;拷贝RegExp对象,得到的是{}

    E.对象中含有NaN,Infinity会变成null

    三、手写浅拷贝

    实现浅拷贝核心思想:如果属性是基本数据类型,则拷贝基本类型的值;如果属性是引用类型,拷贝的就是内存地址 ,会受拷贝对象(本体)的影响。

    function shallowCopy(obj) {if (typeof obj !== 'object') return;
    ​let newObj = Array.isArray(obj) ? [] : {};// let newObj=obj instanceof Array ?[]:{};// let newObj=obj instanceof Object ?[]:{};//这个不能判断
    ​for (let key in obj) {if (obj.hasOwnProperty(key)) { //自己本身具有的属性newObj[key] = obj[key];}}return newObj;// console.log(newObj);
    }
    // 测试对象
    let obj = {name: 'lucky',like: {life: 'running'}
    }
    let myObj = shallowCopy(obj)
    myObj.name = 'dunny'
    myObj.like.life = 'singing'
    console.log(myObj); //{ name: 'dunny', like: { life: 'singing' } }
    console.log(obj); //{ name: 'lucky', like: { life: 'singing' } }
    ​
    ​
    // 测试数组
    let arr = ['hello', 'world', {name: 'cat'
    }]
    let myArr = shallowCopy(arr)
    myArr[1] = 'moon'
    myArr[myArr.length - 1].name = 'dog'
    console.log(myArr); //[ 'hello', 'moon', { name: 'dog' } ]
    console.log(arr); //[ 'hello', 'world', { name: 'dog' } ]
    ​ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    四、手写深拷贝

    实现深拷贝核心思想:原始类型直接拷贝,引用类型递归。

    // 深拷贝
    function deepCopy(obj) {// 过滤原始类型if (typeof obj !== 'object') return obj;
    ​// 过滤null类型 因为typeof null==object,使用不能使用typeof判断null数据类型if (obj == null) return obj;
    ​let newObj = Array.isArray(obj) ? [] : {};// let newObj=obj instanceof Array ?[]:{};
    ​// 拷贝Date对象if (obj instanceof Date) {newObj = new Date(obj)}// 拷贝RegExp对象if (obj instanceof RegExp) {newObj = new RegExp(obj)}
    ​for (let key in obj) {if (obj.hasOwnProperty(key)) { //自己本身具有的属性newObj[key] = typeof obj[key] == 'object' ? deepCopy(obj[key]) : obj[key];}}return newObj;
    }
    ​
    // 测试对象
    let obj = {name: 'lucky',like: {life: 'running'}
    }
    let myObj = deepCopy(obj)
    myObj.name = 'dunny'
    myObj.like.life = 'singing'
    console.log(myObj); //{ name: 'dunny', like: { life: 'singing' } }
    console.log(obj); //{ name: 'lucky', like: { life: 'running' } }
    ​
    ​
    // 测试数组
    let arr = ['hello', 'world', {name: 'cat'
    }]
    let myArr = deepCopy(arr)
    myArr[1] = 'moon'
    myArr[myArr.length - 1].name = 'dog'
    console.log(myArr); //[ 'hello', 'moon', { name: 'dog' } ]
    console.log(arr); //[ 'hello', 'world', { name: 'cat' } ]
    ​ 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    最后

    最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



    有需要的小伙伴,可以点击下方卡片领取,无偿分享

  • 相关阅读:
    就用最笨拙、最踏实的方式去做
    Maven多模块版本统一管理
    用DIV+CSS技术设计的美食主题网站(web前端网页制作课作业)美食餐饮网站设计与实现(HTML+CSS+JavaScript)
    数据结构-快速排序-C语言实现
    如何修复和解决 IP 地址冲突
    微软云计算[3]之Windows Azure AppFabric
    探讨Linux CPU的上下文切换原由
    微信小程序自动推送当天天气情况Java版
    微信公众号记录
    vue中替换全局字体
  • 原文地址:https://blog.csdn.net/pfourfire/article/details/127845878