国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

[譯] 理解 JavaScript Mutation 突變和 PureFunction 純函數(shù)

Enlightenment / 3190人閱讀

摘要:突變引起狀態(tài)的改變。純函數(shù)和副作用純函數(shù)是接受輸入并返回值而不修改其范圍之外的任何數(shù)據(jù)的函數(shù)副作用。如果它們不同,則調(diào)用函數(shù),以更新新狀態(tài)。

作者:Chidume Nnamdi

英文原文:https://blog.bitsrc.io/unders...

[譯] 理解 JavaScript Mutation 突變和 PureFunction 純函數(shù)

不可變性、純函數(shù)、副作用,狀態(tài)可變這些單詞我們幾乎每天都會(huì)見到,但我們幾乎不知道他們是如何工作的,以及他們是什么,他們?yōu)檐浖_發(fā)帶來(lái)了什么好處。

在這篇文章中,我們將深入研究所有這些,以便真正了解它們是什么以及如何利用它們來(lái)提高我們的Web應(yīng)用程序的性能。

Javascript:原始數(shù)據(jù)類型和引用數(shù)據(jù)類型

我們將首先了解JS如何維護(hù)以及訪問到我們的數(shù)據(jù)類型。

在JS中,有原始數(shù)據(jù)類型和引用數(shù)據(jù)類型。原始數(shù)據(jù)類型由值引用,而非原始/引用數(shù)據(jù)類型指向內(nèi)存地址。

原始數(shù)據(jù)類型是:

Boolean

Number

String

Null

Undefined

Symbol

引用數(shù)據(jù)類型:

Object

Arrays

當(dāng)我們寫原始數(shù)據(jù)類型時(shí)是這個(gè)樣子:

let one = 1

在調(diào)用堆棧中,one 變量直接指向值 1:

Call Stack
#000    one -> | 1 |
#001           |   |
#002           |   |
#003           |   |

如果我們改變這個(gè)值:

let one = 1
one = 3

變量 one 的內(nèi)存地址 #000 原本存儲(chǔ) 1 這個(gè)值,會(huì)直接變成 3

但是,如果我們像這樣寫一個(gè)引用數(shù)據(jù)類型:

let arr = {
    one: 1
}

或:

let arr = new Object()
arr.one = 1

JS將在內(nèi)存的堆中創(chuàng)建對(duì)象,并將對(duì)象的內(nèi)存地址存儲(chǔ)在堆上:

Call Stack       Heap
#000    arr -> | #101 |   #101 | one: 1 |
#001           |      |   #102 |        |
#002           |      |   #103 |        |
#003           |      |   #104 |        |

看到 arr 不直接存儲(chǔ)對(duì)象,而是指向?qū)ο蟮膬?nèi)存位置(#101)。與直接保存其值的原始數(shù)據(jù)類型不同。

let arr = { one: 1 }
// arr holds the memory location of the object {one: 1}
// `arr` == #101
let one = 1;
// `one` a primitive data type holds the value `1`
// one == 1

如果我們改變 arr 中的屬性,如下所示:

arr.one = 2

那么基本上我們就是在告訴程序更改 arr 對(duì)對(duì)象屬性值的指向。如果你對(duì) C/C++ 等語(yǔ)言的指針和引用比較熟悉,那么這些你都會(huì)很容易理解。

傳遞引用數(shù)據(jù)類型時(shí),你只是在傳遞其內(nèi)存位置的遞值,而不是實(shí)際的值。

function chg(arg) {
    //arg points to the memory address of { one: 1 }
    arg.one = 99
    // This modification will affect { one: 1 } because arg points to its memory address, 101
}
let arr = { one: 1 } 
// address of `arr` is `#000`
// `arr` contains `#101`, adrress of object, `{one: 1}` in Heap
log(arr); // { one: 1 }
chg(arr /* #101 */)
// #101 is passed in
log(arr) // { one: 99 }
// The change affected `arr`
譯者注:arr 本身的內(nèi)存地址是 #000;arr 其中保存了一個(gè)地址 #101;這個(gè)地址指向?qū)ο?{one:1};在調(diào)用 chg 函數(shù)的時(shí)候,那么修改 arg 屬性 one 就會(huì)修改 arr 對(duì)應(yīng)的 #101 地址指向的對(duì)象 {one:1}

因?yàn)橐脭?shù)據(jù)類型保存的是內(nèi)存地址,所以對(duì)他的任何修改都會(huì)影響到他指向的內(nèi)存。

如果我們傳入一個(gè)原始數(shù)據(jù)類型:

function chg(arg) {
    arg++
}
let one = 1; // primitive data types holds the actual value of the variable.
log(one) // 1
chg(one /* 1 */)
// the value of `one` is passed in.
log(one) // one is still `1`. No change because primitives only hold the value
譯者注:不像原始數(shù)據(jù)類型,他的值是多少就是多少如果修改了這個(gè)值,那么直接修改所在內(nèi)存對(duì)應(yīng)的這個(gè)值
狀態(tài)突變和不可變性

在生物學(xué)領(lǐng)域,我們知道 DNA 以及 DNA 突變。DNA 有四個(gè)基本元素,分別是 ATGC。這些生成了編碼信息,在人體內(nèi)產(chǎn)生一種蛋白質(zhì)。

ATATGCATGCGATA
||||||||||||||   
TACGAGCTAGGCTA
|
|
v
AProteinase
Information to produce a protein (eg, insulin etc)

上述DNA鏈編碼信息以產(chǎn)生可用于骨結(jié)構(gòu)比對(duì)的AP蛋白酶蛋白。

如果我們改變DNA鏈配對(duì),即使是一對(duì):

ATATGCATGCGATA
||||||||||||||   
TACGAGCTAGGCTA
|
v 
GTATGCATGCGATA
||||||||||||||   
TACGAGCTAGGCTA

DNA將產(chǎn)生不同的蛋白質(zhì),因?yàn)楫a(chǎn)生蛋白質(zhì)AP蛋白酶的信息已經(jīng)被篡改。因此產(chǎn)生了另一種蛋白質(zhì),其可能是良性的或在某些情況下是有毒的。

GTATGCATGCGATA
||||||||||||||   
TACGAGCTAGGCTA
|
|
V
Now produces _AProtienase

我們稱這種變化突變DNA突變

突變引起DNA狀態(tài)的改變。

而對(duì)于 JS 來(lái)說(shuō),引用數(shù)據(jù)類型(數(shù)組,對(duì)象)都被稱為數(shù)據(jù)結(jié)構(gòu)。這些數(shù)據(jù)結(jié)構(gòu)保存信息,以操縱我們的應(yīng)用程序。

let state = {
    wardens: 900,
    animals: 800
}

上面名為 state 的對(duì)象保存了 Zoo 應(yīng)用程序的信息。如果我們改變了 animals 屬性的值:

let state = {
    wardens: 900,
    animals: 800
 }
state.animals = 90

我們的 state 對(duì)象會(huì)保存或編碼一個(gè)新的信息:

state = {
    wardens: 900,
    animals: 90    
}

這就叫突變 mutation

我們的 state 從:

state = {
    wardens: 900,
    animals: 800    
}

變?yōu)椋?/p>

state = {
    wardens: 900,
    animals: 90    
}

當(dāng)我們想要保護(hù)我們的 state 時(shí)候,這就需要用到不可變性了 immutability。為了防止我們的 state 對(duì)象發(fā)生變化,我們必須創(chuàng)建一個(gè) state 對(duì)象的新實(shí)例。

function bad(state) {
    state.prp = "yes"
    return state
}
function good(state) {
    let newState = { ...state }
    newState.prp = "yes"
    return newState
}

不可變性使我們的應(yīng)用程序狀態(tài)可預(yù)測(cè),提高我們的應(yīng)用程序的性能速率,并輕松跟蹤狀態(tài)的變化。

純函數(shù)和副作用

純函數(shù)是接受輸入并返回值而不修改其范圍之外的任何數(shù)據(jù)的函數(shù)(副作用)。它的輸出或返回值必須取決于輸入/參數(shù),純函數(shù)必須返回一個(gè)值。

譯者注:純函數(shù)必須要滿足的條件:不產(chǎn)生副作用、返回值只取決于傳入的參數(shù),純函數(shù)必須返回一個(gè)值
function impure(arg) {
    finalR.s = 90
    return arg * finalR.s
}

上面的函數(shù)不是純函數(shù),因?yàn)樗薷牧似浞秶獾臓顟B(tài) finalR.s

function impure(arg) {
    let f = finalR.s * arg
}

上面的函數(shù)也不是純函數(shù),因?yàn)殡m然它沒有修改任何外部狀態(tài),但它沒有返回值。

function impure(arg) {
    return finalR.s * 3
}

上面的函數(shù)是不純的,雖然它不影響任何外部狀態(tài),但它的輸出返回 finalR.s * 3 不依賴于輸入 arg。純函數(shù)不僅必須返回一個(gè)值,還必須依賴于輸入。

function pure(arg) {
    return arg * 4
}

上面的函數(shù)才是純函數(shù)。它不會(huì)對(duì)任何外部狀態(tài)產(chǎn)生副作用,它會(huì)根據(jù)輸入返回輸出。

能夠帶來(lái)的好處

就個(gè)人而言,我發(fā)現(xiàn)的唯一能夠讓人理解的好處是 mutation tracking 變異追蹤。

知道何時(shí)渲染你的狀態(tài)是非常重要的事情。很多 JS 框架設(shè)計(jì)了不錯(cuò)的方法來(lái)檢測(cè)何時(shí)去渲染其狀態(tài)。但是最重要的是,要知道在首次渲染完畢后,何時(shí)觸發(fā)再渲染 re-render。這就被稱為變異追蹤了。這需要知道什么時(shí)候狀態(tài)被改變了或者說(shuō)變異了。以便去觸發(fā)再渲染 re-render

于我們已經(jīng)實(shí)現(xiàn)了不變性,我們確信我們的應(yīng)用程序狀態(tài)不會(huì)在應(yīng)用程序中的任何位置發(fā)生變異,況且純函數(shù)完全準(zhǔn)尋其處理邏輯和原則(譯者注:不會(huì)產(chǎn)生副作用)。這就很容易看出來(lái)到底是哪里出現(xiàn)變化了(譯者注:反正不是純函數(shù)也不是 immutable 變量)。

let state = {
    add: 0,
}
funtion render() {
    //...
}
function effects(state,action) {
    if(action == "addTen") {
        return {...state, add: state.add + 10}
    }
    return state;
}
function shouldUpdate(s) {
    if(s === state){
        return false
    }
    return true
}
state = effects(state, "addTen")
if(shouldUpdate(state)) {
    render();
}

這里有個(gè)小程序。這里有個(gè) state 對(duì)象,對(duì)象只有一個(gè)屬性 add。render 函數(shù)正常渲染程序的屬性。他并不會(huì)在程序的任何改變時(shí)每次都觸發(fā)渲染 state 對(duì)象,而是先檢查 state 對(duì)象是否改變。

就像這樣,我們有一個(gè) effects 函數(shù)和一個(gè)純函數(shù),這兩個(gè)函數(shù)都用來(lái)去修改我們的 state 對(duì)象。你會(huì)看到它返回了一個(gè)新的 state 對(duì)象,當(dāng)要更改狀態(tài)時(shí)返回新狀態(tài),并在不需要修改時(shí)返回相同的狀態(tài)。

因此,我們有一個(gè)shouldUpdate函數(shù),它使用===運(yùn)算符檢查舊狀態(tài)和新狀態(tài)是否相同。如果它們不同,則調(diào)用render函數(shù),以更新新狀態(tài)。

結(jié)論

我們研究了 Web 開發(fā)中這幾個(gè)最常見的術(shù)語(yǔ),并展示了它們的含義以及它們的用途。如果你付諸實(shí)踐,這將是非常有益的。

如果有任何對(duì)于這篇文章的問題,如我應(yīng)該增加、修改或刪除,請(qǐng)隨時(shí)評(píng)論、發(fā)送電子郵件或直接 DM 我。干杯

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/102576.html

相關(guān)文章

  • 即學(xué)即用系列一:函數(shù)

    摘要:于是就有了即學(xué)即用這個(gè)系列的文章。系列第一篇,就從純函數(shù)開始,由于我是前端方向,所以就從語(yǔ)言中的純函數(shù)說(shuō)起。并行代碼純函數(shù)是健壯的,改變執(zhí)行次序不會(huì)對(duì)系統(tǒng)造成影響,因此純函數(shù)的操作可以并行執(zhí)行。 最近一直在思考如何通過(guò)文章或者培訓(xùn)快速提升團(tuán)隊(duì)的編碼能力,總結(jié)下來(lái)其實(shí)技術(shù)的學(xué)習(xí)分為兩類:一種是系統(tǒng)性的學(xué)習(xí),比如學(xué)習(xí)一門語(yǔ)言,學(xué)習(xí)一個(gè)開發(fā)框架,這更需要自己從入門到進(jìn)階再到實(shí)踐一步步系統(tǒng)性的...

    Hanks10100 評(píng)論0 收藏0
  • JavaScript工作原理(九):使用MutationObserver跟蹤DOM的改變

    摘要:概觀是現(xiàn)代瀏覽器提供的,用于檢測(cè)中的變化。您可能正在使用所見即所得的編輯器,試圖實(shí)現(xiàn)撤銷重做功能。函數(shù)的第一個(gè)參數(shù)是在一個(gè)批次中發(fā)生的所有改變的集合。雖然有用,但中的每一次更改都會(huì)觸發(fā)突變事件,這又會(huì)導(dǎo)致性能問題。 showImg(https://segmentfault.com/img/bV9Z7q?w=1016&h=252);Web應(yīng)用程序在客戶端越來(lái)越重要,原因很多,比如需要更豐...

    1fe1se 評(píng)論0 收藏0
  • vuex淺入淺出

    摘要:來(lái)自不同視圖的行為需要變更同一狀態(tài)。圖解后端的行為,響應(yīng)在上的用戶輸入導(dǎo)致的狀態(tài)變化。中的非常類似于事件每個(gè)都有一個(gè)字符串的事件類型和一個(gè)回調(diào)函數(shù)。 什么是Vuex? Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。 Vuex采用和Redux類似的單向數(shù)據(jù)流的方式來(lái)管理數(shù)據(jù)。用戶...

    琛h。 評(píng)論0 收藏0
  • Tasks, microtasks, queues and schedules(

    摘要:事件循環(huán)持續(xù)運(yùn)行,直到清空列隊(duì)的任務(wù)。在執(zhí)行期間,瀏覽器可能更新渲染。線索可能會(huì)發(fā)生多次。由于冒泡,函數(shù)再一次執(zhí)行。這意味著隊(duì)列不會(huì)在事件回調(diào)之間處理,而是在它們之后處理。當(dāng)觸發(fā)成功事件時(shí),相關(guān)的對(duì)象在事件之后轉(zhuǎn)為非激活狀態(tài)第四步。 一 前言 一直想對(duì)異步處理做一個(gè)研究,在查閱資料時(shí)發(fā)現(xiàn)了這篇文章,非常深入的解釋了事件循環(huán)中重的任務(wù)隊(duì)列。原文中有代碼執(zhí)行工具,強(qiáng)烈建議自己執(zhí)行一下查看結(jié)...

    tianyu 評(píng)論0 收藏0
  • [] Elixir、Phoenix、Absinthe、GraphQL、React Apollo

    摘要:對(duì)于每個(gè)案例,我們插入所需要的測(cè)試數(shù)據(jù),調(diào)用需要測(cè)試的函數(shù)并對(duì)結(jié)果作出斷言。我們將這個(gè)套接字和用戶返回以供我們其他的測(cè)試使用。 原文地址:Elixir, Phoenix, Absinthe, GraphQL, React, and Apollo: an absurdly deep dive - Part 2 原文作者:Zach Schneider 譯文出自:掘金翻譯計(jì)劃 本文永久鏈接:gi...

    Cympros 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<