<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 函數式編程 函數式編程是一種典型的**聲明式編程**,與命令式編程相對立,它更看重程序的執行目標而不是執行過程。 函數式編程的一大特點是,函數是“一等公民”,意味著函數優先,提倡使用函數組合 我們先實現以下函數: ```js const add = (x, y) => x + y; const multiply= (x, y) = > x * y; const subtract = (x, y) => x - y; ``` 上述求值過程在函數式編程的理念下,就可以通過連接函數得到: ```js let result= subtract(multiply(add(l,2), 3), 4); ``` 我們看到,函數可以與其他數據一樣,作為參數傳遞,或作為返回值返回,這就是函數是 “一等公民”的體現。 ## 純函數 Redux 中`reducer`函數 都需要是純函數 ,它的處理便是根據 `action` 參數產生一棵新的頁面狀態數據樹。這其實“暗合”(實際上是主動接受的)了函數式編程當中純函數的概念。 純函數代表這樣一類函數: * 對于指定輸出,返回指定結果。 * 不存在副作用。 也就是說,**純函數的返回值只依賴其參數**。比如: ```js //這是一個純函數 const addByOne = x => x + 1; ``` 同時,在純函數內不能存在任何副作用,包括但不限于: * 調用系統 I/O 的 API, `Date.now()` 或者 `Math.random()` 等方法。 * 發送網絡請求。在函數體內修改外部變量的值。 * 使用 `console.log()` 輸出信息。 * 調用存在副作用的函數等。 因為這些操作都具有不確定性,是“不純”的。換句話說,**對于純函數,如果是同樣的參數,則一定能得到一致的返回結果。作為開發者,根據其輸入,是完全可以預測輸出的**。 ## 不可變性和共享數據 共享和不可變性是函數式編程推崇的重要概念,也是其顯著特點。保證數據的不可變性, 好處在于:開發**更加簡單、可回溯、測試友好,以及減少了任何可能的副作用,從而減少了Bug的出現**。 **共享**是指一個變量、對象或者內存空間在多個共享的作用域中出現,或者一個對象的屬性在多個作用域范圍內被傳遞。 共享帶來的問題是:針對共享的數據,我們需要完全掌握其在所有作用域空間內的情況,以保證代碼的正確性。 在 Redux的 `reducer` 一次更新過程中,不應該直接更改原有對象或數組的值,因為它們是引用類型,直接更改其值是不被允許的。**這時就需要新創建一個新的對象或數組用來承載新的數據,以保證純函數的特性**。 ### JavaScript中滿足不可變性操作的方法 ```js let item = { id:0, book:'Learn Redux1', available:true, note:13 } let newItem = Object.keys(item).reduce((obj,key)=>{ //console.log("obj is:",obj); if(key !=='note'){ return {...obj, [key]:item[key] } } return obj; },{}) console.log(newItem); // {id: 0, book: "Learn Redux1", available: true} console.log(item); // {id: 0, book: "Learn Redux1", available: true, note: 13} ``` 這里使用了 `Object.keys`及 `reduce` 方法,對除note屬性以外的所有屬性進行累加拷貝。這是很典型的函數式操作 一個很好的選擇是使用類似于underscore的類庫,這種類庫都會對數據操作進行函數式封裝。另外,將原有數據完全深拷貝一份,然后再對副本進行操作也是一個可選的方案。 ### 實用類庫 社區中活躍著很多不可變的數據操作類庫,如 Facebook 的 [immer](https://github.com/mweststrate/immer)、[immutable.js](http://facebook.github.io/immutable-js/) 、[mori.js](http://swannodette.github.io/mori/) 等。使用它們實現的深拷貝及數據結構,在注重性能的同時也提供了方便實用的API。 但是引入這些第三方類庫也增加了一定的復雜度和學習成本。尤其是在同一個應用中,原生JavaScript數組、對象和這些類庫帶來的新的數據結構混雜,往往也存在著一定程度的淚亂。 如果開發者覺得使用JavaScript的 `slice`、`filter`、`map`、`reduce` 等函數式API,再結合ESNext 新特性己經完全可以滿足開發需求,那么就沒必要再使用類似于 immutable.js 的類庫了。 在取舍之間,開發者需要根據自身的業務情況及團隊風格進行選擇。 # JS 的**共享和可變性** JavaScript 中的對象一般是可變的(Mutable),因為使用了引用賦值,新的對象簡單的引用了原始對象,改變新的對象將影響到原始對象。雖然這樣做可以有效的利用內存,但當應用復雜后,這就造成了非常大的隱患。 太過于靈活多變在復雜數據的場景下也造成了它的不可控性,假設一個對象在多處用到,在某一處不小心修改了數據,其他地方很難預見到數據是如何改變的,針對這種問題的解決方法,一般就像剛才的例子,會想復制一個新對象,再在新對象上做修改,這無疑會造成更多的性能問題以及內存浪費。 為了解決這個問題,一般的做法是使用 **shallowCopy(淺拷貝)** 或 **deepCopy(深拷貝)** 來復制一個新對象,從而使得新對象與舊對象引用地址不同,再在新對象上做修改,這無疑會造成更多的性能問題以及內存浪費。 ## 與 Object.freeze、const 區別 ``` a=Object.freeze({a:1}); b=a; b.a=10; a.a還是1 ``` `Object.assign` 及擴展運算符`...` 、`Object.freeze` 和 ES6 中新加入的 `const` 都可以達到防止對象被篡改的功能,但它們是 `shallowCopy` (淺拷貝) 的。對象層級一深就要特殊處理了。 Redux 借鑒了函數式編程的思想,采用了單向數據流理念。是排斥這種共享和可變性的。 # immutable.js 而Immutable Data 就是一旦創建,就不能再被更改的數據。對 Immutable 對象的任何修改或添加刪除操作都會返回一個新的 Immutable 對象。 **Immutable 實現的原理是 Persistent Data Structure(持久化數據結構),也就是使用舊數據創建新數據時,要保證舊數據同時可用且不變**。同時為了避免 deepCopy 把所有節點都復制一遍帶來的性能損耗。 Immutable 使用了 Structural Sharing(結構共享),即如果對象樹中一個節點發生變化,只修改這個節點和受它影響的父節點,其它節點則進行共享: ```視頻注釋 `[JSConf] Anjana Vakil- Immutable data structures`: ~~~[youku] XMzQ5NTQzMDc1Mg ~~~ `Immutable User Interfaces (Lee Byron)`: ~~~[youku] XMTcyNjY5Mzk3Mg== ~~~ ``` [immutable.js](http://facebook.github.io/immutable-js/) 和React同期出現。是一個完全獨立的庫,無論基于什么框架都可以用它。意義在于它彌補了Javascript沒有不可變數據結構的問題。 **不可變數據結構是函數式編程(Functional Programming )中必備的**。前端工程師被 OOP 洗腦太久了,組件根本上就是函數用法,FP的特點更適用于前端開發。 在React開發中,頻繁操作state對象或是store,配合immutableJS快、安全、方便。 ## immutableJS 三大特性: * Persistent data structure (持久化數據結構) * structural sharing (結構共享) 只重新創建新的節點來更新這個結構樹樹。其他節點都被重用了。(依然可以保留了原來的舊數據) * support lazy operation (惰性操作) 應用惰性操作的特性,會節省非常多的性能 ## 時間旅行小菜一碟 Undo/Redo,Copy/Paste,甚至時間旅行這些功能做起來小菜一碟。因為每次數據都是不一樣的,只要把這些數據放到一個數組里儲存起來,想回退到哪里就拿出對應數據即可,很容易開發出撤銷重做這種功能。 # 擁抱函數式編程 **Immutable 本身就是函數式編程中的概念,純函數式編程比面向對象更適用于前端開發。因為只要輸入一致,輸出必然一致,這樣開發的組件更易于調試和組裝。** 像 [ClojureScript](https://clojurescript.org/),[Elm](http://elm-lang.org/) 等函數式編程語言中的數據類型天生都是 Immutable 的,這也是為什么 ClojureScript 基于 React 的框架 --- Om 性能比 React 還要好的原因。 # 推薦做法 這點是我們使用 Immutable.js 過程中遇到最大的問題。寫代碼要做思維上的轉變。 雖然 Immutable.js 盡量嘗試把 API 設計的與原生對象類似,有的時候還是很難區別到底是 Immutable 對象還是原生對象,容易混淆操作。 Immutable 中的 Map 和 List 雖對應原生 Object 和 Array,但操作非常不同,比如你要用 `map.get('key')` 而不是 `map.key`,`array.get(0)` 、`array[0]`。另外 Immutable 每次修改都會返回新對象,也很容易忘記賦值。 **當使用外部庫的時候,一般需要使用原生對象,也很容易忘記轉換。** 下面給出一些辦法來避免類似問題發生: 1. 使用 TypeScript 這類有靜態類型檢查的工具 2. 約定變量命名規則:如所有 Immutable 類型對象以 `$$` 開頭。 3. 使用 `Immutable.fromJS` 而不是 `Immutable.Map` 或 `Immutable.List` 來創建對象,這樣可以避免 Immutable 和原生對象間的混用。 # 萬物皆有兩面性… 請不要認為這篇文章的意思是“你應該經常使用Immutable.js”,準確的講,我只是告訴你用它的所有好處,以及為什么要使用它。 當我在寫代碼的時候,我首先會用普通的 JavaScript 對象和數組,當我使用 Immutable.js 時,我需要非常確定,比如一個對象包含 10,000 個屬性。**我幾乎從不使用 Immutable.js,因為大多數時候的對象都很小**。 # 參考 [從JS對象開始,談一談“不可變數據”和函數式編程](https://www.jianshu.com/p/89f1d4245b20) 《React狀態管理與同構實戰》 [Immutable 詳解及 React 中實踐](https://zhuanlan.zhihu.com/p/20295971) [Immutable.js 可持久化數據結構以及結構分享](https://blog.csdn.net/vM199zkg3Y7150u5/article/details/78210311) [React實戰-Reactjs中的如何通過不可變數據對象提高頁面性能](https://blog.csdn.net/loveu2000000/article/details/52761498) [Immutable.js 以及在 react+redux 項目中的實踐](https://blog.csdn.net/sinat_17775997/article/details/73603797)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看