手写call bind 函数 以及柯里化,纯函数概念

128 阅读2分钟

手写 call函数

封装:给所有函数的原型都添加上一个hycall方法
Function.prtotype.hycall=function(thisArg,...args){
    这个this是隐式调用 指向的是谁调用了hycall方法
    let funFoo=this
    防止传入的非对象的类型时转换成对象类型
    thisArg=thisArg?Object(thisArg):window
    传入绑定this
    thisArg.funFoo=funFoo
    调用这个函数 如果有结果返回结果
    
    let result = thisArg.funFoo(...args)
    return result 
}


function foo(num1,num2){
  console.log('foo',this)
   console.log(num1,num2)
}

foo.hycall({name:'foo'},10,20,30)

手写bind方法

Function.prototype.hybind = function (thisArg, ...args) {
    var funFoo = this
    function proxyFun(...arrgs) {
        thisArg = thisArg ? Object(thisArg) : window
        thisArg.funFoo = funFoo
        var finalArgs = [...arrgs, ...args]
        var result = thisArg.funFoo(...finalArgs)
        return result
    }
    return proxyFun
}

arguments 方法中的参数类数组 他拥有数组特性 length 索引值 但是没有数组上面的方法 将数组变成array 1.自己通过for循环遍历追加数组

实现一个数组的slice

// arr.slice(1,3)
// Array.prototype.slice = function (start, end) {
  
//     console.log(this)
//     var arr = this
//     start=start||0
//     end=end||arr.length
//     var newArray = []
//     for (var i = start; i < end; i++) {
//         newArray.push(arr[i])
//     }
//     return newArray
// }

// // 2.1
// var arrArguments=Array.prototype.slice.call(arguments)
// // 2.2
// var arrArguments=[].slice.call(arguments)
// // 2.3
// var arrArguments=Array.from(arguments)
// // 2.4
// var arrArguments=[...arguments] 

如果在箭头函数中 arguments本身是没有的 需要从上层作用域找 在js中全局没有arguments 在node中是有arguments 因为在node是通过模块包裹一个函数 执行了一个call方法

柯里化

纯函数

  1. react中组件被要求像是一个纯函数(因为还有class组件redux中也有一个reducer的概念 也要求是一个纯函数(Pure Function) 概念
  2. 此函数在相同的输入值时,需产生相同的输出(在任何情况下给这个函数传入相同的参数 返回都是相同的return)
  3. 函数的输出和输入意外的其他隐藏信息或状态无关 也和I/O设备产生的外部输出无关 (函数外部变量控制输出的点)
  4. 该函数不能有语义上可观察的函数副作用,eg:触发事件,使输出设备设备输出,改变输出值意外的内容 总结
  • 确定的输入一定会产生相对应的确定的输出
  • 函数在执行过程中 不能产生任何副作用 不能修改函数入参以及全局变量 副作用 在执行一个函数时,除了返回函数值以外,还对调用函数产生了附加的影响,eg:修改了全局变量 修改传入参数或者改变外部的存储(localStorange) slice 截取数组 并且不会修改原函数 没有产生副作用 是个纯函数 splice 截取函数 但是会修改原函数 所以不是个纯函数

纯函数的优势 可以安心的编写和安心的使用 只关心这个函数的参数和返回值就可以 你在写的时候保证了函数的纯度,只是单纯实现自己的业务逻辑即可,不需要关心传入的内容是如何获得的或 者依赖其他的外部变量是否已经发生了修改; 你在用的时候,你确定你的输入内容不会被任意篡改,并且自己确定的输入,一定会有确定的输出; React中就要求我们无论是函数还是class声明一个组件,这个组件都必须像纯函数一样,保护它们的props不被修改:

柯里化

把接受多个参数的函数 变成一个单一参数(最初函数的第一个函数)的函数 并且返回接受雨下的参数 返回结果的函数技术 只传递函数的一部分参数来调用它,让它返回一个函数出处理剩下的多余参数

function(m,n,y){
    console.log(m+n+y)
}
// 变成下面的代码的过程叫做柯里化
function foo(m){
    return function(n){
        return function(y){
            console.log(m+n+y)
        }
    }
}
// 简化柯里化代码 箭头函数
var sum =x => y => z =>{
    return x+y+z
}
var sum =x => y => z => x+y+z
foo(1)(2)(3)

在函数式编程中,我们其实往往希望一个函数处理的问题尽可能的单一,而不是将一大堆的处理过程交给一个 函数来处理; **那么我们是否就可以将每次传入的参数在单一的函数中进行处理,处理完后在下一个函数中再使用处理后的结果; **

// 封装一个柯里化代码 把普通函数转换成柯里化函数
function add(x, y, z) {
    console.log(x + y + z)
}
function hyCurring(fn) {
    return function (...args) {
        // 判断所需参数和当前参数是否一致  如果一致直接返回函数
        if (args.length >= fn.length) {
            return fn.call(this, ...args)
        } else {
            return function (...args2) {
                // 接受下一个参数 合并参数进行递归
                return hyCurring(fn).apply(this, [...args2, ...args])
            }
        }
    }
}
var hyCurring1 = hyCurring(add)
hyCurring1(19)(20)(2)

组装函数

比如我们现在需要对某一个数据进行函数的调用**,执行两个函数fn1和fn2**,这两个函数是依次执行的; 那么如果每次我们都需要进行两个函数的调用,操作上就会显得重复; 那么是否可以将这两个函数组合起来,自动依次调用呢? 这个过程就是对函数的组合,我们称之为 组合函数(Compose Function);

    return Number(n) + 2
}

function double(m) {
    return m * 2
}
function compose(...args) {
    var length = args.length
    for (var i = 0; i < length; i++) {
        if (typeof args[i] !== 'function') {
            throw new TypeError('请传入函数')
        }
    }
    return function (...args2) {
        var index = 0
        // 执行第一次调用函数的结果 
        var result = length ? args[index].call(this, args2) : args2
        console.log(result)
        while (++index < length) {
            result = args[index].call(this, result)
        }
        return result
    }
}


var resultFun = compose(add, double)
console.log(resultFun(2))