一文帶你了解JavaScript函數(shù)柯里化
一、定義
柯里化(Currying)是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結果的新函數(shù)的技術。
通過一個簡單的例子解釋一下
function add(a, b) {
return a + b
}
add(1, 2); // 3將函數(shù)add轉(zhuǎn)化為柯里化函數(shù)_add:
function _add(a){
return function(b){
return a + b
}
}
_add(1)(2); // 3函數(shù)add和函數(shù)_add是等價的。
_add能夠處理add的所有剩余參數(shù),因此柯里化也被稱為部分求值。
實際上就是把add函數(shù)的a,b兩個參數(shù)變成了先用一個函數(shù)接收a然后返回一個函數(shù)去處理b參數(shù)。
現(xiàn)在思路應該就比較清晰了:只傳遞給函數(shù)一部分參數(shù)來調(diào)用,讓它返回一個函數(shù)去處理剩下的參數(shù)。
二、柯里化函數(shù)的作用
1、參數(shù)復用
案例:拼接地址
按照普通思路去拼接一個地址
// 拼接地址
function getUrl(protocol, hostname, pathname) {
return `${protocol}${hostname}${pathname}`;
}
const url1 = getUrl('https://', 'www.baidu.com', '/hasa');
const url2 = getUrl('https://', 'www.baidu.com', '/saandsa');
const url3 = getUrl('https://', 'www.baidu.com', '/hasak');
console.log(url1, url2, url3)每次調(diào)用getUrl參數(shù)的時候都要重復的傳入?yún)?shù)'https://', 'www.baidu.com'。
柯里化封裝之后:
function curry(protocol) {
return function (hostname, pathname) {
return `${protocol}${hostname}${pathname}`;
}
}
const url_curry = curry('https://');
const url1 = url_curry('www.baidu.com', '/hasa');
const url2 = url_curry('www.baidu.com', '/saandsa');
const url3 = url_curry('www.baidu.com', '/hasak');
console.log(url1, url2, url3)很明顯,經(jīng)過柯里化封裝之后,之后再進行地址拼接的時候,減少了參數(shù)個數(shù),降低了代碼重復率。
2、提前確認
案例:兼容IE瀏覽器事件的監(jiān)聽方法(IE is dead)
傳統(tǒng)的方法:
/*
* @param element Object DOM元素對象
* @param type String 事件類型
* @param listener Function 事件處理函數(shù)
* @param useCapture Boolean 是否捕獲
*/
var addEvent = function (element, type, listener, useCapture) {
if (window.addEventListener) {
element.addEventListener(type, function (e) {
listener.call(element, e)
}, useCapture)
} else {
element.attachEvent('on' + type, function (e) {
listener.call(element, e)
})
}
}缺陷就是,每次對DOM元素進行事件綁定時都需要重新進行判斷,其實對于事件監(jiān)聽網(wǎng)頁一發(fā)布瀏覽器已經(jīng)確定了,就可以知曉瀏覽器到底是需要哪一種監(jiān)聽方式。所以我們可以讓判斷只執(zhí)行一次。
柯里化封裝之后:
var curEvent = (function () {
if (window.addEventListener) {
return function (element, type, listener, useCapture) { // return funtion
element.addEventListener(type, function () {
listener.call(element)
}, useCapture)
}
} else {
return function (element, type, listener) {
element.attachEvent('on' + type, function () {
listener.call(element)
})
}
}
})
var addEvent = curEvent();
addEvent(element, "click", listener)立即執(zhí)行函數(shù),在觸發(fā)多次事件也依舊只會觸發(fā)一次if條件判斷。
3、延遲執(zhí)行
案例:釣魚統(tǒng)計重量
傳統(tǒng)的方法:
let fishWeight = 0;
const addWeight = function(weight) {
fishWeight += weight;
};
addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
console.log(fishWeight);每次執(zhí)行addWeight方法時,都做了一次魚的體重的加和。
柯里化封裝后:
function curryWeight(fn) {
let _fishWeight = [];
return function () {
if (arguments.length === 0) {
return fn.apply(null, _fishWeight);
} else {
_fishWeight = _fishWeight.concat([...arguments]);
}
}
}
function addWeight() {
let fishWeight = 0;
for (let i = 0, len = arguments.length; i < len; i++) {
fishWeight += arguments[i];
}
return fishWeight;
}
const _addWeight = curryWeight(addWeight);
_addWeight(6.5);
_addWeight(1.2);
_addWeight(2.3);
_addWeight(2.5);
console.log(_addWeight())在執(zhí)行_addWeight方法時,并沒有做魚的體重的加和,之后在最后一次執(zhí)行_addWeight()時,才做了加和。做到了延遲執(zhí)行addWeight方法的效果。
三、柯里化函數(shù)的實現(xiàn)
function curry() {
let args = [...arguments];
let inner = function () {
args.push(...arguments);
return inner;
}
// 核心內(nèi)容:隱式轉(zhuǎn)換,調(diào)用了內(nèi)部的toString
inner.toString = function () {
return args.reduce(function (pre, next) {
return pre + next;
})
}
return inner;
}
const result = curry(1)(2);
console.log(Number(result));四、柯里化總結
函數(shù)的柯里化,需要依賴參數(shù)以及遞歸,通過拆分參數(shù)的方式,來調(diào)用一個多參數(shù)的函數(shù)方法,以達到減少代碼冗余,增加可讀性的目的。
性能方面:
- 存取arguments對象通常要比存取命名參數(shù)要慢一點;
- 一些老版本的瀏覽器在arguments.length的實現(xiàn)上是相當慢的;
- 使用fn.apply( … ) 和 fn.call( … )通常比直接調(diào)用fn( … ) 稍微慢點;
- 創(chuàng)建大量嵌套作用域和閉包函數(shù)會帶來花銷,無論是在內(nèi)存還是速度上。
應用場景:
- 減少重復傳遞不變的部分參數(shù);
- 將柯里化后的callback參數(shù)傳遞給其他函數(shù)。
到此這篇關于一文帶你了解JavaScript函數(shù)柯里化的文章就介紹到這了,更多相關JavaScript函數(shù)柯里化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
JavaScript算法系列之快速排序(Quicksort)算法實例詳解
這篇文章主要介紹了JavaScript算法系列之快速排序(Quicksort)算法實例詳解的相關資料,需要的朋友可以參考下2016-09-09
javascript實現(xiàn)原生ajax的幾種方法介紹
項目中不需要加載jquery這種龐大的js插件要使用到ajax這種功能該如何辦呢?下面和大家分享幾種利用javascript實現(xiàn)原生ajax的方法2013-09-09

