Lodash 函数列表 · 函数
after
指定一个函数在被调用多少次后执行
const after = (n, func) => {
let count = 0;
return (...args) => {
count++;
if (count >= n) {
return func(...args);
}
};
};
const saves = ['profile', 'settings'];
const done = after(saves.length, () => {
console.log('done saving!');
});
forEach(saves, type => {
asyncSave({ type, complete: done });
});
// => Logs 'done saving!' after the two async saves have completed.
思路:返回一个函数,该函数在被调用 n 次后执行指定的函数。利用闭包记录当前已调用次数,判断是否达到执行条件。
ary:对指定函数进行封装,指定最多接收多少个参数
const ary =
(func, n = func.length) =>
(...args) =>
func(...args.slice(0, n));
map(['6', '8', '10'], ary(parseInt, 1));
// => [6, 8, 10]
思路:对指定函数进行封装,指定最多接收 n 个参数。返回一个新函数,限制函数参数个数。
before:指定一个函数在被调用多少次前执行
const before = (n, func) => {
let count = 0;
return (...args) => {
count++;
if (count < n) {
return func(...args);
}
};
};
jQuery(element).on('click', before(5, addContactToList));
// => Allows adding up to 4 contacts to the list.
思路:返回一个函数,该函数在被调用 n 次前执行指定的函数。利用闭包记录当前已调用次数,判断是否达到执行条件。
bind
绑定函数的 this 值和指定的参数,并返回一个新的函数
const bind =
(func, thisArg, ...boundArgs) =>
(...args) =>
func.apply(thisArg, [...boundArgs, ...args]);
const greet = function (greeting, punctuation) {
return `${greeting} ${this.user}${punctuation}`;
};
const object = { user: 'fred' };
var bound = bind(greet, object, 'hi');
bound('!');
// => 'hi fred!'
// Bound with placeholders.
var bound = bind(greet, object, _, '!');
bound('hi');
// => 'hi fred!'
思路:绑定函数的 this 值和指定的参数,并返回一个新的函数。利用 apply 和 bind 方法实现。
bindKey
与 bind 类似,但是绑定的是对象上的指定方法
const bindKey =
(object, key, ...args) =>
(...args2) =>
object[key].apply(object, [...args, ...args2]);
const object = {
user: 'fred',
greet(greeting, punctuation) {
return `${greeting} ${this.user}${punctuation}`;
},
};
var bound = bindKey(object, 'greet', 'hi');
bound('!');
// => 'hi fred!'
object.greet = function (greeting, punctuation) {
return `${greeting}ya ${this.user}${punctuation}`;
};
bound('!');
// => 'hiya fred!'
// Bound with placeholders.
var bound = bindKey(object, 'greet', _, '!');
bound('hi');
// => 'hiya fred!'
思路:与 bind 类似,但是绑定的是对象上的指定方法。利用 apply 和 bind 方法实现。
curry
对指定函数进行柯里化
const curry = (func, arity = func.length, ...args) =>
arity <= args.length ? func(...args) : curry.bind(null, func, arity, ...args);
const abc = function (a, b, c) {
return [a, b, c];
};
const curried = curry(abc);
curried(1)(2)(3);
// => [1, 2, 3]
curried(1, 2)(3);
// => [1, 2, 3]
curried(1, 2, 3);
// => [1, 2, 3]
// Curried with placeholders.
curried(1)(_, 3)(2);
// => [1, 2, 3]
思路:对指定函数进行柯里化。返回一个新函数,当参数数量不足时,继续返回一个新函数,直到参数数量足够执行原函数。
curryRight
与 curry 类似,但是从右到左处理参数
const curryRight = (func, arity = func.length, ...args) =>
arity <= args.length
? func(...args.reverse())
: curryRight.bind(null, func, arity, ...args);
const abc = function (a, b, c) {
return [a, b, c];
};
const curried = curryRight(abc);
curried(3)(2)(1);
// => [1, 2, 3]
curried(2, 3)(1);
// => [1, 2, 3]
curried(1, 2, 3);
// => [1, 2, 3]
// Curried with placeholders.
curried(3)(1, _)(2);
// => [1, 2, 3]
思路:与 curry 类似,但是从右到左处理参数。
debounce
对指定函数进行防抖处理
const debounce = (func, wait, immediate = false) => {
let timeoutId;
return (...args) => {
if (immediate && !timeoutId) {
func(...args);
}
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
if (!immediate) {
func(...args);
}
timeoutId = null;
}, wait);
};
};
// 避免窗口在变动时出现昂贵的计算开销。
jQuery(window).on('resize', debounce(calculateLayout, 150));
// 当点击时 `sendMail` 随后就被调用。
jQuery(element).on(
'click',
debounce(sendMail, 300, {
leading: true,
trailing: false,
})
);
// 确保 `batchLog` 调用1次之后,1秒内会被触发。
const debounced = debounce(batchLog, 250, { maxWait: 1000 });
const source = new EventSource('/stream');
jQuery(source).on('message', debounced);
// 取消一个 trailing 的防抖动调用
jQuery(window).on('popstate', debounced.cancel);
思路:对指定函数进行防抖处理。返回一个新函数,在一段时间内只执行一次。
defer
将指定函数延迟执行
const defer = (func, ...args) => setTimeout(func, 1, ...args);
defer(text => {
console.log(text);
}, 'deferred');
// => 一毫秒或更久一些输出 'deferred'。
思路:将指定函数延迟执行。利用 setTimeout 实现。
delay
将指定函数延迟一段时间后执行
const delay = (func, wait, ...args) => setTimeout(func, wait, ...args);
delay(
text => {
console.log(text);
},
1000,
'later'
);
// => 一秒后输出 'later'。
思路:将指定函数延迟一段时间后执行。利用 setTimeout 实现。
flip
对指定函数的参数进行反转
const flip =
fn =>
(...args) =>
fn(...args.reverse());
const flipped = flip(function () {
return toArray(arguments);
});
flipped('a', 'b', 'c', 'd');
// => ['d', 'c', 'b', 'a']
思路:反转函数的参数顺序,返回一个新的函数
memoize
对指定函数进行记忆化处理,缓存函数的计算结果
const memoize = fn => {
const cache = new Map();
return (...args) => {
const key = JSON.stringify(args);
return cache.has(key)
? cache.get(key)
: cache.set(key, fn(...args)).get(key);
};
};
const object = { a: 1, b: 2 };
const other = { c: 3, d: 4 };
var values = memoize(values);
values(object);
// => [1, 2]
values(other);
// => [3, 4]
object.a = 2;
values(object);
// => [1, 2]
// 修改结果缓存。
values.cache.set(object, ['a', 'b']);
values(object);
// => ['a', 'b']
// 替换 `memoize.Cache`。
memoize.Cache = WeakMap;
思路:缓存函数的计算结果,返回一个新的函数
negate
对指定函数进行封装,返回原函数的否定值
const negate =
fn =>
(...args) =>
!fn(...args);
function isEven(n) {
return n % 2 == 0;
}
filter([1, 2, 3, 4, 5, 6], negate(isEven));
// => [1, 3, 5]
思路:返回一个新的函数,该函数执行原函数的结果取反
once
指定一个函数只能被调用一次
const once = fn => {
let called = false;
return (...args) => {
if (!called) {
called = true;
return fn(...args);
}
};
};
const initialize = once(createApplication);
initialize();
initialize();
// `initialize` 只能调用 `createApplication` 一次。
思路:返回一个新的函数,该函数只能被调用一次
overArgs
对指定函数进行封装,转换参数的形式
const overArgs =
(fn, transforms) =>
(...args) =>
fn(...args.map((arg, index) => transforms[index](arg)));
function doubled(n) {
return n * 2;
}
function square(n) {
return n * n;
}
const func = overArgs((x, y) => [x, y], [square, doubled]);
func(9, 3);
// => [81, 6]
func(10, 5);
// => [100, 10]
思路:返回一个新的函数,该函数对原函数的指定参数进行转换
partial
对指定函数进行部分应用,指定部分参数
const partial =
(fn, ...args) =>
(...newArgs) =>
fn(...args, ...newArgs);
const greet = function (greeting, name) {
return `${greeting} ${name}`;
};
const sayHelloTo = partial(greet, 'hello');
sayHelloTo('fred');
// => 'hello fred'
// 使用了占位符。
const greetFred = partial(greet, _, 'fred');
greetFred('hi');
// => 'hi fred'
思路:返回一个新的函数,该函数部分应用原函数的指定参数
partialRight
与 partial 类似,但是从右到左指定部分参数
const partialRight =
(fn, ...args) =>
(...newArgs) =>
fn(...newArgs, ...args);
const greet = function (greeting, name) {
return `${greeting} ${name}`;
};
const greetFred = partialRight(greet, 'fred');
greetFred('hi');
// => 'hi fred'
// 使用了占位符。
const sayHelloTo = partialRight(greet, 'hello', _);
sayHelloTo('fred');
// => 'hello fred'
思路:返回一个新的函数,该函数从右到左部分应用原函数的指定参数
rearg
对指定函数进行封装,调整参数的位置
const rearg =
(fn, indexes) =>
(...args) =>
fn(...indexes.map(index => args[index]));
const rearged = rearg((a, b, c) => [a, b, c], [2, 0, 1]);
rearged('b', 'c', 'a');
// => ['a', 'b', 'c']
思路:返回一个新的函数,该函数调整原函数的参数顺序
rest
对指定函数进行封装,将参数集合成一个数组传入原函数
const rest =
fn =>
(...args) =>
fn(args);
const say = rest(
(what, names) =>
`${what} ${initial(names).join(', ')}${size(names) > 1 ? ', & ' : ''}${last(
names
)}`
);
say('hello', 'fred', 'barney', 'pebbles');
// => 'hello fred, barney, & pebbles'
思路:返回一个新的函数,该函数将原函数的参数集合成一个数组传入
spread
对指定函数进行封装,将参数数组展开作为多个参数传入原函数
const spread = fn => args => fn(...args);
const say = spread((who, what) => `${who} says ${what}`);
say(['fred', 'hello']);
// => 'fred says hello'
const numbers = Promise.all([Promise.resolve(40), Promise.resolve(36)]);
numbers.then(spread((x, y) => x + y));
// => a Promise of 76
思路:返回一个新的函数,该函数将原函数的参数数组展开作为多个参数传入
throttle
对指定函数进行节流处理
const throttle = (fn, time) => {
let timer;
return (...args) => {
if (!timer) {
timer = setTimeout(() => {
fn(...args);
timer = null;
}, time);
}
};
};
// 避免在滚动时过分的更新定位
jQuery(window).on('scroll', throttle(updatePosition, 100));
// 点击后就调用 `renewToken`,但5分钟内超过1次。
const throttled = throttle(renewToken, 300000, { trailing: false });
jQuery(element).on('click', throttled);
// 取消一个 trailing 的节流调用。
jQuery(window).on('popstate', throttled.cancel);
思路:返回一个新的函数,该函数对原函数进行节流处理
- 感谢你赐予我前进的力量