国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

JavaScript數據類型對函數式編程的影響示例解析

瀏覽:219日期:2022-06-01 14:41:08
目錄
  • 前言
  • JavaScript中 的數據類型中的可變數據
    • 原始類型(基本類型)
    • 對象類型(引用類型)
  • JavaScript 為何能會讓純函數變得不純?
    • 如何解決可變數據的影響?
      • 數據拷貝
      • 使用不可變數據方案
    • 總結

      前言

      本篇文章是JavaScript 函數式編程 學習系列第二篇,感興趣也可以先去看第一篇:

      • 一文理解JavaScript中的函數式編程的概念
      • JavaScript數據類型對函數式編程的影響
      • 不可變數據方案之immer.js實現探索

      前文 一文理解JavaScript中的函數式編程的概念 中寫了函數式編程的概念,本篇文章繼上文之后,來梳理 JavaScript 數據類型對函數式編程的影響。

      函數式編程編程的核心就是 純函數 和隔離 副作用 ,為了讓 純函數 保持純粹,純函數的參數或者內部引用的外部數據應該是不可變數據。但 JavaScript 中的數據類型并不是都是不可變的,而數據類型的可變性,很有可能讓 純函數 變的不純。

      因此,本篇文章的目的有兩點:

      • 探索 JavaScript 的數據類型來了解的可變數據的根源。
      • JavaScript 的可變數據數據是怎么讓 純函數 變得不純的?
      • 如何解決 可變數據 的影響?

      JavaScript中 的數據類型中的可變數據

      在 JavaScript 中,數據類型有以下 8 種:

      • null
      • undefined
      • boolean
      • number
      • symbol -- 在 es6 中被加入
      • bigint -- es6+ 被加入
      • object

      注意點:

      在 JavaScript 中,變量是沒有類型的,值才有類型。變量可以在任何時候,持有任何值。

      原始類型(基本類型)

      上面 8 中類型除了 object ,其他都是原始類型,原始類型存儲的都是值,其特點有兩點:

      • 沒有方法可以直接調用
      • 原始類型的數據是不可被改變的,改變一個變量的值,并不是把值改變了,而是讓變量擁有新的值。

      注意點:

      • '1'.toString()或者false.toString()等可以用的原因是被強制轉換成了 String 類型也就是對象類型,所以可以調用 toString 函數。
      • 對于null來說,很多人會認為它是個對象類型,其實是錯誤的。typeof null 會輸出 object,這只是 JS 存在的一個悠久 Bug,而且好像永遠不會也不會被修復,因為有太多已經存在的 web 的內容依存著這個 bug。注: 在 JS 的最初版本中使用的是 32 位系統,為了性能考慮使用低位存儲變量的類型信息,000開頭代表是對象,然而 null 表示為全零,所以將它錯誤的判斷為 object 。雖然現在的內部類型判斷代碼已經改變了,但是對于這個 Bug 卻是一直流傳下來。

      對象類型(引用類型)

      而除了原始類型,剩下的 object 就是對象類型,和原始類型的不同點在于:原始類型存儲的是值,對象類型存儲的是地址。

      經典示例:

      var c = 1;
      var d = c;
      d = 2;
      console.log(c === d) // false
      var a = {
          name: "張三",
          age: 20
      }
      var b = a;
      b.age = 21;
      console.log(a.age === b.age) // true
      

      示例中把變量 a 的值給到了變量 b , b 修改了age 屬性,但是 a 的 age 屬性也跟著變了,是因為 var b = a 是 a 把對象的引用地址賦值給 b ,這時候 a 和 b 指向的是內存中的同一個數據。

      而 c 給 d 的是值,并不是一個引用,相當于復制了一份數據。

      因此可以知道原型類型的數據是不可變的,而對象類型的數據是可變的。

      JavaScript 為何能會讓純函數變得不純?

      JavaScript 中的對象類型的數據是可變,而可變性,就代表了不確定性,純函數 中使用了不確性的數據就會導致不純,因為其違背了 純函數 的特征:不受外界影響,不影響外界。

      下面來看一個例子:

      A 同學寫了這么一段代碼,初始化生成了一個 “zhangsan” 用戶。

      export const defaultUserInfo = {
          name: "名稱",
          age: 20,
          hobby: ["玩耍"]
      };
      export function initUser(userTemplate, name, age) {
          const newUser = userTemplate;
          newUser.name = name;
          newUser.age = age;
          return newUser;
      }
      const zhangsan = userInit(userDefaultInfo, "zhangsan", 21);
      

      然后 B 同學在開發其他頁面的時候,看到有初始化用戶信息的方法,然后直接復制過去,初始化了一個 “lisi” 用戶。

      import { defaultUserInfo, initUser } from "xxx模塊"。
      const lisi = userInit(userDefaultInfo, "lisi", 21);
      

      檢測的時候看到自己初始化的用戶信息正確的就沒有去檢查之前 A 同學的是否是正確的,上線后發現所有的用戶都變成了 lisi 。因為 userDefaultInfo 是一個引用類型,userInit(userDefaultInfo, "xxx", xx) 操作的都是內存中的同一個對象。其原因就是因為 A 和 B 開發者犯了一個錯誤,把可變數據傳遞到了 userInit 函數內部進行處理,哪怕進行了淺層拷貝,也出現了問題。究其原因還是因為給函數傳遞進去了一個 可變數據。

      我們校驗一個 純函數 有效性的關鍵依據,永遠是“針對已知的輸入,能否給出符合預期的輸出”,而上面例子中 initUser 函數沒有違背這個規則,但是在可變數據的影響下,讓它產生了 副作用,對外界已有的數據造成了影響。

      如何解決可變數據的影響?

      數據拷貝

      從使用函數方的角度來看,既然造成這個問題的原因是因為傳遞進去的數據是 可變數據 ,那么我就復制一份數據傳遞給函數內部使用,隨便你怎么修改,都不會影響外界其他數據。

      比如我們使用前面例子中的 initUser 函數時,先拷貝一份數據:

      function copyFunc(object) {
          return JSON.parse(JSON.string(object));
      }
      const zhangsan = userInit(copyFunc(userDefaultInfo), "zhangsan", 21);
      const lisi = userInit(copyFunc(userDefaultInfo), "lisi", 21);
      console.log(zhangsan.name === lisi.name); // false
      

      進行拷貝后的數據傳遞給 userInit 函數,就不會出現問題了。這里的 copyFunc 只能針對部分數據類型,對不少類型是不支持的,具體可以去看一下 關于JSON.parse(JSON.stringify(obj))實現深拷貝應該注意的坑 這篇文章。

      從被調用函數方來看,在使用 object 類型數據時,函數內部盡量不要去修改外界 object 數據(通過參數傳遞,或者直接使用外界的對象都不建議去修改),修改之前可以拷貝一份再修改。

      比如:

      export function initUser(userTemplate, name, age) {
          const newUser = copyFunc(userTemplate);
          newUser.name = name;
          newUser.age = age;
          return newUser;
      }
      

      使用不可變數據方案

      拷貝的數據比較大的時候,會出現性能問題,因此出現了不可變數據的方案。

      現在不可變數據常見的有兩種: Immutable.js 和 immer.js 。它們都能實現在操作數據后,返回新的一個數據,而不影響之前的數據。

      Immutable.js 實現了持久化數據結構,實現原理說明(引用于immutable.js 和 immer):

      • 使用舊數據創建新數據時,要保證舊數據同時可用且不變。同時為了避免 deepCopy 把所有節點都復制一遍帶來的性能問題,immutable 使用了結構共享方式,即如果對象樹中的一個節點改變,只修改這個節點和受它影響的父節點,其他節點共享。
      • immutable-js 使用了另一套數據結構 api,它會將原生數據類型都轉化為 immutable-js 內部對象。

      因此 Immutable.js 需要嚴格使用它自定義的操作數據的方法才行。

      immer.js 利用了 es6 的 Proxy 來進行對數據操作的攔截實現,具體原理可去 剖析 Immer.js 工作原理與設計模式 這里看看,也可以去網上查詢。

      總結

      • 分析 JavaScript中 的數據類型中的可變數據根源:Object 數據結構。
      • 探索了其可變數據數據是怎么對 純函數 造成的影響:Object 數據的不確定性。
      • 分析了如何解決 可變數據 的影響:深拷貝 和使用 不可變數據結構.

      參考:

      • JavaScript 函數式編程實踐指南
      • immutable.js 和 immer)

      以上就是JavaScript數據類型對函數式編程的影響示例解析的詳細內容,更多關于JavaScript數據類型函數式編程的資料請關注其它相關文章!

      標簽: JavaScript
      主站蜘蛛池模板: 91伦理视频 | 4455永久在线毛片观看 | 一区二区三区中文 | 男女扒开双腿猛进入免费网站 | 欧美 亚洲 另类 自拍 在线 | 久久黄色影片 | 精品视频网 | 美女视频黄色免费 | 精品一区二区三区免费毛片爱 | 国内精品影院久久久久 | 亚洲最大情网站在线观看 | 久久伊人热 | 曰批美女免费视频播放 | japanese乱子另类 | 国产成人在线视频 | 毛片美国| 国产成人三级经典中文 | 成人午夜免费视频 | 久爱免费观看在线网站 | 女人张开腿给人桶免费视频 | 久久精品国产免费观看99 | 在线观看片成人免费视频 | 男人精品一线视频在线观看 | 亚洲深夜 | aaa大片 | 国产欧美在线播放 | 欧美国产日韩在线观看 | 日本免费高清视频二区 | 免费看成人毛片日本久久 | 久久精品无遮挡一级毛片 | 男女在线视频 | 欧美一区二区二区 | 亚洲国产精久久久久久久春色 | 中国黄色一级毛片 | 亚洲另类自拍 | 午夜欧美成人香蕉剧场 | 视频在线一区二区三区 | 精品久久久日韩精品成人 | 国产性自拍 | 永久免费观看午夜视频在线 | 多人伦精品一区二区三区视频 |