掘金處女做-柯里化

JS函數柯里化

提早接收部分參數,延遲執行,不當即輸出結果,而是返回一個接受剩餘參數的函數緩存

EXAMPLE 01app

 "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
        }
    }

	// 該方式本質上就是將原來必須由對象去點方法的形式改成,方法接受對象做爲參數

複製代碼

其實這與下面的方法沒什麼不一樣ui

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),不能讓大佬發現個人無知。this

柯里化應用

/** * 柯里化應用 * @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) }) */


})()

複製代碼
相關文章
相關標籤/搜索