原文:Write safer and cleaner code by leveraging the power of 「Immutability」javascript
譯者:neal1991java
welcome to star my articles-translator , providing you advanced articles translation. Any suggestion, please issue or contact menode
LICENSE: MITgit
Immutability是函數式編程的重要基礎之一。它容許你能編寫更安全以及更整潔的代碼。我將會經過一些JavaScript例子來向你展現如何來達到immutability。github
根據維基百科:編程
不可變對象是一個在建立以後不能修改其狀態的對象。這正與可變對象相反,它可以在建立以後被修改。在某些狀況下,對象被認爲是不可變的,即便其內部的某些屬性發生改變,可是從外部的角度來看這個對象的狀態看起來仍是沒有發生變化的。數組
數組是理解immutability如何工做的很好的起點。讓咱們一塊兒來看一看。安全
const arrayA = [1, 2, 3]; arrayA.push(4); const arrayB = arrayA; arrayB.push(5); console.log(arrayA); // [1, 2, 3, 4, 5] console.log(arrayB); // [1, 2, 3, 4, 5]
這個例子將arrayA的引用分配給arrayB,所以這個push方法在這兩個變量中都會添加5這個值。咱們的代碼間接地修改其它的值,這並非咱們想要的。這也違反了immutability的原則。併發
咱們能夠經過使用 slice函數將咱們的例子提高爲immutable,而且這個代碼的行爲也產生了變化。ide
const arrayA = [1, 2, 3]; arrayA.push(4); const arrayB = arrayA.slice(0); arrayB.push(5); console.log(arrayA); // [1, 2, 3, 4] console.log(arrayB); // [1, 2, 3, 4, 5]
這正是咱們想要的。代碼沒有改變其它值。
提醒:當你使用 push 向數組添加一個值的時候,你是在改變這個數組。你想要避免修改變量,由於這可能會給你的代碼帶來負面影響。 slice函數可以返回數組的拷貝。
如今你知道如何避免修改其它值。那麼你知道如何寫「純」函數了嘛?純函數是對於一個不會又任何反作用以及不會改變狀態的函數另外一個稱呼。
咱們來看一個利用數組示例中相同原理的函數。 首先,咱們建立一個改變其它值的函數,而後咱們將該函數改進爲「純」。
const add = (arrayInput, value) => { arrayInput.push(value); return arrayInput; }; const array = [1, 2, 3]; console.log(add(array, 4)); // [1, 2, 3, 4] console.log(add(array, 5)); // [1, 2, 3, 4, 5]
所以再一次,咱們修改咱們的輸入,這會產生一個沒法預測的函數。在函數式編程的世界中,對於函數有一個黃金法則:使用相同輸入的函數應該返回相同的結果。
上述的函數違反了這一黃金法則。每一次咱們的add函數被調用的時候,它就會修改這個array變量,結果也就不一樣了。
讓咱們一塊兒看看看如何改變咱們add函數的事先,所以讓其成爲immutable。
const add = (arrayInput, value) => { const copiedArray = arrayInput.slice(0); copiedArray.push(value); return copiedArray; }; const array = [1, 2, 3]; const resultA = add(array, 4); console.log(resultA); // [1, 2, 3, 4] const resultB = add(array, 5); console.log(resultB); // [1, 2, 3, 5]
如今咱們能夠調用咱們的函數屢次,而且能夠預期在相同輸入的時候,輸出都是相同的。這是由於咱們再也不會修改這個array變量。咱們可以將這個函數成爲「純函數」。
注意:你也能使用concat,而不是slice以及push。
所以:arrayInput.concat(value)
咱們可以利用ES6中的擴展語法來縮短函數。
const add = (arrayInput, value) => […arrayInput, value];
NodeJS應用使用了一個叫作併發的概念。一個併發操做意味着兩個計算可以可以同時進行而且不用考慮另一個。若是這裏有兩個線程的話,第二個計算不須要等到第一個計算完成才能只需執行。
NodeJS經過event-loop讓併發變得可能。event-loop會重複獲取一個事件,而且每次會激活任一一個事件處理器來監聽事件。這個模型容許NodeJS應用處理大量的請求。若是你想了解更多,閱讀這篇關於event-loop的文章。
Immutability和併發之間有什麼關係呢?由於作個操做可以在函數的做用域外以併發的方式改變值,這會產生一個不可靠的輸出以及沒法預期的結果。意識到函數可能會在做用域外修改變量,所以這可能會很是危險的。
Immutability對於你理解和學習函數式編程是很是重要的一個概念。你可能但願瞭解mmutableJS](https://facebook.github.io/im...,其由Facebook開發者編寫。這個library提供了某些不可變的數據機構,好比 Map, Set以及List.
Immutable.js, persistent data structures and structural sharing(譯者注:牆外地址)