欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript數(shù)據(jù)類型對函數(shù)式編程的影響示例解析

 更新時間:2023年02月23日 09:12:45   作者:Hutao  
這篇文章主要為大家介紹了JavaScript數(shù)據(jù)類型對函數(shù)式編程的影響示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

本篇文章是JavaScript 函數(shù)式編程 學(xué)習(xí)系列第二篇,感興趣也可以先去看第一篇:

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

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

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

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

JavaScript中 的數(shù)據(jù)類型中的可變數(shù)據(jù)

在 JavaScript 中,數(shù)據(jù)類型有以下 8 種:

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

注意點:

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

原始類型(基本類型)

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

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

注意點:

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

對象類型(引用類型)

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

經(jīng)典示例:

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 指向的是內(nèi)存中的同一個數(shù)據(jù)。

而 c 給 d 的是值,并不是一個引用,相當(dāng)于復(fù)制了一份數(shù)據(jù)。

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

JavaScript 為何能會讓純函數(shù)變得不純?

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

下面來看一個例子:

A 同學(xué)寫了這么一段代碼,初始化生成了一個 “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 同學(xué)在開發(fā)其他頁面的時候,看到有初始化用戶信息的方法,然后直接復(fù)制過去,初始化了一個 “lisi” 用戶。

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

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

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

如何解決可變數(shù)據(jù)的影響?

數(shù)據(jù)拷貝

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

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

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

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

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

比如:

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

使用不可變數(shù)據(jù)方案

拷貝的數(shù)據(jù)比較大的時候,會出現(xiàn)性能問題,因此出現(xiàn)了不可變數(shù)據(jù)的方案。

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

Immutable.js 實現(xiàn)了持久化數(shù)據(jù)結(jié)構(gòu),實現(xiàn)原理說明(引用于immutable.js 和 immer):

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

因此 Immutable.js 需要嚴(yán)格使用它自定義的操作數(shù)據(jù)的方法才行。

immer.js 利用了 es6 的 Proxy 來進行對數(shù)據(jù)操作的攔截實現(xiàn),具體原理可去 剖析 Immer.js 工作原理與設(shè)計模式 這里看看,也可以去網(wǎng)上查詢。

總結(jié)

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

參考:

以上就是JavaScript數(shù)據(jù)類型對函數(shù)式編程的影響示例解析的詳細內(nèi)容,更多關(guān)于JavaScript數(shù)據(jù)類型函數(shù)式編程的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 微信小程序 實戰(zhàn)程序簡易新聞的制作

    微信小程序 實戰(zhàn)程序簡易新聞的制作

    這篇文章主要介紹了微信小程序 實戰(zhàn)程序簡易新聞的制作的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • 關(guān)于JavaScript?中?if包含逗號表達式

    關(guān)于JavaScript?中?if包含逗號表達式

    這篇文章主要介紹了?關(guān)于JavaScript?中?if包含逗號表達式,有時會看到JavaScript中if判斷里包含英文逗號?“,”,這個是其實是逗號表達式。在if條件里,只有最后一個表達式起判斷作用。下面來看看文章的具體介紹吧
    2021-11-11
  • web?worker在項目中的使用學(xué)習(xí)為項目增加亮點

    web?worker在項目中的使用學(xué)習(xí)為項目增加亮點

    這篇文章主要為大家介紹了web?worker使用學(xué)習(xí)來為你的項目增加亮點,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • 詳解微信小程序 相對定位和絕對定位

    詳解微信小程序 相對定位和絕對定位

    這篇文章主要介紹了詳解微信小程序 相對定位和絕對定位的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • JS ES新特性 模板字符串

    JS ES新特性 模板字符串

    這篇文章主要介紹了JS ES新特性模板字符串,模板字符串即Template String是增強版的字符串,使用反引號(```)來代替譜通字符串中的用雙引號和單引號,更多相關(guān)介紹,需要的朋友可以參考下面文章的詳細內(nèi)容
    2021-12-12
  • TS 類型收窄教程示例詳解

    TS 類型收窄教程示例詳解

    這篇文章主要為大家介紹了TS 類型收窄教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • 詳解節(jié)點監(jiān)控相對準(zhǔn)確的計算FMP

    詳解節(jié)點監(jiān)控相對準(zhǔn)確的計算FMP

    這篇文章主要為大家介紹了節(jié)點監(jiān)控相對準(zhǔn)確的計算FMP詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • 微信小程序 頁面跳轉(zhuǎn)如何實現(xiàn)傳值

    微信小程序 頁面跳轉(zhuǎn)如何實現(xiàn)傳值

    這篇文章主要介紹了微信小程序 頁面跳轉(zhuǎn)如何實現(xiàn)傳值的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 微信小程序 本地圖片按照屏幕尺寸處理

    微信小程序 本地圖片按照屏幕尺寸處理

    這篇文章主要介紹了微信小程序 本地圖片按照屏幕尺寸處理的相關(guān)資料,這里提供具體實現(xiàn)步驟,需要的朋友可以參考下
    2017-08-08
  • 微信小程序 歡迎界面開發(fā)的實例詳解

    微信小程序 歡迎界面開發(fā)的實例詳解

    這篇文章主要介紹了微信小程序 歡迎界面開發(fā)的實例詳解的相關(guān)資料,這里實現(xiàn)歡迎界面的簡單實例和實現(xiàn)代碼及實現(xiàn)效果圖,需要的朋友可以參考下
    2016-11-11

最新評論