以前项目中遇到数据拷贝、引用之间数据层级嵌套过深,拷贝的值相互之间影响的问题,后来引入了immutability-helper
,使用过程当中的一些总结,跟你们分享下,至于为何不是immutable
,请看下文分解,这里是@IT·平头哥联盟,我是首席填坑官
——苏南。javascript
相信你们在面试/工做中都遇到过js对象/数组的拷贝问题,面试官问你,你通常怎么作??在如今ES6盛行的当下,不会一点ES6都很差意思说本身是前端(其实我通常都说本身是攻城狮、切图崽😝),咱们想的大多第一想法,以下:html
Object.assign
- 最方便;[...]
- 最有逼格;JSON.parse
、JSON.stringify
- 完美组合;$.extend()
- jQuery时代的引领潮流时尚前沿的API; 可是一般咱们使用的Object.assign
属于浅拷贝,当数据嵌套层级较深时,就……呵呵了;而JSON.parse、stringify
它应该是建立一个临时可能很大的字符串,而后又访问解析器,性能是比较慢的。因而后来发现了 immutable
「不可变数据」,曾经我也一度特别喜欢它,但时间久了,慢慢发现,它过于有个性了些、凡事都都没有任何商量的余地,全部的数据,从建立、变动、插入、删除等操做,都要按它的套路来,对于我这种一辈子放荡不羁爱自由的人来讲,长时间的约束,是不能忍的;都说两人若是三观不合,是没法长久下去的,可能也是缘份吧,在后来的某一天偶然的闲逛中邂逅了新欢 ————Immutability Helpers。前端
嗯,今天的主题就是给你们分享一下,Immutability Helpers
的一些用法,会介绍API的使用操做和小技巧,若有不理解不对,请纠正:
java
太兴奋了,差点忘了,补充一下,一个简单的拷贝:
//实现一个简单的递归数据拷贝 let customClone = (rawObj)=>{ let copyObj = {}; for (var key in rawObj) { if( typeof rawObj[key] === 'object' && Object.prototype.toString.call(rawObj[key]) !== '[object Array]'){ copyObj[key] = customClone(rawObj[key]); }else{ copyObj[key] = rawObj[key]; }; }; return copyObj; }; let objA = {"name":"苏南","sex":"男","height":"176"}; let objB = customClone(objA); objB.signature = "宝剑锋从磨砺出,梅花香自苦寒来,作有温度的攻城狮"; console.log(objA); console.log(objB);
Object.assign
的坑 :let data = { a:1, b:2, children:{ name:"苏南", organization:"@IT·平头哥联盟", job:"首席填坑官", address:"ShenZhen", age:18 } }; let data2 = Object.assign({},data); data2.children.age = 28; data2.children.job = "首席甩锅官"; data2.b = 666; console.log("我是原始数据 data:",data); console.log("我是复制后的数据 data2:",data2);
都说有了新欢,忘了旧爱,但我不是那种无情无义的人,最后正式介绍一下 immutable
,为我俩的……画上一个圆满的句号:react
再次强调,并非以为immutable
很差,不够强大,只是本身我的观点,有些不喜欢而已,各位immutable
粉勿喷,想了解更多的同窗能够点击这里git
Immutable data encourages pure functions (data-in, data-out) and lends itself to much simpler application development and enabling techniques from functional programming such as lazy evaluation.
const list1 = List([ 1, 2, 3 ]); const list2 = List([ 4, 5, 6 ]); const array = [ 7, 8, 9 ]; const list3 = list1.concat(list2, array); console.log(list3) // List {size: 9, _origin: 0, _capacity: 9, _level: 5, _root: null, …} 是不能直接获取到数据的,须使用get,-- list3.get(0)
let data = fromJS({ obj:{} }); let data1 = { a:1, b:2, children:{ name:"苏南", } }; let data2 = data.mergeIn(['obj'],data1,{c:666}); console.log("获取的数据:",data2.getIn(['obj','c'])); console.log("这里是由formJS建立的数据:",data2.getIn(['obj','children','name']));//
使用immutable后,全部数据都要相似选择器,一个一个往下选择,并非说它很差、功能不够强大,只是本身有些不喜欢它相似JQuery选择器同样的语法,get、getIn、set、List等的使用方式,固然它也是可使用
toJS
方法转回来的。
gitHub上它对本身的介绍很简单:
Mutate a copy of data without changing the original source
—— 在不更改原始源的状况下改变数据副本。
与它结缘,是由于它在react官方文档中出镜,而被我所宠幸,真的 ,只是由于在人群中多看了它一眼再也没能忘掉
, 它跟immutable
不同,不会有那么多条条框框约束你,给你自由、给你独立的空间、给你独立的思想,让你想用即用、用之即走~~(泥马,怎么有点像张小龙说它的小程序同样😬),但您放心,它的坑真的比小程序少,API也很简洁,接下来来看一下,它的基本用法:程序员
$push
—— 数组;$unshift
—— 数组;$splice
—— 数组;$set
—— 替换/覆盖/合并原数据;$toggle
—— array of strings ,toggles a list of boolean fields from the target object;$unset
—— remove the list of keys in array from the target object;$merge
—— 合并对象;$apply
—— passes in the current value to the function and updates it with the new returned value;$add
—— 新增;$remove
—— 删除。以上基本就是它所有的API了,下面一块儿来看看,具体用法吧:
push
同样,不过写法有一点点不同;let arr = [1,2,3,4,5,66]; let arr2 = update(arr,{ $push : ["a","b","c"], //必定要 []号的形式哦,不能够 "a"; [4]:{ // !!index ,能够指定修改下标的值 $set:"我是替换过的" } }); console.log(arr2);
unshift
,在原数组开头处插入,一样写法是以一个数组的形式;let arr = [1,2,3,4,5,66]; let arr2 = update(arr,{ $unshift : ["a","b","c"], [4]:{ $set:"我是首席填坑官∙苏南" //这里须要注意,它的操做是在 unshift以前执行的,也就是在原 arr 上查找 第4个下标 } }); console.log("原始数组",arr);// [1, 2, 3, 4, 5, 66] 相互之间并不会影响 console.log(arr2); //["a", "b", "c", 1, 2, 3, 4, "我是首席填坑官∙苏南", 66]
let arr = [1,2,3,4,5,66]; let arr2 = update(arr,{ $splice : [[1,2,[66788,99],{a:123,b:"苏南"}]], // or [0,1,"从我开始是插入的内容",88,89,90,"后面能够不少,是数组、对象、字符串都行"] }); console.log(arr2); //复杂一些的用法: let obj={ name:"immutable", list :[1,2,[90,55,44,3,22,55],3,4,6,7,8] }; let obj2 = update(obj,{ list:{ [2]:value=>update(value,{ $splice:[[0,2]] // [90,55,44,3,22,55] => [44, 3, 22, 55] }) } });
let obj={ name:"immutable", children:{ address:"ShenZhen", hobby:"@IT·平头哥联盟-前端开发" } }; let obj2 = update(obj,{ $set : {name:"immutability-helper",other:"其余字段,如微信公众号:honeyBadger8,每周为你带来最新分享"} }); let obj3 = update(obj,{ name:{ $set : "苏南" }, children:{ hobby:{ $set:"首席填坑官 - javascript" } } }); console.log("原始数据:",obj); console.log("obj2:",obj2); console.log("obj3",obj3);
Numbe
r 类型 的 0、1,那么使用引方法的时候就要注意了;let obj={ name:"immutable", a:false, b:true, c:1, d:0 }; let obj2 = update(obj,{ $toggle:['b','a',"c","d"], }); console.log("原始数据:",obj); console.log("obj2:",obj2);
object
时key是删除了;而数组array
中它的值没有了,却保留了下标
,不改变数组的长度,删除数组建议仍是用$splice
;请看下图:let arr = [1,2,3,4,5,6]; let obj={ name:"immutable", children:{ address:"ShenZhen", hobby:"写博客" } }; let obj2 = update(obj,{ $unset : ["name"], children:{ $unset:["address"] } }); console.log("原始数据:",obj); console.log("obj2:",obj2); let arr2 = update(arr,{ $unset : [1] }); console.log("arr2:",arr2,arr2.length);
$merge
跟咱们最爱的Object.assign
同样,作合并操做的,但它比assign
优秀不少,深层次拷贝,不会相互影响 :let arr = [1,2,3,4,5,6]; let obj={ name:"immutable", children:{ address:"ShenZhen", hobby:"写博客", array:["我不是程序员","切图崽了解一下"], } }; let obj2 = update(obj,{ $merge:{ arr }, children:{ array:{ $merge:{items:["从前有坐山","山里有个庙"]}, $splice:[[3,0,"住着一个小和尚"]] } } }); console.log("原始数据:",obj); console.log("obj2:",obj2);
$apply
基于当前值进行一个函数运算,从而获得新的值 :function
哦!let obj={ name:"immutable", children:{ items:["从前有一坐山"], array: [1,2,3,4,5,6], } }; let obj2 = update(obj,{ name:{ $apply:(val)=>("首席填坑官") }, children:{ items:{ $apply:(val)=>{ console.log("旧值",val); return [3,0,"住着一个小和尚"] } }, array:{ $apply:(val)=>(val.reverse()) //必须是一个函数 } } }); console.log("原始数据:",obj); console.log("obj2:",obj2);
$remove
必定必定 要是使用Set
、Map
建立的数组:$remove:[2,666]
,2会删除,6则会被忽略;let obj={ name:"immutable", children:{ array:new Set([1, 2, 3, 4, 4]), } }; let obj2 = update(obj,{ children:{ array:{ $remove:[2], }, } }); console.log("原始数据:",obj); console.log("obj2:",obj2);
$add
跟刚才的 $remove 同样要使用Map/Set,$add方法也跟 es6
Map/Set
的 add方法一致:let obj={ name:"immutable", array:new Map([["a",1],["b",2]]), }; let obj2 = update(obj,{ array:{ $add:[["66",56]], }, }); console.log("原始数据:",obj); console.log("obj2:",obj2); console.log("获取key a:",obj2.array.get('a'));
$trinocular
方法,来判断数组中的值;update.extend('$trinocular', function(proportion, original) { return original > 88 ? (original/proportion ): (proportion+original); }); let array =[56,33,55,777,322,444,61,12,34,52,245]; let array2 = array.map((k,v)=>update(k,{ $trinocular:2 })) console.log("原始数据:",array); console.log("array2:",array2);
以上就是基础 API 的用法 ,添加了一些官方示例,没有讲到的组合使用,以及使用过程当中,可能出现的一些错误,须要留意的地方,更多定制高级用法,有兴趣的同窗能够自行了解一下。es6
以上就是今天为你们带来的分享,它可能没有 immutable
那么多功能,但贵在简洁,不会有太多的约束,如理解有误之处,欢迎各位大佬纠正,毕竟我还只是个宝宝——新手上路中!🤪。github
下方是我弄的一个公众号,欢迎关注,之后文章会第一时间,在公众号上更新,缘由是以前分享的有两篇文章,居然被其余公众号抄袭了😭,前些天去更新发表的时候,微信提示我文章已经不是原创了检测到相同的文章,宝宝内心那个凉啊~,果断申诉告了对方(是一个培训学校公众号,好气哦),补了掘金发布的连接和截图日期,万幸最后胜诉了🤗!👇👇面试
作完小程序项目、老板给我加了6k薪资~
面试踩过的坑,都在这里了~
你应该作的前端性能优化之总结大全!
如何给localStorage设置一个过时时间?
手把手教你如何绘制一辆会跑车
如何用CSS3画出懂你的3D魔方?
SVG Sprites Icon的使用技巧
做者:苏南 - 首席填坑官
连接: https://honeybadger8.github.i...
交流:91259409五、公众号:honeyBadger8
本文原创,著做权归做者全部。商业转载请联系@IT·平头哥联盟
得到受权,非商业转载请注明原连接及出处。