首先看一段代码:
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源码中很多都用到了这种方式或思想,以后更有助于我们自己写一些插件、组件等。
原文地址:https://www.cnblogs.com/ronaldo9ph/p/12303333.html
时间: 2024-12-13 22:18:47