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

一文帶你了解JavaScript函數(shù)柯里化

 更新時間:2023年02月01日 09:36:44   作者:起風(fēng)了  
柯里化(Currying)是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(shù)的技術(shù)。本文將通過一些示例帶大家深入了解JS的函數(shù)柯里化,需要的可以參考一下

一、定義

柯里化(Currying)是把接受多個參數(shù)的函數(shù)變換成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù)且返回結(jié)果的新函數(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ù),因此柯里化也被稱為部分求值。

實(shí)際上就是把add函數(shù)的a,b兩個參數(shù)變成了先用一個函數(shù)接收a然后返回一個函數(shù)去處理b參數(shù)。

現(xiàn)在思路應(yīng)該就比較清晰了:只傳遞給函數(shù)一部分參數(shù)來調(diào)用,讓它返回一個函數(shù)去處理剩下的參數(shù)。

二、柯里化函數(shù)的作用

1、參數(shù)復(fù)用

案例:拼接地址

按照普通思路去拼接一個地址

// 拼接地址
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ù)的時候都要重復(fù)的傳入?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)過柯里化封裝之后,之后再進(jìn)行地址拼接的時候,減少了參數(shù)個數(shù),降低了代碼重復(fù)率。

2、提前確認(rèn)

案例:兼容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元素進(jìn)行事件綁定時都需要重新進(jìn)行判斷,其實(shí)對于事件監(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ù)的實(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));

四、柯里化總結(jié)

函數(shù)的柯里化,需要依賴參數(shù)以及遞歸,通過拆分參數(shù)的方式,來調(diào)用一個多參數(shù)的函數(shù)方法,以達(dá)到減少代碼冗余,增加可讀性的目的。

性能方面:

  • 存取arguments對象通常要比存取命名參數(shù)要慢一點(diǎn);
  • 一些老版本的瀏覽器在arguments.length的實(shí)現(xiàn)上是相當(dāng)慢的;
  • 使用fn.apply( … ) 和 fn.call( … )通常比直接調(diào)用fn( … ) 稍微慢點(diǎn);
  • 創(chuàng)建大量嵌套作用域和閉包函數(shù)會帶來花銷,無論是在內(nèi)存還是速度上。

應(yīng)用場景:

  • 減少重復(fù)傳遞不變的部分參數(shù);
  • 將柯里化后的callback參數(shù)傳遞給其他函數(shù)。

到此這篇關(guān)于一文帶你了解JavaScript函數(shù)柯里化的文章就介紹到這了,更多相關(guān)JavaScript函數(shù)柯里化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論