lodash里的after、before、once、negate

414 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

前言

在lodash中,after、before、once、negate方法被归类为函数类,主要是对函数类型的数据进行拓展。

after

after方法可以创建一个函数,当他被调用第一个参数n或更多次之后将马上触发第二个参数func 函数 。

使用如下:

var saves = ['profile', 'settings'];
 
var done = _.after(saves.length, function() {
  console.log('done saving!');
});
 
done()
done()
// => done方法在两次调用之后,后续调用会一直输出'done saving!'

after方法的实现主要借助toInteger方法,将数据转化为整数类型,利用闭包特性,当值达到某个零界点时停止执行,绑定this用到了apply方法。

源码如下:

import toInteger from './toInteger.js';

var FUNC_ERROR_TEXT = 'Expected a function';

function after(n, func) {
  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  n = toInteger(n);
  return function() {
    if (--n < 1) {
      return func.apply(this, arguments);
    }
  };
}

before

before方法可以创建一个函数,该函数接收两个参数,其中第一个参数n 代表调用次数,第二个参数是供内部调用的函数func,通过this绑定和创建函数的参数调用func,调用次数不超过 n 次。 之后再调用这个函数,将返回一次最后调用func的结果。

使用如下:

fn = _.before(3, ()=>{console.log('run');return Math.random()})

fn()
// => 输出run,返回0.9970988584136162

fn()
// => 输出run,返回0.6064649946039051

fn()
// => 输出run,返回0.6064649946039051

fn()
// => 输出run,返回0.6064649946039051

同样的,before在实现上也借助了toInteger方法将数据转化为整数类型,利用闭包特性,对次数进行判断。

源码如下:

import toInteger from './toInteger.js';

var FUNC_ERROR_TEXT = 'Expected a function';

function before(n, func) {
  var result;
  if (typeof func != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  n = toInteger(n);
  return function() {
    if (--n > 0) {
      result = func.apply(this, arguments);
    }
    if (n <= 1) {
      func = undefined;
    }
    return result;
  };
}

once

once方法表示创建一个只能调用 func (参数)一次的函数。 重复调用返回第一次调用的结果。 func 调用时, this 绑定到创建的函数,并传入对应参数。

使用如下:

var initialize = _.once(createApplication);

initialize();
initialize();
// => `initialize` 只能调用 `createApplication` 一次。

once方法实现上只需要调用before方法,对第一个参数传入2即可。

源码如下:

import before from './before.js';

function once(func) {
  return before(2, func);
}

negate

negate方法可以创建一个针对断言函数 func 结果取反的函数。 func 断言函数被调用的时候,this 绑定到创建的函数,并传入对应参数。

使用如下:

var array = [1, 2, 3, 4, 5, 6]

array.filter(_.negate((item) => item % 2 === 0))

// => [1, 3, 5]

negate方法的实现借助!操作法取反操作,通过switch将参数限制在3个。

源码如下:

var FUNC_ERROR_TEXT = 'Expected a function';

function negate(predicate) {
  if (typeof predicate != 'function') {
    throw new TypeError(FUNC_ERROR_TEXT);
  }
  return function() {
    var args = arguments;
    switch (args.length) {
      case 0: return !predicate.call(this);
      case 1: return !predicate.call(this, args[0]);
      case 2: return !predicate.call(this, args[0], args[1]);
      case 3: return !predicate.call(this, args[0], args[1], args[2]);
    }
    return !predicate.apply(this, args);
  };
}

小结

本篇章我们了解到了after、before、once、negate方法的使用以及代码实现,实现上基本上是借助闭包特性以及call或apply绑定this指向。