函數柯里化(面試題)包懂,不懂我改。

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:我在想,怎麼把上面整篇文字寫成一個故事。哈哈
標題說了大話,但我應該能夠堅持一下

相關文章
相關標籤/搜索