第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機(jī)立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

無法理解 javascript 中的 compose reduce 示例中發(fā)生了什么?

無法理解 javascript 中的 compose reduce 示例中發(fā)生了什么?

慕尼黑8549860 2023-07-14 10:02:48
var user1 = {  name: 'Nady',  active: true,  cart: [],  purchase: [],};var compose = function test1(f, g) {  return function test2(...args) {    return f(g(...args));  };};function userPurchase(...fns) {  return fns.reduce(compose);}userPurchase(  empty,  addItemToPurchase,  applayTax,  addItemToCart)(user1, { name: 'laptop', price: 876 });function addItemToCart(user, item) {  return { ...user, cart: [item] };}function applayTax(user) {  var { cart } = user;  var taxRate = 1.3;  var updatedCart = cart.map(function updateCartItem(item) {    return { ...item, price: item.price * taxRate };  });  return { ...user, cart: updatedCart };}function addItemToPurchase(user) {  return { ...user, purchase: user.cart };}function empty(user) {  return { ...user, cart: [] };}我不太明白這個例子。我嘗試使用調(diào)試器單步執(zhí)行它并得出以下結(jié)論:當(dāng)我調(diào)用函數(shù)時userPurchase, willreduce起作用,并且在其結(jié)束時fwill be test2,gwill beaddItemToCart然后test2作為累積值返回。然后我們稱其(user1, { name: 'laptop', price: 876 })為參數(shù)傳遞,并g在其中稱為addItemToCart。我不明白每次函數(shù)調(diào)用自身時如何g更改為applayTax, then addItemToPurchase, then 。emptytest2這是如何或為何發(fā)生的?
查看完整描述

3 回答

?
守候你守候我

TA貢獻(xiàn)1802條經(jīng)驗 獲得超10個贊

可能讓您感到困惑的是從字面上理解這個術(shù)語accumulator。按照慣例,這是減速器的第一個參數(shù)的名稱。但沒有必要用它來積累價值。在本例中,它用于組合一系列函數(shù)。


減速器第一個參數(shù)的真正含義是previouslyReturnedValue:


function compose(previouslyReturnedValue, g) {

  return function (...args) {

    return previouslyReturnedValue(g(...args));

  };

}

那么讓我們來看看這個循環(huán):


[empty, addItemToPurchase, applayTax, addItemToCart].reduce(

    (f,g) => {

        return (...args) => {

            return f(g(...args));

        }

    }

);

第一輪循環(huán),f = empty和g = addItemToPurchase。這將導(dǎo)致compose返回:


return (...args) => {

    return empty(addItemToPurchase(...args));

}

離開數(shù)組變?yōu)椋篬applayTax, addItemToCart]


第二輪循環(huán)f = (...args) => {return empty(addItemToPurchase(...args))}和g = applyTax。這將導(dǎo)致compose返回:


return (...args) => {

    return empty(addItemToPurchase(applyTax(...args)));

}

我們繼續(xù)這個邏輯,直到我們最終compose返回完整的函數(shù)鏈:


return (...args) => {

    return empty(addItemToPurchase(applyTax(addItemToCart(...args))));

}

同一流程的替代視圖

如果上面的內(nèi)容有點難以理解,那么讓我們?yōu)閒每個循環(huán)中的匿名函數(shù)命名。


在第一輪中我們得到:


function f1 (...args) {

    return empty(addItemToPurchase(...args));

}

在第二輪中我們得到:


function f2 (...args) {

    return f1(applyTax(...args));

}

在最后一輪我們得到:


function f3 (...args) {

    return f2(addItemToCart(...args));

}

f3返回的就是這個函數(shù)reduce()。所以當(dāng)你調(diào)用reduce的返回值時它會嘗試做:


f2(addItemToCart(...args))

哪個將調(diào)用addItemToCart(),然后調(diào)用f2哪個將執(zhí)行:


f1(applyTax(...args))

哪個將調(diào)用applyTax(),然后調(diào)用f1哪個將執(zhí)行:


empty(addItemToPurchase(...args))

哪個會調(diào)用addItemToPurchase()然后調(diào)用empty()


總長DR

基本上所有這些都是在做:


let tmp;


tmp = addItemToCart(args);

tmp = applyTax(tmp);

tmp = addItemToPurchase(tmp);

tmp = empty(tmp);

更易讀的版本

有一種方法可以實現(xiàn)這個邏輯,如果我們放棄的話,它會更具可讀性和更容易理解reduce()。map()我個人喜歡像and這樣的函數(shù)數(shù)組方法,reduce()但這是一種罕見的情況,常規(guī)for循環(huán)可能會導(dǎo)致代碼更具可讀性和可調(diào)試性。這是一個簡單的替代實現(xiàn),它執(zhí)行完全相同的操作:


function userPurchase(...fns) {

  return function(...args) {

    let result = args;


    // The original logic apply the functions in reverse:

    for (let i=fns.length-1; i>=0; i--) {

        let f = fns[i];

        result = f(result);

    }


    return result;

  }

}

userPurchase就我個人而言,我發(fā)現(xiàn)使用循環(huán)的實現(xiàn)for比版本更具可讀性reduce。它顯然以相反的順序循環(huán)遍歷函數(shù),并使用上一個函數(shù)的結(jié)果繼續(xù)調(diào)用下一個函數(shù)。


查看完整回答
反對 回復(fù) 2023-07-14
?
瀟瀟雨雨

TA貢獻(xiàn)1833條經(jīng)驗 獲得超4個贊

這有幫助嗎?


var user1 = {

  name: 'Nady',

  active: true,

  cart: [],

  purchase: [],

};


function compose(f, g) {

  const composition = function(...args) {

    console.log('f name', f.name);

    console.log('g name', g.name);

    return f(g(...args));

  };

  Object.defineProperty(composition, 'name', {

    value: 'composition_of_' + f.name + '_and_' + g.name,

    writable: false

  });

  return composition;

};


function userPurchase(...fns) {

  return fns.reduce(compose);

}


function addItemToCart(user, item) {

  return { ...user, cart: [item] };

}


function applayTax(user) {

  var { cart } = user;

  var taxRate = 1.3;

  var updatedCart = cart.map(function updateCartItem(item) {

    return { ...item, price: item.price * taxRate };

  });


  return { ...user, cart: updatedCart };

}

function addItemToPurchase(user) {

  return { ...user, purchase: user.cart };

}

function empty(user) {

  return { ...user, cart: [] };

}


const result = userPurchase(

  empty,

  addItemToPurchase,

  applayTax,

  addItemToCart

)(user1, { name: 'laptop', price: 876 });


console.log(result);


假設(shè)您需要輸入一個數(shù)字,加十,然后加倍。您可以編寫一些函數(shù),例如:


const add_ten = function(num) { return num + 10; };

const double = function(num) { return num * 2; };


const add_ten_and_double = function(num) { return double(add_ten(num)); };

你也可以寫同樣的東西:


function compose(outer_function, inner_function) {

  return function(num) {

    return outer_function(inner_function(num));

  };

};


const add_ten = function(num) { return num + 10; };

const double = function(num) { return num * 2; };


const add_ten_and_double = compose(double, add_ten);


console.log('typeof add_ten_and_double:', typeof add_ten_and_double);

console.log('add_ten_and_double:', add_ten_and_double(4));


使用 compose,我們創(chuàng)建了一個與原始 add_ten_and_double 函數(shù)執(zhí)行相同操作的函數(shù)。到目前為止這有意義嗎?(A點)。


如果我們決定添加五個,我們可能會得到:


function compose(outer_function, inner_function) {

  return function(num) {

    return outer_function(inner_function(num));

  };

};


const add_ten = function(num) { return num + 10; };

const double = function(num) { return num * 2; };

const add_five = function(num) { return num + 5; };


const add_ten_and_double_and_add_five = compose(compose(add_five, double), add_ten);


console.log('typeof add_ten_and_double_and_add_five :', typeof add_ten_and_double_and_add_five);

console.log('add_ten_and_double_and_add_five :', add_ten_and_double_and_add_five(4));


現(xiàn)在我們已經(jīng)使用一個函數(shù)和一個由另外兩個函數(shù)組成的函數(shù)運(yùn)行 compose,但我們得到的仍然只是一個接受數(shù)字并返回數(shù)字的函數(shù)。到目前為止這有意義嗎?(B點)。


如果我們想添加更多函數(shù),那么我們最終會在代碼中進(jìn)行大量 compose 調(diào)用,因此我們可以只說“給我所有這些函數(shù)的組合”,它可能看起來像:


function compose(outer_function, inner_function) {

  return function(num) {

    return outer_function(inner_function(num));

  };

};


const add_ten = function(num) { return num + 10; };

const double = function(num) { return num * 2; };

const add_five = function(num) { return num + 5; };


functions_to_compose = [add_five, double, add_ten];


let composition;

functions_to_compose.forEach(function(to_compose) {

  if(!composition)

    composition = to_compose;

  else

    composition = compose(composition, to_compose);

});


const add_ten_and_double_and_add_five = composition;


console.log('typeof add_ten_and_double_and_add_five:', typeof add_ten_and_double_and_add_five);

console.log('add_ten_and_double_and_add_five:', add_ten_and_double_and_add_five(4));


fns.reduce(compose); 代碼中的 userPurchase 基本上與此處的 forEach 循環(huán)執(zhí)行相同的操作,但更簡潔。為什么 add_ten_and_double_and_add_ Five 是一個可以傳入數(shù)字的函數(shù),并且functions_to_compose 中的所有操作都應(yīng)用于該數(shù)字(從最后到第一個),這是否有意義?(C點)。


查看完整回答
反對 回復(fù) 2023-07-14
?
HUH函數(shù)

TA貢獻(xiàn)1836條經(jīng)驗 獲得超4個贊

重命名

部分問題只是在于命名。引入另外一項功能并重命名另外兩項功能將有所幫助。


var composeTwo = function test1(f, g) {

  return function test2(...args) {

    return f(g(...args));

  };

};


function composeMany(...fns) {

  return fns.reduce(composeTwo);

}


const userPurchase = composeMany(

  empty,

  addItemToPurchase,

  applyTax,

  addItemToCart


userPurchase(user1, { name: 'laptop', price: 876 });

//=> {active: true, cart: [], name: "Nady", purchase: [{name: "laptop", price: 1138.8}]}


// other functions elided

composeTwo(最初稱為compose) 是一個函數(shù),它接受兩個函數(shù)并返回一個新函數(shù),該函數(shù)接受一些輸入,使用該輸入調(diào)用第二個函數(shù),然后使用結(jié)果調(diào)用第一個函數(shù)。這是函數(shù)的簡單數(shù)學(xué)組合。


composeMany(最初稱為 - 非常令人困惑 - userPurchase)將此組合擴(kuò)展為在函數(shù)列表上工作,從傳遞的參數(shù)開始reduce,按順序調(diào)用到目前為止管道結(jié)果上的每個函數(shù)。請注意,它的工作范圍是從列表中的最后一項到第一項。


我們用它來定義 new userPurchase,它將empty、addItemToPurchase和傳遞給。這會返回一個函數(shù),然后該函數(shù)將按順序應(yīng)用它們,執(zhí)行相當(dāng)于applyTaxaddItemToCartpipelinefunction (...args) {return empty1(addItemToPurchase(applyTax(addItemToCart(...args))))}


我們可以在這段代碼中看到它的實際效果:

var user1 = {

  name: 'Nady',

  active: true,

  cart: [],

  purchase: [],

};


var composeTwo = function test1(f, g) {

  return function test2(...args) {

    return f(g(...args));

  };

};


function composeMany (...fns) {

  return fns.reduce(composeTwo);

}


const userPurchase = composeMany (

  empty,

  addItemToPurchase,

  applyTax,

  addItemToCart


console .log (

  userPurchase(user1, { name: 'laptop', price: 876 })

)



function addItemToCart(user, item) {

  return { ...user, cart: [item] };

}

function applyTax(user) {

  var { cart } = user;

  var taxRate = 1.3;

  var updatedCart = cart.map(function updateCartItem(item) {

    return { ...item, price: item.price * taxRate };

  });


  return { ...user, cart: updatedCart };

}

function addItemToPurchase(user) {

  return { ...user, purchase: user.cart };

}

function empty(user) {

  return { ...user, cart: [] };

}

.as-console-wrapper {max-height: 100% !important; top: 0}

現(xiàn)代語法

然而,我會發(fā)現(xiàn)使用更現(xiàn)代的 JS 語法會更干凈。這是非常等價的,但更干凈:


const composeTwo = (f, g)  => (...args)  => 

  f (g (...args))


const composeMany = (...fns) =>

  fns .reduce (composeTwo)


// .. other functions elided


const userPurchase = composeMany (

  empty,

  addItemToPurchase,

  applyTax,

  addItemToCart

)

很明顯,這里composeTwo接受兩個函數(shù)并返回一個函數(shù)。在了解和理解后.reduce,應(yīng)該清楚composeMany接受一個函數(shù)列表并返回一個新函數(shù)。此版本也將此更改應(yīng)用于其余功能,可在以下代碼段中找到:

var composeTwo = (f, g)  => (...args)  => 

  f (g (...args))


const composeMany = (...fns) =>

  fns .reduce (composeTwo)


const addItemToCart = (user, item) =>

  ({ ...user, cart: [item] })


const applyTax = (user)  => {

  var { cart } = user;

  var taxRate = 1.3;

  var updatedCart = cart .map (item => ({ ...item, price: item .price * taxRate }))

  return { ...user, cart: updatedCart };

}


const addItemToPurchase = (user) =>

  ({ ...user, purchase: user.cart })


const empty = (user) =>

  ({ ...user, cart: [] })



const userPurchase = composeMany (

  empty,

  addItemToPurchase,

  applyTax,

  addItemToCart

)


const user1 = {

  name: 'Nady',

  active: true,

  cart: [],

  purchase: [],

};


console .log (

  userPurchase (user1, { name: 'laptop', price: 876 })

)

.as-console-wrapper {max-height: 100% !important; top: 0}

如何reduce以及如何composeTwo一起工作

在這里,我們嘗試演示如何reducecomposeTwo多個函數(shù)組合為一個函數(shù)。

第一步,缺少init參數(shù) to ,因此 JS 使用數(shù)組中的第一個值作為初始值,然后開始迭代第二個值。reduce所以reduce首先composeTwoemptyand調(diào)用addItemToPurchase,產(chǎn)生一個相當(dāng)于

(...args) => empty (addItemsToPurchase (...args))

現(xiàn)在reduce將該函數(shù) 和applyTax傳遞給compose,產(chǎn)生一個類似的函數(shù)

(...args) => ((...args2) => empty (addItemsToPurchase (...args2))) (applyTax (...args))

現(xiàn)在其結(jié)構(gòu)如下:

(x) => ((y) => f ( g (y)) (h (x))

其中x代表...args、y代表...args2f代表empty、g代表addItems、h代表applyTax

但右側(cè)是一個函數(shù) ( ),并對其應(yīng)用了(y) => f ( g ( y))值。h (x)這與y在主體中替換為h(x), 產(chǎn)生相同f (g (h (x))),因此該函數(shù)相當(dāng)于 (x) => f (g (h (x))),并且通過替換我們的原始值,最終結(jié)果為

(...args) => empty (addItemsToPurchase (applyTax ( ...args)))

請注意,在構(gòu)建函數(shù)時,現(xiàn)在不會對函數(shù)應(yīng)用值。當(dāng)調(diào)用結(jié)果函數(shù)時就會發(fā)生這種情況。記憶中,這還是類似的東西(...args) => ((...args2) => empty (addItems (...args2))) (applyTax (...args))。但這個合乎邏輯的版本展示了它是如何工作的。

當(dāng)然,我們現(xiàn)在再次這樣做addItemToCart

(...args) => ((...args2) => empty (addItemsToPurchase (applyTax ( ...args2)))) (addItemToCart (...args))

通過同樣的應(yīng)用,我們得到等價的

(...args) => empty (addItems (applyTax ( addItemToCart (...args))))

這就是這些函數(shù)的組成的基本定義。

清理稅率

硬編碼的稅率有些奇怪。我們可以通過在調(diào)用中使用參數(shù)來解決這個問題userPurchase。這也允許我們清理該applyTax函數(shù):

const applyTax = (taxRate) => ({cart, ...rest}) => ({

  ... rest,

  cart: cart .map (item => ({ ...item, price: item .price * taxRate }))

})


const userPurchase = (taxRate) => composeMany (

  empty,

  addItemToPurchase,

  applyTax(taxRate),

  addItemToCart

)


// ...


userPurchase (1.3) (user1, { name: 'laptop', price: 876 })

請注意,此參數(shù)的柯里化性質(zhì)讓我們選擇僅應(yīng)用此值來獲取特定于稅率的函數(shù):


const someDistrictPurchase = userPurchase (1.12) // 12% tax


someDistrictPurchase(user, item)

我們可以在另一個片段中看到這一點:

var composeTwo = (f, g)  => (...args)  => 

  f (g (...args))


const composeMany = (...fns) =>

  fns .reduce (composeTwo)


const addItemToCart = (user, item) =>

  ({ ...user, cart: [item] })


const applyTax = (taxRate) => ({cart, ...rest}) => ({

  ... rest,

  cart: cart .map (item => ({ ...item, price: item .price * taxRate }))

})


const addItemToPurchase = (user) =>

  ({ ...user, purchase: user.cart })


const empty = (user) =>

  ({ ...user, cart: [] })


const userPurchase = (taxRate) => composeMany (

  empty,

  addItemToPurchase,

  applyTax(taxRate),

  addItemToCart

)


var user1 = { name: 'Nady', active: true, cart: [], purchase: []}


console .log (

  userPurchase (1.3) (user1, { name: 'laptop', price: 876 })

)

.as-console-wrapper {max-height: 100% !important; top: 0}

教訓(xùn)

  • 函數(shù)組合是函數(shù)式編程(FP)的重要組成部分。雖然擁有composeTwo和 等函數(shù)很有幫助composeMany,但如果它們具有易于理解的名稱,那就更好了。(請注意,這compose是第一個的完全合法的名稱。我在這里的更改只是為了使區(qū)別更清晰。)在我看來,最大的問題是作為組合函數(shù)composeMany的原始名稱。userPurchase這讓很多事情變得混亂。

  • 現(xiàn)代 JS(箭頭函數(shù)、休息/擴(kuò)展和解構(gòu))使代碼不僅更簡潔,而且通常更容易理解。


查看完整回答
反對 回復(fù) 2023-07-14
  • 3 回答
  • 0 關(guān)注
  • 167 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學(xué)習(xí)伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號