immutable详解

来源

1 .js中的对象是可变的,因为使用了引用赋值,新的对象简单的引用了原始对象,改变新的对象会影响到原始对象
2 .为了解决这个问题,一般就是使用浅拷贝或者深拷贝来避免被修改,但是这样会造成cpu和内存的浪费

immutable Data

1 .一旦创建,就不能更改的数据,对immutable对象的任何修改或删除添加都会返回一个新的immutable对象
2 .实现原理就是持久化数据结构,在使用旧数据创建新数据的时候,会保证旧数据同时可用且不变,同时为了避免深度复制复制所有节点的带来的性能损耗,immutable使用了结构共享,即如果对象树种的一个节点发生变化,只修改这个节点和受他影响的父节点,其他节点则共享。
3 .优点

1 .immutable降低了Mutable带来的复杂度
2 .节省内存
3 .时间旅行,复制粘贴这些操作做起来非常简单
4 .并发安全:传统的并发需要加锁,但是这个数据是天生不可变的,所以并发所就不需要了

处理复杂对象

浅拷贝

深拷贝

1 .JSON.parse:利用jaon.pase将对象转换为其JSON字符串形式,然后将其解析回对象

1 .缺点:不能处理循环对象,子父节点互相引用的情况,无法处理对象中有function,正则等情况
2 .const deepClone(obj)=>JSON.parse(JSON.stringify(obj))
3 .详细操作[http://blog.sina.com.cn/s/blog_6ad6243801013egv.html](http://blog.sina.com.cn/s/blog_6ad6243801013egv.html)

2 .messageChannel

1 .messageChannel接口是信道通信api的一个接口,允许我们创建一个新的信道并通过信道的两个MessageProt属性传递数据
2 .类似的还有Histor API,Notification API.都是用了结构化克隆算法实现传输值的
function structuralClone(obj) {
            return new Promise(resolve => {
                const {port1, port2} = new MessageChannel();
                port2.onmessage = function(e){
                    console.log(e)
                    resolve(e.data)
                }
                port1.postMessage(obj);
            });
        }
    

        const obj={name:"123"}
        structuralClone(obj).then((e)=>{
            console.log('clone',e)
        })
        console.log(obj)
        
        obj.name="456"
        console.log(obj,'change-->')
3 .

immutable

1 .如果需要频繁的操作一个复杂对象,每次完全拷贝一次的效率太低了。大部分场景下都只是更新了对象的一两个字段,其他字段都不变,对于这些不变的字段的拷贝都是多于的。
2 .核心思路,创建持久化的数据结构,在操作对象的时候值clone变化的节点和其祖先节点,其他的不变,实现结构贡献。
3 .Immutable.js
4 .Immer.js
5 .

自己写的全部深度克隆代码

function type(obj){
    var type=Object.prototype.toString.call(obj)

    var 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[type]
} 

function deepClone(item){
    if(!item)return item

    var types=['number','string','boolean'],result
    if(types.includes(type(item))){
        result=item
    }

    if(result===undefined){
        if(type(item)==='array'){
            console.log('arr')
            result=[]
            item.forEach((child,index,array)=>{
                result[index]=deepClone(child)
            })
        }else if(type(item)==='object'){
            if(item.nodeType&& typeof item.cloneNode=='function'){
                retult=item.cloneNode(true)
//真实的复制函数并没有走到这里
            }else if(!item.prototype){
                // 检查是否是可循环的
                if(item instanceof Date){
                    result=new Date(item)
                }else{
                    result={}
                    for(var i in item){
                        result[i]=deepClone(item[i])
                    }
                }
            }else{
                console.log('发现了其他类型')
            }
        }else{
            result=item
        }
    }else{
        console.log('123',result)
    }
    return result
}

let arr=[1,2,3]

var arr2=deepClone(arr)
console.log(arr2,'arr2')
arr.push(1)
console.log(arr2,'arr2-after')

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 点击查看原文 Web SDK 开发手册 SDK 概述 网易云信 SDK 为 Web 应用提供一个完善的 IM 系统...
    layjoy阅读 14,767评论 0 15
  • 原文 我们知道 js 对象是按共享传递(call by sharing)的,因此在处理复杂 js 对象的时候,往往...
    videring阅读 4,902评论 0 2
  • 你所谓的爱写作,不过是用它来给自己建立一个脆弱的壳,你好躲在里面,当别人说你无所作为性格惰怠时,你便以文人都清高据...
    江南吹雪阅读 4,007评论 11 18
  • 小城的老巷子深处藏着一家店,卖酒的。 那店怪得很,开了有些年头,却始终没有挂出过招牌,也没个名字。店老板是位年轻的...
    三行情书贩卖社阅读 3,911评论 0 6
  • 离职率大小反映了一个企业或部门的稳定性,一个企业的发展不仅要关注离职率,更要关注离职背后的原因,知其根源才能帮助企...
    自如得己阅读 631评论 0 0

友情链接更多精彩内容