bind函数:

  1. const $ = document.querySelector;
  2. const div = $('div');
  3. //Uncaught TypeError: Illegal invocation
  4. // at <anonymous>:1:1
  5. // querySelector 这个方法是document对象下的方法,window对象下并没有这个方法
  6. //解决办法:
  7. const $ = document.querySelector.bind(document);
  8. const div = $('div');
  9. // 返回结果 <div>......</div>
  • bind函数可以多次bind调用,其中的this总是指向第一个绑定的对象
  1. const sayName = function () {
  2. console.log(this.name);
  3. }
  4. const p1 = {
  5. name:'vidy'
  6. }
  7. const p2= {
  8. name: 'lily'
  9. }
  10. const say = sayName.bind(p1).bind(p2);
  11. say(); // vidy
  • ES6的箭头函数里的this是指向外层函数的this的,不可改变,所以bind对箭头函数是无效的
  • polyfill实现
  1. if (!Function.prototype.bind) {
  2. Function.prototype.bind = function(oThis) {
  3. if (typeof this !== 'function') {
  4. // closest thing possible to the ECMAScript 5
  5. // internal IsCallable function
  6. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
  7. }
  8. var aArgs = Array.prototype.slice.call(arguments, 1),
  9. fToBind = this,
  10. fNOP = function() {},
  11. fBound = function() {
  12. // this instanceof fNOP === true时,说明返回的fBound被当做new的构造函数调用
  13. return fToBind.apply(this instanceof fNOP
  14. ? this
  15. : oThis,
  16. // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
  17. aArgs.concat(Array.prototype.slice.call(arguments)));
  18. };
  19. // 维护原型关系
  20. if (this.prototype) {
  21. // Function.prototype doesn't have a prototype property
  22. fNOP.prototype = this.prototype;
  23. }
  24. // 下行的代码使fBound.prototype是fNOP的实例,因此
  25. // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
  26. fBound.prototype = new fNOP();
  27. return fBound;
  28. };
  29. }
  • 偏函数

bind() 的另一个最简单的用法是使一个函数拥有预设的初始参数。这些参数(如果有的话)作为bind()的第二个参数跟在this(或其他对象)后面,之后它们会被插入到目标函数的参数列表的开始位置传递给绑定函数的参数会跟在它们的后面。

简单的理解就是:偏函数会返回一个新函数,这个函数有预设的参数

  1. function list() {
  2. return Array.prototype.slice.call(arguments);
  3. }
  4. var list1 = list(1, 2, 3); // [1, 2, 3]
  5. // Create a function with a preset leading argument
  6. var leadingThirtysevenList = list.bind(undefined, 37);
  7. var list2 = leadingThirtysevenList(); // [37]
  8. var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

柯里化:

又称为部分求值,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回一个新的函数的技术,新函数接受余下参数并返回运算结果。

柯里化可以用来解决我们平时开发过程中具有共同主题的,或者说处理某一类,具有共同特性的,能起到代码复用。

比如:表单验证,我们可能需要验证手机,邮箱等等;

一般做法是:

  1. function checkPhone(phoneNumber) {
  2. return /^1[34578]\d{9}$/.test(phoneNumber);
  3. }
  1. function checkEmail(email) {
  2. return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(email);
  3. }

封装一个通用函数:

  1. // 将正则,要验证的字符串作为参数传入
  2. function check(targetString, reg) {
  3. return reg.test(targetString);
  4. }
  5. check(/^1[34578]\d{9}$/, '14900000088');
  6. check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@163.com');

柯里化封装:

  1. var _check = createCurry(check);
  2. var checkPhone = _check(/^1[34578]\d{9}$/);
  3. var checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
  4. //使用的时候就更简洁
  5. checkPhone('1806467897');
  6. checkEmail('xxx@qq.com');
  • 柯里化通用式:
  1. function curry(fn, ...rest) {
  2. return function(...arg) {
  3. var args = [...rest, ...arg]
  4. if (args.length >= fn.length) {
  5. return fn.apply(null, args)
  6. } else {
  7. return curry.call(null, fn, ...args)
  8. }
  9. }
  10. }

偏函数与柯里化区别:

柯里化是将一个多参数函数转换成多个单参数函数,也就是将一个 n 元函数转换成 n 个一元函数。

偏函数则是固定一个函数的一个或者多个参数,也就是将一个 n 元函数转换成一个 n - x 元函数。

js偏函数与柯里化函数:https://blog.csdn.net/neweastsun/article/details/75947785

Javascript bind的应用场景及实现思路:https://bonevidy.github.io/posts/2018/09/13/javascript-bind/

MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

深入高阶函数应用之柯里化