zoukankan      html  css  js  c++  java
  • 手写系列:call、apply、bind、函数柯里化

    少废话,show my code

    call

    原理都在注释里了

    // 不覆盖原生call方法,起个别名叫myCall,接收this上下文context和参数params
    Function.prototype.myCall = function (context, ...params) {
      // context必须是个对象并且不能为null,默认为window
      const _this = typeof context === "object" ? context || window : window;
      // 为了避免和原有属性冲突,定义一个Symbol类型的属性
      const key = Symbol();
      // call方法的目的是改变函数的this指向,函数的this指向它的调用者,也就是说我们的目标是改变函数的调用者。
      // 下面的this就是函数本身,给_this增加一个名为[key]的方法指向this,就能用_this来调用this了
      _this[key] = this;
      const result = _this[key](...params);
      // 获取函数执行结果后,删除以上添加的属性
      delete _this[key];
      return result;
    };
    

    apply

    和call的区别在于第二个参数

    Function.prototype.myApply = function (context, params) {
      return this.myCall(context, ...params);
    };
    

    bind

    和call的区别在于不立即执行,返回一个函数即可

    Function.prototype.myBind = function (context, ...params) {
      const _this = this;
      // 返回的函数也能接收参数,但是是放在params后面
      return function (...args) {
        return _this.myCall(context, ...[...params, ...args]);
      };
    };
    

    函数柯里化

    函数柯里化,举例,有如下函数

    function test(a, b, c, d, e) {
      console.log(a + b + c + d + e);
    }
    

    有一个curry转换函数对test函数进行一些转换

    function curry(){
      // todo
    }
    const transformTest = curry(test, ...args)
    

    转换之后,原本一次性传过去的参数现在可以分步传参

    // 使得
    test(1,2,3,4,5)
    // 等同于
    transformTest(1)(2)(3)(4)(5)
    // 或者
    transformTest(1, 2)(3)(4, 5)
    // 又或者
    transformTest(1, 2, 3, 4)(5)
    

    curry函数应该怎么写?

    function curry(fn, ...args) {
      // 判断参数个数是不是等于原函数参数个数
      // 如果是,直接返回调用结果
      if ([...args].length >= fn.length) {
        return fn(...args);
      } else {
        // 如果不是,则返回一个函数
        return (...params) => {
          // 将前面传的全部参数传给curry,回到第一步的if判断,直到参数个数满足要求
          return curry(fn, ...args, ...params);
        };
      }
    }
    

    本文GitHub链接:手写系列:call、apply、bind、函数柯里化

  • 相关阅读:
    U8 UAP 存储过程未提供该参数
    SQL exec 报错 找不到存储过程 'select * from TEMP_byhktb20191213104416697'
    U8修改存货扩展自定义项
    插入临时表时报在将 nvarchar 值 'config_category.metadata_item.popedom' 转换成数据类型 int 时失败
    拼接字符串发生的错误
    js 三种提取部分字符串的方法的 区别: slice(start, end) substring(start, end) substr(start, length)
    sqlserver 保留位数
    1月转01月
    焦点图插件-06
    通栏自适应通栏焦点图-05
  • 原文地址:https://www.cnblogs.com/wangmeijian/p/14219155.html
Copyright © 2011-2022 走看看