掘金处女作-柯里化

JS函数柯里化

提前接收部分参数,延迟执行,不立即输出结果,而是返回一个接受剩余参数的函数

EXAMPLE 01


"use strict";

/**
 * 
 * EXAMPLE 0-1
 */
;(() => {

    function add_currying() {
        console.log(arguments, this);
    }

    function currying(fn) {

        let cache = []

        let next = function () {
            if (arguments.length > 0) {
                let args = [].slice.call(arguments, 0)
                cache = cache.concat(args)
                return next
            } else {
                return fn.apply(this, cache) // 看到结果后,明白这里的this是没有用的,可以传null
            }
        }

        next.empty = function () {
            let res = fn.apply(this, cache)
            cache = []
            return res
        }

        return next
    }

    var add = currying(add_currying)

    add(1)(2)(3, 4).empty() 
	//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4 } { [Function: next] empty: [Function] }
    add(2)(5)(7)()
	//[Arguments] { '0': 2, '1': 5, '2': 7 } undefined

})()

复制代码

EXAMPLE 02


/**
 * 
 * EXAMPLE 0-2
 */

;( () => {

    function add_currying () {
        console.log(arguments,this);// [Arguments] { '0': 1, '1': 1, '2': 34, '3': 5 } null
        return 1
    }

    function currying(fn){
        let cache = []
        let next = function(){
            cache = [...cache,...arguments]
            return next
        }
        next.toString = next.valueOf = () => fn.apply(null,cache)
        return next
    }

    var add = currying(add_currying)

    console.log(add(1)(1,34,5) + 1); //2
	
})()

复制代码

反柯里化


   Function.prototype.unCurrying = function(){
        let self = this
        return function(){
            return Function.prototype.call.apply(self,arguments)
        }
    }

    var show = Object.prototype.toString.unCurrying()

    console.log(show('23'));

复制代码

如何理解 Function.prototype.call.apply


var show = Object.prototype.toString.unCurrying() // ==>

   Function.prototype.unCurrying = function(){
        let self = this // this ==> Object.prototype.toString
        return function(){
            return Function.prototype.call.apply(self,arguments)
			// ==> Object.prototype.toString.call(arguments)
			// 这里call的this指向被apply方法转变为Object.prototype.toString
			// 同时执行 toString 并且将toString的this指向转变为 arguments[0] 
			// 最终执行的是 arguments[0].toString
        }
    }

	// 该方式本质上就是将原来必须由对象去点方法的形式改为,方法接受对象作为参数

复制代码

其实这与下面的方法没什么不同


    var unCurrying = function(fn){
        return function(){
            return fn.apply(arguments[0],[].slice.call(arguments,1))
        }
    }
    
    var show2 = unCurrying(Object.prototype.toString)

    console.log(show2('23'));
    
复制代码

写了一通,发现反柯里化好像没什么道理(小声BB),不能让大佬发现我的无知。

柯里化应用


/**
 * 柯里化应用
 * @descript 缓存计算值,重复计算(需要目标值)
 */

;
(() => {

    function currying(v, fn) {

        let cache = v

        let next = function () {
            if (arguments.length > 0) {
                let args = [].slice.call(arguments, 0)
                cache = fn.call(this, cache, ...arguments)
                return next
            } else {
                let res = cache
                cache = v
                return res
            }
        }

        next.empty = function () {
            let res = cache
            cache = v
            return res
        }
        return next
    }

    function ab_currying(a, b) {
        return a + b
    }

    var ab = currying(0, ab_currying)

    console.log(ab(1)(2)(3)()); //6
    console.log(ab(4,5)(9)()); // 13
    
})()

复制代码

/**
 * 给定目标值,分别计算
 */
;
(() => {


    Function.prototype.currying = function () {
        let fn = this,
            args = arguments

        return function () {
            return fn.apply(this, [...args, ...arguments])
        }
    }

    function ab(a, b) {
        return a + b
    }

    let test = ab.currying(1)

    console.log(test(2)); // 3

    console.log(test(3)); // 4

})()

复制代码

/**
 * 简化参数
 * @descript 当函数参数中有多个同样的参数
 */
;
(() => {


    Function.prototype.currying = function () {
        let fn = this,
            args = arguments

        return function () {
            let index = 0,
                len = arguments.length,
                new_args = [...args]
            for (let i = 0, args_len = args.length; i < args_len && len < args_len; i++) {
                if (args[i] === undefined) {
                    new_args[i] = arguments[index++]
                }
            }
            return fn.apply(this, new_args)
        }
    }

    function test_currying(a, b, c) {
        console.log(a, b, c);
    }

    let test = test_currying.currying(1, undefined, 2)

    test(10) // 1 10 2

    test(100) // 1 100 2

    /* 
    
    let bindClick = document.body.addEventListner.currying('click',undefined,false)
    
    bindClick(function(){
        console.log(1)
    })

    bindClick(function(){
        console.log(2)
    })

    */


})()

复制代码

转载于:https://juejin.im/post/5d08989151882546dd101008

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值