以前項目中遇到數據拷貝、引用之間數據層級嵌套過深,拷貝的值相互之間影響的問題,後來引入了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·平頭哥聯盟
得到受權,非商業轉載請註明原連接及出處。