函数柯里化(面试题)包懂,不懂我改。

ps:本篇中所假设的场景及后续的代码是借鉴别人的。可是注释及思路是本身组织的语言。我会抽空本身假设一个场景并写出新的业务代码。今天多是不成的,在加班中。(2020/6/1 18:48)前端

(柯里化函数是高阶函数的一种特殊应用。对的,在我看来:要明白函数柯里化,前置知识点只有“高阶函数”。高级函数对于我们每一个前端程序员来讲,常常用,不难。只不过咱们(基础不牢的初级程序员)对于高级函数的定义不是十分明确。因此本片文章分为两个部分:一、高级函数。二、“特殊应用”高级函数。)程序员

1、什么是高阶函数?

  1. 若是一个函数的参数是一个函数 (回调函数就是一种高阶函数)bash

  2. 若是一个函数返回(return)一个函数 当前这个函数也是一个高阶函数函数

    典型例子:(既有回调函数,也有把函数看成参数返回ui

    // 写了一个业务代码,扩展当前的业务代码
    function say(a,b){
        console.log('say',a,b);
    }
    // 给某个方法 添加一个方法并在他执行以前调用
    Function.prototype.before = function (callback) {
        return (...args)=>{ // 剩余运算符, 箭头函数没有this(向上找) 也没有arguments (return一个函数)
            callback();    //执行传过来的匿名函数
            this(...args); // 执行this。能够暂时理解谁调用的this就指向谁:say.before  say调用的因此say指向say-
        }
    }
    let beforeSay = say.before(function(){
        console.log('before say')
    })//将返回的函数赋值给beforeSay (参数函数)
    beforeSay('hello','world');
    复制代码

    运行结果:this

    before say
    say hello world
    复制代码

2、“特殊应用”高级函数(柯里化)

假设一个场景,作一个判断变量类型功能(咱们如何知道一个变量的类型呢)。经常使用的方法有四种(知识补充):spa

  1. typeof 不能判断对象类型 typeof [] typeof {} 缺陷是不能判断引用类型prototype

  2. constructor 能够找到这个变量是经过谁构造出来的code

  3. instanceof 判断谁是谁的实例 __proto__对象

  4. Object.prototype.toString.call() 缺陷就是不能细分是谁谁的实例

    咱们如今选择第四种方法来作判断数据类型这个功能,这个时候咱们能够想到的是:

    function isType(type,value) {
        return Object.prototype.toString.call(value) === `[object ${type}]`;
    }
    console.log(isType('Array',[]))
    复制代码

    运行结果:

    true
    复制代码

    挺完美的吧,简简单单一句就能够完成。的确,在这个场景中这的确就是最优解。可是在实际开发中呢,有很大多是须要处理大量不一样类型的变量,每一次调用都要咱们本身编写两个参数,尤为是Array这个字符串变量,有可能一个不当心写错,可是编译器却不会报错,而且很难找到错误在哪里。以下:

    console.log(isType([],'Arary');//Arary写错了
    复制代码

    运行结果:

    false //? ? 怎么就错了 ?
    复制代码

    因此这个时候咱们就想能不能作一件事情,就是将方法细分。细分红isArray isString(柯里化)。
    说人话就是:利用高级函数提早把其中一个变量写好。调用的时候只须要填写一个变量就好。

    function isType(type) {
       return function(value) {
           return Object.prototype.toString.call(value) === `[object ${type}]`;
       }
    }
    let isArray = isType('Array');//提早写好了Array  并把isType赋值给isArray
    //这个时候咱们就能够只传咱们想校验的变量就能够了,Array早已经写死。
    console.log(isArray('hello'));
    console.log(isArray([]));
    复制代码

    执行结果:

    false
    true
    复制代码

    以上就是最基础的函数柯里化,可是若是真的只有那么简单,怎么能够配得上柯里化这么一个高大上的名字呢?怎么能够应用的各类各样的复杂需求场景里呢?因此上面的函数能够须要升级,须要公式化,不一样的场景中均可以用一个通用的函数来套用。

    通用的函数柯里化(封装):对比上面的代码能够看懂。

    function isType(type,value) {
        return Object.prototype.toString.call(value) === `[object ${type}]`;
    }
    //通用  公式 能够套用
    //这里有一个地方我是没有弄明白的:”type = []“,在括号里面声明。
    const currying = (fn,type = []) => {
        let len = fn.length;//这里是函数实参的长度,说的不明白或者不许确,等找到好的说法再来改一下。
        return function(...args) {
            let concatValue = [...type,...args];
            if(concatValue.length < len) {
                return currying(fn,concatValue);
            } else {
                return fn(...concatValue);
            }
        }
    }
    
    let isArray = currying(isType)('Array');//执行currying,传形参isType,执行return回来的函数同时传形参‘Array’,并把最后返回出来的fn(是刚才传进去的isType)赋值给isArray。其中处理看代码
    let isString = currying(isType)('String');
    console.log(isArray([]))
    console.log(isArray('123'))
    console.log(isString([]));
    console.log(isString('123'));
    复制代码

    输出结果

    true
    false
    false
    true
    复制代码

ps:我在想,怎么把上面整篇文字写成一个故事。哈哈
标题说了大话,但我应该能够坚持一下

相关文章
相关标签/搜索