JavaScript 函数工具
组
- all:布尔全等判断
const all = (arr, fn = Boolean) => arr.every(fn); all([4, 2, 3], x => x > 1); // true
all([1, 2, 3]); // true
- allEqual:检查数组各项相等
const allEqual = arr => arr.every(val => val === arr[0]); allEqual([1, 2, 3, 4, 5, 6]); // false
allEqual([1, 1, 1, 1]); // true
- approximatelyEqual:约等于
const approximatelyEqual = (v1, v2, epsilon = 0.001) => Math.abs(v1 - v2) < epsilon; approximatelyEqual(Math.PI / 2.0, 1.5708); // true
- arrayToCSV:数组转CSV格式(带空格的字符串)
const arrayToCSV = (arr, delimiter = ',') =>
arr.map(v => v.map(x => `"${x}"`).join(delimiter)).join('\n'); arrayToCSV([['a', 'b'], ['c', 'd']]); // '"a","b"\n"c","d"'
arrayToCSV([['a', 'b'], ['c', 'd']], ';'); // '"a";"b"\n"c";"d"'
- arrayToHtmlList:数组转li列表
const arrayToHtmlList = (arr, listID) =>
(el => (
(el = document.querySelector('#' + listID)),
(el.innerHTML += arr.map(item => `<li>${item}</li>`).join(''))
))(); arrayToHtmlList(['item 1', 'item 2'], 'myListID');
- average:平均数
const average = (...nums) => nums.reduce((acc, val) => acc + val, 0) / nums.length;
average(...[1, 2, 3]); // 2
average(1, 2, 3); // 2
- averageBy:数组对象属性平均数
此代码段将获取数组对象属性的平均值
const averageBy = (arr, fn) =>
arr.map(typeof fn === 'function' ? fn : val => val[fn]).reduce((acc, val) => acc + val, 0) /
arr.length; averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n); // 5
averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n'); // 5
- bifurcate:拆分断言后的数组
可以根据每个元素返回的值,使用reduce()和push() 将元素添加到第二次参数fn中 。
const bifurcate = (arr, filter) =>
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [[], []]);
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]);
// [ ['beep', 'boop', 'bar'], ['foo'] ]
- castArray:其它类型转数组
const castArray = val => (Array.isArray(val) ? val : [val]); castArray('foo'); // ['foo']
castArray([1]); // [1]
castArray(1); // [1]
- compact:去除数组中的无效/无用值
const compact = arr => arr.filter(Boolean); compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]);
// [ 1, 2, 3, 'a', 's', 34 ]
- countOccurrences:检测数值出现次数
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);
countOccurrences([1, 1, 2, 1, 2, 3], 1); // 3
- deepFlatten:递归扁平化数组
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]
- difference:寻找差异(并返回第一个数组独有的)
此代码段查找两个数组之间的差异,并返回第一个数组独有的。
const difference = (a, b) => {
const s = new Set(b);
return a.filter(x => !s.has(x));
}; difference([1, 2, 3], [1, 2, 4]); // [3]
- differenceBy:先执行再寻找差异
在将给定函数应用于两个列表的每个元素之后,此方法返回两个数组之间的差异。
const differenceBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter(x => !s.has(fn(x)));
}; differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [1.2]
differenceBy([{ x: 2 }, { x: 1 }], [{ x: 1 }], v => v.x); // [ { x: 2 } ]
- dropWhile:删除不符合条件的值
此代码段从数组顶部开始删除元素,直到传递的函数返回为true。
const dropWhile = (arr, func) => {
while (arr.length > 0 && !func(arr[0])) arr = arr.slice(1);
return arr;
}; dropWhile([1, 2, 3, 4], n => n >= 3); // [3,4]
- flatten:指定深度扁平化数组
此代码段第二参数可指定深度。
const flatten = (arr, depth = 1) =>
arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []); flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]
- indexOfAll:返回数组中某值的所有索引
此代码段可用于获取数组中某个值的所有索引,如果此值中未包含该值,则返回一个空数组。
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []); indexOfAll([1, 2, 3, 1, 2, 3], 1); // [0,3]
indexOfAll([1, 2, 3], 4); // []
- intersection:两数组的交集
const intersection = (a, b) => {
const s = new Set(b);
return a.filter(x => s.has(x));
}; intersection([1, 2, 3], [4, 3, 2]); // [2, 3]
- intersectionWith:两数组都符合条件的交集
此片段可用于在对两个数组的每个元素执行了函数之后,返回两个数组中存在的元素列表。
const intersectionBy = (a, b, fn) => {
const s = new Set(b.map(fn));
return a.filter(x => s.has(fn(x)));
}; intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); // [2.1]
- intersectionWith:先比较后返回交集
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1); intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]
- minN:返回指定长度的升序数组
const minN = (arr, n = 1) => [...arr].sort((a, b) => a - b).slice(0, n); minN([1, 2, 3]); // [1]
minN([1, 2, 3], 2); // [1,2]
- negate:根据条件反向筛选
const negate = func => (...args) => !func(...args); [1, 2, 3, 4, 5, 6].filter(negate(n => n % 2 === 0)); // [ 1, 3, 5 ]
- randomIntArrayInRange:生成两数之间指定长度的随机数组
const randomIntArrayInRange = (min, max, n = 1) =>
Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min); randomIntArrayInRange(12, 35, 10); // [ 34, 14, 27, 17, 30, 27, 20, 26, 21, 14 ]
- sample:在指定数组中获取随机数
const sample = arr => arr[Math.floor(Math.random() * arr.length)]; sample([3, 7, 9, 11]); // 9
- sampleSize:在指定数组中获取指定长度的随机数
此代码段可用于从数组中获取指定长度的随机数,直至穷尽数组。 使用Fisher-Yates算法对数组中的元素进行随机选择。
const sampleSize = ([...arr], n = 1) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr.slice(0, n);
}; sampleSize([1, 2, 3], 2); // [3,1]
sampleSize([1, 2, 3], 4); // [2,3,1]
- shuffle:“洗牌” 数组
此代码段使用Fisher-Yates算法随机排序数组的元素。
const shuffle = ([...arr]) => {
let m = arr.length;
while (m) {
const i = Math.floor(Math.random() * m--);
[arr[m], arr[i]] = [arr[i], arr[m]];
}
return arr;
}; const foo = [1, 2, 3];
shuffle(foo); // [2, 3, 1], foo = [1, 2, 3]
- nest:根据parent_id生成树结构(阿里一面真题)
根据每项的parent_id,生成具体树形结构的对象。
const nest = (items, id = null, link = 'parent_id') =>
items
.filter(item => item[link] === id)
.map(item => ({ ...item, children: nest(items, item.id) }));
用法:
const comments = [
{ id: 1, parent_id: null },
{ id: 2, parent_id: 1 },
{ id: 3, parent_id: 1 },
{ id: 4, parent_id: 2 },
{ id: 5, parent_id: 4 }
];
const nestedComments = nest(comments); // [{ id: 1, parent_id: null, children: [...] }]
函数
- attempt:捕获函数运行异常
该代码段执行一个函数,返回结果或捕获的错误对象。
onst attempt = (fn, ...args) => {
try {
return fn(...args);
} catch (e) {
return e instanceof Error ? e : new Error(e);
}
};
var elements = attempt(function(selector) {
return document.querySelectorAll(selector);
}, '>_>');
if (elements instanceof Error) elements = []; // elements = []
- defer:推迟执行
const defer = (fn, ...args) => setTimeout(fn, 1, ...args); defer(console.log, 'a'), console.log('b'); // logs 'b' then 'a'
- runPromisesInSeries:运行多个Promises
const runPromisesInSeries = ps => ps.reduce((p, next) => p.then(next), Promise.resolve());
const delay = d => new Promise(r => setTimeout(r, d)); runPromisesInSeries([() => delay(1000), () => delay(2000)]);
//依次执行每个Promises ,总共需要3秒钟才能完成
- timeTaken:计算函数执行时间
const timeTaken = callback => {
console.time('timeTaken');
const r = callback();
console.timeEnd('timeTaken');
return r;
}; timeTaken(() => Math.pow(2, 10)); // 1024, (logged): timeTaken: 0.02099609375ms
- createEventHub:简单的发布/订阅模式
创建一个发布/订阅(发布-订阅)事件集线,有emit,on和off方法。
- 使用Object.create(null)创建一个空的hub对象。
- emit,根据event参数解析处理程序数组,然后.forEach()通过传入数据作为参数来运行每个处理程序。
- on,为事件创建一个数组(若不存在则为空数组),然后.push()将处理程序添加到该数组。
- off,用.findIndex()在事件数组中查找处理程序的索引,并使用.splice()删除。
const createEventHub = () => ({
hub: Object.create(null),
emit(event, data) {
(this.hub[event] || []).forEach(handler => handler(data));
},
on(event, handler) {
if (!this.hub[event]) this.hub[event] = [];
this.hub[event].push(handler);
},
off(event, handler) {
const i = (this.hub[event] || []).findIndex(h => h === handler);
if (i > -1) this.hub[event].splice(i, 1);
if (this.hub[event].length === 0) delete this.hub[event];
}
});
用法:
const handler = data => console.log(data);
const hub = createEventHub();
let increment = 0; // 订阅,监听不同事件
hub.on('message', handler);
hub.on('message', () => console.log('Message event fired'));
hub.on('increment', () => increment++); // 发布:发出事件以调用所有订阅给它们的处理程序,并将数据作为参数传递给它们
hub.emit('message', 'hello world'); // 打印 'hello world' 和 'Message event fired'
hub.emit('message', { hello: 'world' }); // 打印 对象 和 'Message event fired'
hub.emit('increment'); // increment = 1 // 停止订阅
hub.off('message', handler);
- memoize:缓存函数
通过实例化一个Map对象来创建一个空的缓存。
通过检查输入值的函数输出是否已缓存,返回存储一个参数的函数,该参数将被提供给已记忆的函数;如果没有,则存储并返回它。
const memoize = fn => {
const cache = new Map();
const cached = function(val) {
return cache.has(val) ? cache.get(val) : cache.set(val, fn.call(this, val)) && cache.get(val);
};
cached.cache = cache;
return cached;
};
Ps: 这个版本可能不是很清晰,还有Vue源码版的:
/**
* Create a cached version of a pure function.
*/
export function cached<F: Function> (fn: F): F {
const cache = Object.create(null)
return (function cachedFn (str: string) {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}: any)
}
- once:只调用一次的函数
const once = fn => {
let called = false
return function () {
if (!called) {
called = true
fn.apply(this, arguments)
}
}
};
- flattenObject:以键的路径扁平化对象
使用递归。
- 利用Object.keys(obj)联合Array.prototype.reduce(),以每片叶子节点转换为扁平的路径节点。
- 如果键的值是一个对象,则函数使用调用适当的自身prefix以创建路径Object.assign()。
- 否则,它将适当的前缀键值对添加到累加器对象。
- prefix除非您希望每个键都有一个前缀,否则应始终省略第二个参数。
const flattenObject = (obj, prefix = '') =>
Object.keys(obj).reduce((acc, k) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
else acc[pre + k] = obj[k];
return acc;
}, {}); flattenObject({ a: { b: { c: 1 } }, d: 1 }); // { 'a.b.c': 1, d: 1 }
- unflattenObject:以键的路径展开对象
与上面的相反,展开对象。
const unflattenObject = obj =>
Object.keys(obj).reduce((acc, k) => {
if (k.indexOf('.') !== -1) {
const keys = k.split('.');
Object.assign(
acc,
JSON.parse(
'{' +
keys.map((v, i) => (i !== keys.length - 1 ? `"${v}":{` : `"${v}":`)).join('') +
obj[k] +
'}'.repeat(keys.length)
)
);
} else acc[k] = obj[k];
return acc;
}, {}); unflattenObject({ 'a.b.c': 1, d: 1 }); // { a: { b: { c: 1 } }, d: 1 }
这个的用途,在做Tree组件或复杂表单时取值非常舒服。
字符串
- byteSize:返回字符串的字节长度
const byteSize = str => new Blob([str]).size; byteSize('JavaScript 函数工具的更多相关文章
- 利用JavaScript函数对字符串进行加密
加密.解密问题对我来说一直是很神秘的,感到神奇无比. 理论了解 前段时间看到关于利用JavaScript函数unescape()和escape()对字符串进行替换处理.通过查资料得知, escape( ...
- 实例演示 kino.razor (前端 Javascript 模板工具,Razor 风格)的使用
前言 对于习惯了 ASP.NET MVC Razor 模板引擎的人来说,比如我,一直在寻找前端 Javascript 端的 Razor 模板工具.这之前,我也了解到很多Javascript 端的模板工 ...
- 第八章:Javascript函数
函数是这样一段代码,它只定义一次,但可能被执行或调用任意次.你可能从诸如子例程(subroutine)或者过程(procedure)这些名字里对函数概念有所了解. javascript函数是参数化的: ...
- JavaScript 开发工具webstrom使用指南
本文给大家推荐了一款非常热门的javascript开发工具webstrom,着重介绍了webstrom的特色功能.设置技巧.使用心得以及快捷键汇总,非常的全面. 看到网上一篇介绍webstrom的文章 ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第七节--登录逻辑及abp封装的Javascript函数库
经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这里算是前面几节的一个初次试水. 首先我们数据库已经有的相应的数据. 模型和DTO已经建好,所以我们直接在服务 ...
- JavaScript开发工具大全
译者按: 最全的JavaScript开发工具列表,总有一款适合你! 原文: THE ULTIMATE LIST OF JAVASCRIPT TOOLS 译者: Fundebug 为了保证可读性,本文采 ...
- javaScript系列 [01]-javaScript函数基础
[01]-javaScript函数基础 1.1 函数的创建和结构 函数的定义:函数是JavaScript的基础模块单元,包含一组语句,用于代码复用.信息隐蔽和组合调用. 函数的创建:在javaScri ...
- javascript常用工具类整理(copy)
JavaScript常用工具类 类型 日期 数组 字符串 数字 网络请求 节点 存储 其他 1.类型 isString (o) { //是否字符串 return Object.prototype.to ...
- ABP+AdminLTE+Bootstrap Table权限管理系统第七节--登录逻辑及几种abp封装的Javascript函数库
返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 简介 经过前几节,我们已经解决数据库,模型,DTO,控制器和注入等问题.那么再来看一下登录逻辑.这 ...
随机推荐
- Linux之find命令
1.find命令的作用 主要用于操作系统文件.目录的查找. 2.find命令常用参数 -name #按文件名查找 -type #按文件类型查找:b/p/c/p/l/f -size #但文件大小查找,G ...
- VLAN实验2(配置Trunk接口)
本实验基于<HCNA网络技术实验指南> 本实验使用eNSP软件 原理概述: 在以太网中,通过划分VLAN来隔离广播域和增强网络通信的安全性.以太网通常由 多台交换机组成,为了使VLAN的数 ...
- Flask开发VIP版HttpServer #华为云·寻找黑马程序员#
欢迎添加华为云小助手微信(微信号:HWCloud002 或 HWCloud003),输入关键字"加群",加入华为云线上技术讨论群:输入关键字"最新活动",获取华 ...
- eclipse maven 项目导出为 jar 包
一个 maven 项目有很多依赖,所以最后打出的 jar 一般会很多,且比较大,打成 jar 包的步骤 (注意pom.xml文件中打包类型不能是war包): 1. 把 pom.xml 中依赖的库打成 ...
- luogu P4343 [SHOI2015]自动刷题机 |二分答案
题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开了他的新发明:自动刷题机--一种可以自动 AC 题目的神秘装置. 自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序. ...
- luogu P2296 寻找道路 |最短路
题目描述 在有向图 G 中,每条边的长度均为 1,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 路径上的所有点的出边所指向的点都直接或间接与终点连通. 在满足条件 1 的 ...
- luogu P1582 倒水 |数学
题目描述 一天,CC买了N个容量可以认为是无限大的瓶子,开始时每个瓶子里有1升水.接着~~CC发现瓶子实在太多了,于是他决定保留不超过K个瓶子.每次他选择两个当前含水量相同的瓶子,把一个瓶子的水全部倒 ...
- MySql数据基础之数据表操作
MySql数据库中主要利用多个数据表进行数据的存储,我们可以将数据表理解成一个Excel表格,Excel表格的第一列可以将它看为id列,主要任务是数据表中数据的唯一标识,不能重复.不能为空.如果将数据 ...
- CSS修饰文档
定义字体类型 <html> <head> <meta http-equiv="Content-Type" content="text/htm ...
- django学习03-模版
新手做的笔记,很可能会有理解错误的地方.欢迎拍砖. 在polls/views.py中增加下面内容,完善功能. def detail(request, question_id): return Http ...