為什麼不變性在JavaScript中如此重要?
為什麼不變性在JavaScript中如此重要?
可變性或代碼中的對象突變怎麼了?
它不是使事情變得簡單嗎?
在深入了解不變性的重要性之前,我們應該首先了解軟件開發中的可變性和不變性的概念。
公主親吻青蛙,希望它會變成一個英俊的王子。不變性的概念說青蛙永遠是青蛙。不變性概念主要源於功能和麵向對象的編程。每當我們想對某些數據(例如,對像或數組)進行更改時,我們都應使用更新後的數據返回一個新對象,而不是直接修改原始數據。
可以將不變性視為“另存為”,因為您知道它會返回一個新更改的對象,而傳統的就地突變就像“保存”就意味著更新原始狀態並釋放一個較早的狀態。不變數據的結構無法更改。
數據將是原始數據,一旦創建了對象,我們就無法在不可變對像中修改其狀態。將不變性概念視為不受外界影響的人體。一種安心的狀態。
反之亦然。可變性描述對象的狀態在聲明後是否可以修改。將其視為親吻青蛙會導致王子的轉變。舉一個例子,我們有一個變量,並給它賦了一個值。稍後,如果我們需要修改此變量的值,然後先更改它,然後更改其狀態,則該對像被認為是可變的。
從未使用不變性概念的開發人員可能會對將變量分配給新值或重新分配感到困惑。在JavaScript中,字符串和數字是不可變的數據類型。
JavaScript並不是一種以不變的方式處理數據的好語言。在JavaScript中,數組和對像不是不可變的。它們的值可以隨時間改變。兩者都始終作為參考傳遞,並且絕大多數可用方法都會對數據進行適當的突變。您可以考慮以下示例...
const a = [2, 1, 4, 3];
console.log(a);
// output: [2, 1, 4, 3]
const b= a.sort();
console.log(b);
// output: [1, 2, 3, 4]
console.log(a)
// output: [1, 2, 3, 4]
我們已經為變量“ a”分配了一個數組,並且正在對其執行排序操作。將排序後的數組分配給變量“ b”,您可以看到在執行排序操作後,我們得到了兩個變量的排序後的數組。在這裡,對象和數組作為參考傳遞,而不是複制變量“ a”和“ b”指向內存中的同一數組,並且該數組直接由方法sort進行了更改。
許多數組方法是Mutator方法。copyWithin,fill,pop,push,reverse,shift,sort,splice,unshift這些方法都允許可變性。映射和過濾器是不可變的,因為它創建了一個新的數組而不改變原始數組。要使對象和數組不可變,可以使用JavaScript中的某些技術並創建新值,而無需修改原始內容。不要直接更改對象的原始值。將此對象視為不可變對象,並返回具有更新值的全新對象。
讓我們再舉一個例子來理解這個概念。我們有一系列數據,其中包含一名員工在某個項目中工作的天數。
var daysWorked = [7, 7, 5, 9, 8, 6, 6, 7, 9, 5];
console.log(daysWorked);
// op: [7, 7, 5, 9, 8, 6, 6, 7, 9, 5];
//讓我們檢查一下最近6個月的工作
var lastSixMonths = daysWorked.slice(0,6);
console.log(lastSixMonths);
// op: [7, 7, 5, 9, 8, 6]
// 讓我們整理一下工作日
var sortedDaysWorked = daysWorked.sort();
console.log(sortedDaysWorked);
// op: [5, 5, 6, 6, 7, 7, 7, 8, 9, 9]
var lastSevenMonths = hoursWorked.slice(0,7);
console.log(lastSevenMonths);
// op: [5, 5, 6, 6, 7, 7] ,但預期輸出為 [7, 7, 5, 9, 8, 6] expected.
在上面的方法中,我們在可變的dayWorked上使用了兩種方法。
- 切片:在以上示例中,我們使用切片方法實現了不變性。此方法將原始對象切成薄片,而不是修改原始數據集,而是獲取對象lastSixMonths的新副本。
- 排序:此方法是一種可變方法,它正在對原始數據集進行排序。這種方法使我們無法對數據集進行進一步的計算。
JavaScript中不變性的重要性
不變性的優點是什麼?為什麼我們首先需要關心不變性?為什麼還要打擾?
不變性可立即對您的數據進行更嚴格的控制,從而使您的代碼更安全,更可預測。換句話說,不可變的對象使您能夠以可預測的方式控制界面和數據流,從而有效地發現更改。它還使實現諸如撤消/重做,時間旅行調試,樂觀更新和回滾等複雜功能變得更加容易。
如果我們談論前端庫React,Vue os狀態管理庫Redux,那麼不變性還可以通過在更改前後的狀態版本之間進行快速廉價的比較來幫助獲得更好的性能。組件可以利用此優勢,並僅在需要時智能地重新渲染自身。這可以大大提高性能。
不變性的主要好處是可預測性,性能和更好的突變跟踪。
1.可預測性
在任何應用程序中,當我們使用某些前端庫時,都會在其中聲明很多狀態。我們執行異步操作,並更新原始狀態(變異)。一旦最終用戶開始使用它,更新後的狀態將與初始狀態大不相同。改變狀態會隱藏更改,並且會產生副作用,從而導致多個錯誤。在這種情況下,調試變得很困難。
當您保持應用程序架構的不變性和思維模型簡單時,在任何給定時間預測狀態下的數據變得更加容易,然後您可以放心,它不會造成任何令人討厭的副作用。
2.表現
創建一個不變的對象會消耗內存。怎麼樣?當您向不可變對象添加值時,您需要創建一個新對象,並在此新對像中,將現有值與需要額外內存的新值一起復制。為了減少內存消耗,我們使用結構共享。
無論我們執行什麼更新,都將返回新值,但是我們在內部共享結構以減少內存消耗。例如,如果將一個向量附加到包含100個元素的向量中,則它不會創建一個新的101個元素長的向量。內部僅分配了一些小對象。
3.變異追踪
不變性的優點之一是,您可以通過使用引用和值相等來優化應用程序。這樣可以很容易地確定是否有任何更改。您可以考慮React組件中狀態更改的示例。shouldComponentUpdate可用於檢查狀態是否相同,比較狀態對象並防止不必要的呈現。
不變性使您可以跟踪這些對象發生的更改,例如一系列事件。與現有變量相比,變量具有易於跟踪的新引用。這有助於調試代碼和構建並發應用程序。此外,事件調試器還可以幫助您通過跟踪突變的視頻回放來回放DOM事件。
不變性的概念第一次讓您感到困惑。如果您了解不變性的需求和好處,則可以做得更好。當狀態發生變化時,您會遇到許多錯誤,並且處理它會使您更好地理解不變性的概念。