最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript偏函數(shù)與柯里化實例詳解

 更新時間:2019年03月27日 12:03:57   作者:neweastsun  
這篇文章主要介紹了JavaScript偏函數(shù)與柯里化,結合實例形式詳細分析了JavaScript偏函數(shù)與柯里化的概念、原理、定義、使用方法及相關操作注意事項,需要的朋友可以參考下

本文實例講述了JavaScript偏函數(shù)與柯里化。分享給大家供大家參考,具體如下:

到目前為止我們僅討論綁定this,現(xiàn)在讓我們更深入學習。
我們不僅能綁定this,也可以是參數(shù),這較少使用,但有時很方便。

bind完整的語法為:

let bound = func.bind(context, arg1, arg2, ...);

可以綁定上下文this和函數(shù)的初始參數(shù)。舉例,我們有個乘法函數(shù)mul(a,b):

function mul(a, b) {
 return a * b;
}

我們可以在該函數(shù)的基礎上使用綁定創(chuàng)建一個double函數(shù):

let double = mul.bind(null, 2);
alert( double(3) ); // = mul(2, 3) = 6
alert( double(4) ); // = mul(2, 4) = 8
alert( double(5) ); // = mul(2, 5) = 10

調(diào)用mul.bind(null, 2)創(chuàng)建新函數(shù)double,傳遞調(diào)用mul函數(shù),固定第一個參數(shù)上下文為null,第二個參數(shù)為2,多個參數(shù)傳遞也是如此。

這稱為偏函數(shù)應用——我們創(chuàng)造一個新函數(shù),讓現(xiàn)有的一些參數(shù)值固定。

注意,這里確實不用this,但bind需要,所以必須使用null。

在下面代碼中函數(shù)triple實現(xiàn)乘以3的功能:

let triple = mul.bind(null, 3);
alert( triple(3) ); // = mul(3, 3) = 9
alert( triple(4) ); // = mul(3, 4) = 12
alert( triple(5) ); // = mul(3, 5) = 15

為什么我們通常使用偏函數(shù)?

這里我們偏函數(shù)的好處是:通過創(chuàng)建一個名稱易懂的獨立函數(shù)(double,triple),調(diào)用是無需每次傳入第一個參數(shù),因為第一個參數(shù)通過bind提供了固定值。

另一種使用偏函數(shù)情況是,當我們有一個很通用的函數(shù),為了方便提供一個較常用的變體。

舉例,我們有一個函數(shù)send(from, to, text),那么使用偏函數(shù)可以創(chuàng)建一個從當前用戶發(fā)送的變體:sendTo(to, text)

使用沒有上下文的偏函數(shù)

如果想固定一些參數(shù),但不綁定this呢?

內(nèi)置的bind不允許這樣,我們不能忽略上下文并跳轉到參數(shù)。幸運的是,可以僅綁定參數(shù)partial函數(shù)容易實現(xiàn)。

如下:

function partial(func, ...argsBound) {
 return function(...args) { // (*)
  return func.call(this, ...argsBound, ...args);
 }
}
// Usage:
let user = {
 firstName: "John",
 say(time, phrase) {
  alert(`[${time}] ${this.firstName}: ${phrase}!`);
 }
};
// add a partial method that says something now by fixing the first argument
user.sayNow = partial(user.say, new Date().getHours() + ':' + new Date().getMinutes());
user.sayNow("Hello");
// Something like:
// [10:00] Hello, John!

調(diào)用partial(func[, arg1, arg2...])函數(shù)的結果為調(diào)用func的包裝器(*號行):

  • this一致(因為user.sayNow是通過user調(diào)用的)
  • 然后給其...garsBound—— partial使用該參數(shù)("10:00")進行調(diào)用。
  • 然后提供參數(shù)...gars——提供給包裝器的參數(shù)(“Hello“)

所以使用spread運算符很容易實現(xiàn),是嗎?

loadash庫也提供了—.partial實現(xiàn)。

柯里化

有時人們混淆上面提及的偏函數(shù)和另一個名稱為“柯里化”函數(shù)功能,柯里化是另一個有趣的處理函數(shù)技術,這里我們必須要涉及。

柯里化(Currying):轉換一個調(diào)用函數(shù)f(a,b,c)f(a)(b)(c)方式調(diào)用。

讓我們實現(xiàn)柯里化函數(shù),執(zhí)行一個兩元參數(shù)函數(shù),即轉換f(a,b)f(a)(b):

function curry(func) {
 return function(a) {
  return function(b) {
   return func(a, b);
  };
 };
}
// usage
function sum(a, b) {
 return a + b;
}
let carriedSum = curry(sum);
alert( carriedSum(1)(2) ); // 3

上面是通過一系列包裝器實現(xiàn)的。

  • curry(func)的結果是function(a)的一個包裝器。
  • 當調(diào)用sum(1)是,參數(shù)被保存在詞法環(huán)境中,然后返回新的包裝器function(b)
  • 然后sum(1)(2)提供2并最終調(diào)用function(b),然后傳遞調(diào)用給原始多參數(shù)函數(shù)sum

有一些柯里化的高級實現(xiàn),如lodash庫中_.curry可以實現(xiàn)更復雜功能。其返回一個包裝器,它允許函數(shù)提供全部參數(shù)被正常調(diào)用或返回偏函數(shù)。

function curry(f) {
 return function(..args) {
  // if args.length == f.length (as many arguments as f has),
  //  then pass the call to f
  // otherwise return a partial function that fixes args as first arguments
 };
}

柯里化?應用場景?

高級柯里化允許函數(shù)正常調(diào)用,也可以容易以偏函數(shù)方式調(diào)用。為了理解其優(yōu)勢,我們需要一個實際的示例說明。

舉例,我們有日志函數(shù)log(date,importance,message),格式化輸出信息。實際項目中這些函數(shù)也有許多其他有用的特性,如:通過網(wǎng)絡發(fā)送或過濾:

function log(date, importance, message) {
 alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}

讓我們使用柯里化!

log = _.curry(log);

柯里化后仍然可以正常調(diào)用:log(new Date(), "DEBUG", "some debug");

我們也可以使用柯里化方式調(diào)用:log(new Date())("DEBUG")("some debug"); // log(a)(b)(c)

這里定義一個便捷函數(shù),記錄當天日志:

// todayLog will be the partial of log with fixed first argument
let todayLog = log(new Date());
// use it
todayLog("INFO", "message"); // [HH:mm] INFO message

現(xiàn)在再定義一個便捷函數(shù):記錄當天debug信息:

let todayDebug = todayLog("DEBUG");
todayDebug("message"); // [HH:mm] DEBUG message

所以:

1. 柯里化后沒有失去任何東西,log仍然可以正常調(diào)用。
2. 我們能生成在多個場景使用的便捷偏函數(shù)。

高級柯里化實現(xiàn)

如果你感興趣,這里提供了上面提到的高級柯里化實現(xiàn):

function curry(func) {
 return function curried(...args) {
  if (args.length >= func.length) {
   return func.apply(this, args);
  } else {
   return function(...args2) {
    return curried.apply(this, args.concat(args2));
   }
  }
 };
}
function sum(a, b, c) {
 return a + b + c;
}
let curriedSum = curry(sum);
// still callable normally
alert( curriedSum(1, 2, 3) ); // 6
// get the partial with curried(1) and call it with 2 other arguments
alert( curriedSum(1)(2,3) ); // 6

這里實現(xiàn)看上去有點復雜,但確實很容易理解。curry(func)的結果是包裝器curried,如下所示:

// func is the function to transform
function curried(...args) {
 if (args.length >= func.length) { // (1)
  return func.apply(this, args);
 } else {
  return function pass(...args2) { // (2)
   return curried.apply(this, args.concat(args2));
  }
 }
};

當我們運行時,有兩個分支:

1. 如果傳遞args數(shù)與原函數(shù)已經(jīng)定義的參數(shù)個數(shù)一樣或更長,那么直接調(diào)用。
2. 獲得偏函數(shù):否則,不調(diào)用func函數(shù),返回另一個包裝器pass,提供連接之前的參數(shù)一起做為新參數(shù)重新應用curried。然后再次執(zhí)行一個新調(diào)用,返回一個新偏函數(shù)(如果參數(shù)不夠)或最終結果。

舉例,讓我們看sum(a, b, c)會怎樣,三個參數(shù),所以sum.length=3.

如果調(diào)用curried(1)(2)(3):

1. 第一次調(diào)用curried(1),在詞法環(huán)境中記住1,返回包裝器pass。
2. 使用(2)調(diào)用包裝器pass:其帶著前面的參數(shù)(1),連接他們?nèi)缓笳{(diào)用curried(1,2),因為參數(shù)數(shù)量仍然小于3,返回pass。
3. 再次使用(3)被調(diào)用包裝器pass,帶著之前的參數(shù)(1,2),然后增加3,并調(diào)用curried(1,2,3)——最終有三個參數(shù),傳遞給原始函數(shù)。

如果仍然不清除,可以按順序在腦子里或紙上跟蹤調(diào)用過程。

僅針對函數(shù)參數(shù)長度固定

柯里化需要函數(shù)有已知的參數(shù)數(shù)量固定。

比柯里化多一點

根據(jù)柯里化定義,轉換sum(a,b,c)sum(a)(b)(c).

但在Javascript中大多數(shù)實現(xiàn)是超越定義,也可以讓函數(shù)使用多個參數(shù)變量執(zhí)行。

總結

當把已知函數(shù)的一些參數(shù)固定,結果函數(shù)被稱為偏函數(shù),通過使用bind獲得偏函數(shù),也有其他方式實現(xiàn)。

當我們不想一次一次重復相同的參數(shù)時,偏函數(shù)是很便捷的。如我們有send(from,to)函數(shù),如果from總是相同的,可以使用偏函數(shù)簡化調(diào)用。

柯里化是轉換函數(shù)調(diào)用從f(a,b,c)f(a)(b)(c).Javascript通常既實現(xiàn)正常調(diào)用,也實現(xiàn)參數(shù)數(shù)量不足時的偏函數(shù)方式調(diào)用。

當我們想容易的偏函數(shù)時,柯里化非常好。如我們已經(jīng)看到的日志示例:通用的函數(shù)是log(date,importance,message),柯里化之后獲得偏函數(shù)為,一個參數(shù)如log(date),或兩個參數(shù)log(date,importance).

更多關于JavaScript相關內(nèi)容可查看本站專題:《JavaScript常用函數(shù)技巧匯總》、《javascript面向?qū)ο笕腴T教程》、《JavaScript錯誤與調(diào)試技巧總結》、《JavaScript數(shù)據(jù)結構與算法技巧總結》及《JavaScript數(shù)學運算用法總結

希望本文所述對大家JavaScript程序設計有所幫助。

相關文章

  • Js中parentNode,parentElement,childNodes,children之間的區(qū)別

    Js中parentNode,parentElement,childNodes,children之間的區(qū)別

    這篇文章主要是對Js中parentNode,parentElement,childNodes,children的區(qū)別進行了詳細的分析介紹,需要的朋友可以過來參考下,希望對大家有所幫助
    2013-11-11
  • 小程序拖動區(qū)域?qū)崿F(xiàn)排序效果

    小程序拖動區(qū)域?qū)崿F(xiàn)排序效果

    這篇文章主要為大家詳細介紹了小程序拖動區(qū)域?qū)崿F(xiàn)排序效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • JavaScript的Proxy對象詳解

    JavaScript的Proxy對象詳解

    這篇文章主要為大家介紹了JavaScript的Proxy對象,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-12-12
  • JavaScript點擊按鈕生成4位隨機驗證碼

    JavaScript點擊按鈕生成4位隨機驗證碼

    這篇文章主要為大家詳細介紹了JavaScript點擊按鈕生成4位隨機驗證碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-01-01
  • BootStrap前端框架使用方法詳解

    BootStrap前端框架使用方法詳解

    這篇文章主要介紹了BootStrap前端框架使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-02-02
  • Taro小程序自定義頂部導航欄功能的實現(xiàn)

    Taro小程序自定義頂部導航欄功能的實現(xiàn)

    這篇文章主要介紹了Taro小程序自定義頂部導航欄功能的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • js限制input標簽中只能輸入中文

    js限制input標簽中只能輸入中文

    這篇文章主要介紹了js限制input標簽中只能輸入中文的的相關資料,需要的朋友可以參考下
    2015-06-06
  • JavaScript實現(xiàn)的一個日期格式化函數(shù)分享

    JavaScript實現(xiàn)的一個日期格式化函數(shù)分享

    這篇文章主要介紹了JavaScript實現(xiàn)的一個日期格式化函數(shù)分享,本文給出了實現(xiàn)代碼和使用例子,需要的朋友可以參考下
    2014-12-12
  • 最新評論

    吕梁市| 山东省| 泗洪县| 乐至县| 齐齐哈尔市| 壤塘县| 山西省| 鄂尔多斯市| 商南县| 文化| 泰来县| 大悟县| 忻城县| 江口县| 屯昌县| 南阳市| 诏安县| 且末县| 天柱县| 兰考县| 承德市| 大足县| 淮滨县| 东乌珠穆沁旗| 泌阳县| 河西区| 鹤峰县| 肥乡县| 利川市| 伊宁市| 黑龙江省| 西乌| 滨州市| 同心县| 崇明县| 新郑市| 万山特区| 朝阳县| 永善县| 石景山区| 黔江区|