zoukankan      html  css  js  c++  java
  • JS高阶编程技巧--柯理化函数

    首先看一段代码:

    let obj = {
        x: 100
    };
    
    function fn(y) {
        this.x += y;
        console.log(this);
    }

    现在有一个需求:在1秒后,执行函数fn,并让其this指向obj。

    如果写成

    setTimeout(fn, 1000);

    这么写的话,fn函数中的this是指向window的,而且也没有传递参数。

    如果写成

    setTimeout(fn(200), 1000);

    这么写的话,this指向依然是window,而且相当于立即执行fn函数,并把结果赋给定时器1秒后再执行,这样肯定不行。

    如果写成

    setTimeout(fn.call(obj,200), 1000);

    这么写的话,用call或apply虽然改变了this指向,但都是函数立即执行并把返回结果赋给了定时器,依然无法完成需求。

    如果写成

    setTimeout(function() {
        fn.call(obj, 200);
    }, 1000);

    这么写的话,用一个匿名函数包起来,等到1秒后执行匿名函数里边的代码,这样便可以完成上述需求。

    从中我们可以看出,在某一个阶段之后执行某些代码,我们需要预先把this指向、参数等预先准备好,这种预先处理的思想即柯理化思想。

    即,柯理化函数的思想:利用闭包的机制,把一些内容事先存储和处理了,等到后期需要的时候拿来用即可。
     

    当然,这个需求如果用bind写的话,也能实现
    setTimeout(fn.bind(obj,200), 1000);
    因为bind不会立即执行函数,而且可以预先存储一些内容,和柯理化函数的思想相似,但问题是bind不兼容IE8及以下,那么为了通用,我们可以自己封装一个bind方法,从而实现这种需求。
     
    /*
    * bind:预先处理内容
    *   @params
    *     func:要执行的函数
    *      context:需要改变的this指向
    *      args:给函数传递的参数
    *   @return
    *         返回一个代理函数
    */
     function bind(func, context, ...args) {
        return function proxy() {
            func.call(context, ...args); //call和apply兼容低版本IE
        };
     }

    完成最开始的需求

    setTimeout(bind(fn, obj, 200), 1000);

    理解了这种思想,有助于我们更好的阅读别人的代码,如redux源码中applyMiddleware.js、combineReducers.js等很多都用到了这种方式或思想,以后更有助于我们自己写一些插件、组件等。

     
     
  • 相关阅读:
    ORA-30567: name already used by an existing
    vue router 需要go(-2)才能返回前一页
    MVC理解
    细说业务逻辑(后篇)
    细说业务逻辑(前篇)
    Python学习笔记-风变编程
    Python3 基础语法最常⻅报错类型&示意
    删除我的电脑/此电脑里的多余图标(坚果云、百度网盘、腾讯XX、WPS)
    vue 父组件传递方法 :和@的区别
    最全 Neo4j 可视化图形数据库的工具!
  • 原文地址:https://www.cnblogs.com/ronaldo9ph/p/12303333.html
Copyright © 2011-2022 走看看