js函数柯里化

2021-02-02  本文已影响0人  攻城熊

柯里化: 一个函数原本有多个参数, 之传入一个参数, 生成一个新函数, 由新函数接收剩下的参数来运行得到结构.

   var add = function (x) {
        return function (y) {
            return x + y
        }
    }
    var increment = add(1)  // 参数x被封印在了返回的新函数中,值为1不变化
    var addTen = add(10)   // 参数x被封印在了返回的新函数中,值为10不变化
    increment(2) // 3
    addTen(10)  // 12
    add(10)(10) // 20
    increment(1)  // 2

为什么要使用科里化? 为了提升性能. 使用科里化可以缓存一部分能力.
高阶函数: 一个函数参数是一个函数, 该函数对参数这个函数进行加工, 得到一个函数, 这个加工用的函数就是高阶函数.
Array.prototype.map((item,index,arr)=>{}) //高级函数的参数为函数

柯里化函数原理其实是 闭包,
函数即能力, 将某些能力作为新能力的基础能力
有点类似于层层递进的能力等级
柯里化函数返回的是函数, 是下一次操作的调用者

柯里化的对比

// 存在硬编码问题的函数
function checkAge (age) {
    const min = 18
    return age >= min
}
console.log(checkAge(20))

// 使用普通纯函数解决方案
function checkage (min, age) {
    return age >= min
}
console.log(checkAge(18, 20))

// 使用闭包配合柯里化解决方案
function checkAge (min) {
    return function (age) {
        return age >= min
    }
}
const checkAge18 = checkAge(18)
console.log(checkAge18(20))

思考: 虚拟DOM的render方法
思考: Vue 项目模版转换为抽象语法树需要执行几次?
页面一开始加载需要渲染
每一个属性( 响应式 )数据在发生变化的时候需要渲染
watch,computed等等
之前的代码 每次需要渲染的时候,模版就会解析一次

reder 的作用是将虚拟DOM转换为真正DOM加到页面中
虚拟DOM可以降级理解为 AST
一个项目运行时候,模版是不会变的,就表示 AST 是不会变的

我们可以将代码进行优化,将虚拟DOM缓存起来,生成一个函数,函数只需要传入数据,就可以得到真正的DOM.

function ad(a) {
    return function(b) {
        return function(c) {
            return a + b + c;
            // ... 不限制层级如何处理?  
        }
    }
}
// 先理解一下toString()
function add (a) {
    function sum(b) { // 使用闭包
        a = a + b; // 累加
        return sum;
    }
    sum.toString = function() { // 重写toSting() 方法
        return a;
    }
    return sum; // 返回一个函数
}
 
console.log(add(1)(3)) // 4
console.log(add(1)(3)(5)) // 9
 
// 解决方式
function add() {
    // 第一次执行时,定义一个数组专门用来存储所有的参数
    var _args = [].slice.call(arguments);
    // 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
    var adder = function () {
        var _adder = function() {
            [].push.apply(_args, [].slice.call(arguments));
            return _adder;
        };
        //  利用隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
        //  打印函数时会自动调用 toString()方法
        _adder.toString = function () {
            return _args.reduce(function (a, b) {
                return a + b;
            });
        }
        return _adder;
    }
    return adder.apply(null, [].slice.call(arguments));
}
// 输出结果,可自由组合的参数
console.log(add(1, 2, 3, 4, 5));  // 15
console.log(add(1, 2, 3, 4)(5));  // 15

字符串正则判断的应用

function checkEmail(email) {
    return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(email);
}
function check(targetString, reg) {
    return reg.test(targetString);
}
check(/^1[34578]\d{9}$/, '14900000088');
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@163.com');

// 如何封装通用能力 ?

// 正常正则验证字符串 reg.test(txt)
// 函数封装后
function check(reg, txt) {
    return reg.test(txt)
}

check(/\d+/g, 'test')       //false
check(/[a-z]+/g, 'test')    //true

// Currying后
function curryingCheck(reg) {
    return function(txt) {
        return reg.test(txt)
    }
}
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)

柯里化可以让我们给一个函数传递较少的参数,得到一个已经记住了某些固定参数的新函数,者就是柯里化的核心。在柯里化内部就是使用闭包,对函数的参数进行缓存。柯里化让函数变得更灵活,因为我们可以通过一个函数生成一些细粒度更小的函数。这么做的目的是为了在后续函数组合的时候在使用。柯里化可以把多元函数转换成一元函数,目的是可以组合使用函数产生强大的功能。

lodash_curry函数柯里化的实现? 有兴趣的可以查看lodash源码,这里就不讲了哈.

上一篇下一篇

猜你喜欢

热点阅读