javscript 函数式编程库
下载地址:gitee
)
javascript 函数式编程的接口库
模仿underscore.js实现自己的函数库,增加额外自己常用的函数,用于学习函数式编程
- 使用es6实现部分underscore.js的函数,增加自己常用的
- 增加自己常用到的函数,如
onceDelay
(运行一次后在指定时间后才能再次运行) - 错误处理:
- 指定参数类型才能运行函数
- 检测运行时函数是否为必须,必须时没传函数控制台输出提示信息
- 单元测试
目录结构
+ browserTest // 浏览器单元测试环境
|-- index.html
+ lib
|-- functional.js // 函数库
+ mochawesome-report
|-- mochawesome.html // 单元测试报告
+ doc 文档
|-- index_with_tree
+ test 单元测试
|-- functional.test.js // 测试用例代码
|-- spec.html // 测试用例规格
运行单元测试
node
npm install -g mocha mochawesome
npm install
npm run test
// 生成测试报告
npm run report
// 生成测试用例规格
npm run spec
浏览器
直接打开browserTest/index.html
使用
安装
- 浏览器: 通过
<script>
引入,默认绑定全局变量 _ - node:
require
引入
统一
- 传入 [context],在function中的this会指向[context]
- 当传入不合符函数的参数类型时,会返回自身(有想过返回undefined),不会去运行函数
- 当函数参数中 function 为必传时,没传控制台会输出提示信息
- 参数带 [ ] 为选填,如[context]
- hasKey
- isEqual
- inMatch
- isObject
- isArray
- isFunction
- isPromise
- isDate
- isRegExp
- isMap
- isSet
- isString
- isNumber
- isNull
- isNaN
- isUndefined
- isSymbol
<h2 name='集合'>集合 (数组或对象)</h2集合>
each each [^each ]
_.each(list, function, [context])
遍历集合中的每一个元素。 list可以是 Object|Array|String|Set|Map,function 的参数是(value, key, list)
_.each([1,2],(value,key,list)=>{
console.log(value,key,list) // 1 0 [1,2]
})
<h4 name='map'>map</h4>
_.map(list, function, [context])
将集合中的每一个元素转换成function的返回值,返回值是原来的数据类型。 list可以是 Object|Array,function 的参数是(value, key, list)
_.map([1,2],value=>value+1) // [2,3]
_.map({a:2,b:3},value=>value+1) // {a:3,b:4}
<h4 name='reduce'>reduce</h4>
_.reduce(list, function, [context])
迭代集合中的元素,将每次迭代的值保存在memo参数中。 list可以是 Object|Array|String,function 的参数是(memo,value, key, list)
_.reduce([1,2,3],(memo,value)=>value+memo) // 6
_.reduce({a:2,b:3},(memo,value)=>value+memo) // 5
_.reduce('str',(memo,value)=>value+'-'+memo) // s-t-r
<h4 name='find'>find</h4>
_.find(list, function, [context])
在集合查找符合function 返回值的元素。 list可以是 Object|Array|String,function 的参数是(value, key, list)
_.find([1,2,3],value=>value === 3) // 3
_.find({a:2,b:3},value=>value === 3) // 3
_.find([{a:2},{a:3}],obj=>obj.a === 3) // {a:3}
_.find('str',value=>value == 't') // t
<h4 name='filter'>filter</h4>
_.filter(list, function, [context])
返回在集合中符合function 返回值的元素。 list可以是 Object|Array,function 的参数是(value, key, list)
_.filter([1,2,3],value=>value >= 2) // [2,3]
_.filter({a:2,b:3},value=>value === 3) // {b:3}
<h4 name='every'>every</h4>
_.every(list, function, [context])
在集合中每一项元素都符合条件,返回true。 list可以是 Object|Array|String,function 的参数是(value, key, list)
_.every([1,2,3],value=>value != 0) // true
_.every([1,2,3],value=>value >= 2) // false
_.every({a:2,b:3},value=>value != 0) // true
_.every('sss',value=>value == 's') // true
<h4 name='some'>some</h4>
_.some(list, function, [context])
在集合中每一项元素都符合条件,返回true。 list可以是 Object|Array|String,function 的参数是(value, key, list)
_.some([1,2,3],value=>value == 0) // false
_.some([1,2,3],value=>value == 2) // true
_.some({a:2,b:3},value=>value != 0) // true
_.some('str',value=>value == 's') // true
<h4 name='max'>max</h4>
_.max(list)
返回集合中最大的元素。 list可以是 Object|Array,只支持数字
_.max([1,2,3]) // 3
_.max({a:1,b:2}) // 2
_.max({}) // undefined
<h4 name='min'>min</h4>
_.min(list)
返回集合中最大的元素。 list可以是 Object|Array,只支持数字
_.min([1,2,3]) // 1
_.min({a:1,b:2}) // 1
_.min({}) // undefined
<h4 name='contains'>contains</h4>
_.contains(list,ele)
包含指定元素,返回true。 list可以是 Object | Array | String, ele可以是 Object | Array | String | Number | Boolean | null | undefined | NaN。注意当是Object | Array 会使用 isEqual 进行判断
_.contains('st','t') // true
_.contains({a:1,b:2},2) // true
_.contains([1,2],2) // true
_.contains([{a:1}],{a:1}) // true
<h4 name='size'>size</h4>
_.size(list)
返回元素长度。 list可以是 Object | Array | String
_.size('st') // 2
_.size({a:1,b:2}) // 2
_.size([1,2,3]) // 3
<h4 name='isEmpty'>isEmpty</h4>
_.isEmpty(list)
集合是否为空 。 list可以是 Object | Array | String
_.isEmpty('st') // false
_.isEmpty({a:1,b:2}) // false
_.isEmpty([]) // true
<h2 name='数组'>数组</h2>
<h4 name='last'>last</h4>
_.last(list)
返回数组最后的元素。
_.last([2,3,1]) // 1
<h4 name='unique'>unique</h4>
_.unique(list)
数组去重
_.unique([2,3,1,1]) // [2,3,1]
<h4 name='range'>range</h4>
_.range([start],end,[step])
生成数组
_.range(4) // [0,1,2,3]
_.range(1,4) // [1,2,3]
_.range(2,8,2) // [2,4,6]
<h2 name='函数'>函数</h2>
<h4 name='partial'>partial</h4>
_.partial(fn,args)
偏函数。使用null为占位符,保存已有参数,返回一个函数,
function add(a,b) {return a+b}
let add2 = _.partial(add,null,2)
add2(3) // 5
<h4 name='memoize'>memoize</h4>
_.memoize(fn)
缓存函数运行后的结果。如果缓存中已有,则直接返回。只支持单个参数的函数
let factorial = _.memoize(function (n) {
let result = 1;
return _factorial(n);
function _factorial(n) {
count++; // 调用次数
result *= n;
if (n == 1) {
return result;
}
return _factorial(--n) // es6的尾调用优化
}
});
let count = 0; // 调用factorial次数
factory(5) // 120,count == 5
count = 0;
factory(5) // 120, count == 0
<h4 name='curry'>curry</h4>
_.curry(fn,args)
柯里化。将函数变成一元函数(单个参数)的过程。用处:根据一个模板函数,生成多个函数。注意 fn参数中有es6 ...rest 无法进行柯里化
function add(a,b) {
return a+b;
}
let three = _.curry(add)(1,2);
let add2 = _.curry(add)(2);
three // 3
add2(1) // 3
<h4 name='delay'>delay</h4>
_.delay(fn,delay,[*args])
延迟运行。args为fn的参数,可以多个
_.delay(alert,1000,'hello')
<h4 name='throttle'>throttle</h4>
_.throttle(fn,[delay])
节流函数。在 delay ms内不停触发只运行一次,默认200ms。返回一个函数
let fn = _.throttle(alert,100);
window.onmousemove = function() {fn('hello')} // hello
<h4 name='debounce'>debounce</h4>
_.debounce(fn,[wait])
防抖函数。运行一次后过 wait ms后才能运行。返回一个函数
let fn = _.debounce(alert,500);
window.onmousemove = function() {fn('hello')} // hello
<h4 name='once'>once</h4>
_.once(fn,[context])
页面生命周期内只运行一次fn。
let fn = _.once(alert)
fn('once')
<h4 name='pipe'>pipe</h4>
_.pipe(*function)
管道函数。从左往右运行,返回最后函数运行的值
let mapAbs = array=>{
return _.map(array,value=>Math.abs(value))
}
let max = array=>{
return Math.max(...array)
}
let fn = _.pipe(mapAbs,max)
// let fn = _.pipe(mapAbs ,_.tap((v)=>{log(v)}),max) · // 可用_.tap 调试运行过程的值
fn([1,-3,2]) // 3
<h2 name='对象'>对象</h2>
<h4 name='hasKey'>hasKey</h4>
_.hasKey(obj,key)
obj是否有key 这个属性。
_.hasKey({a:1},'a') // true
_.hasKey({},'a') // false
<h4 name='isEqual'>isEqual</h4>
_.isEqual(obj,other)
判断obj,other 是否深度相等。类型可以是 引用类型: Object | Array | Date | DOM元素, 基本数据类型: String | NUmber | Boolean | Null | undefined | NaN。遇到第一个false会退出。注意: Array 与顺序有关,Object 与顺序无关。
_.isEqual([],[]) //true
_.isEqual({},{}) //true
_.isEqual({a:1},{a:1}) //true
_.isEqual({b:1,a:2},{a:2,b:1}) //true,Object 顺序无关
_.isEqual({a:[1,false]},{a:[1,false]}) //true
_.isEqual({a:{a:NaN}},{a:{a:NaN}}) //true
_.isEqual([null,'s'],[null,'s']) //true
_.isEqual([[1,2],{a:1}],[[1,2],{a:1}]) //true
_.isEqual([1,2],[2,1]) //false
<h4 name='inMatch'>inMatch</h4>
_.inMatch(obj,properties)
对象 是否包含 properties。相等类型可以是 引用类型: Object | Array | Date | DOM元素, 基本数据类型: String | NUmber | Boolean | Null | undefined | NaN。遇到第一个false会退出。注意: Array 与顺序有关,Object 与顺序无关;Array 和 Object 会使用isEqual进行判断。
_.inMatch({},{}) //true
_.inMatch({a:1},{a:1}) //true
_.inMatch({b:1,a:{name:1,age:2}},{a:{age:2,name:1}}) //true,Object 顺序无关
_.inMatch({},{a:1}) // false
<h4 name='isObject'>isObject</h4>
_.isObject(obj)
obj是否为一个对象
_.isObject({a:1}) // true
<h4 name='isArray'>isArray</h4>
_.isArray(obj)
obj是否为一个数组
_.isArray({a:1}) // true
<h4 name='isFunction'>isFunction</h4>
_.isFunction(obj)
obj是否为一个函数
_.isFunction(()=>{}) // true
<h4 name='isPromise'>isPromise</h4>
_.isPromise(obj)
obj是否为一个Promise 对象
let promise = new Promise((resovle,reject)=>{})
_.isPromise(promise) // true
<h4 name='isDate'>isDate</h4>
_.isDate(obj)
obj是否为一个日期对象
_.isDate(new Date()) // true
<h4 name='isRegExp'>isRegExp</h4>
_.isRegExp(obj)
obj是否为一个正则对象
_.isRegExp(/1/) // true
<h4 name='isMap'>isMap</h4>
_.isMap(obj)
obj是否为一个Map对象
_.isMap(new Map()) // true
<h4 name='isSet'>isSet</h4>
_.isSet(obj)
obj是否为一个Set对象
_.isSet(new Set()) // true
<h4 name='isString'>isString</h4>
_.isString(obj)
obj是否为一个字符串
_.isString('') // true
<h4 name='isNumber'>isNumber</h4>
_.isNumber(obj)
obj是否为一个数字
_.isNumber(1) // true
<h4 name='isNull'>isNull</h4>
_.isNull(obj)
obj是否为一个null
_.isNull(null) // true
<h4 name='isNaN'>isNaN</h4>
_.isNaN(obj)
obj是否为一个NaN
_.isNaN(NaN) // true
<h4 name='isUndefined'>isUndefined</h4>
_.isUndefined(obj)
obj是否为一个undefined
_.isUndefined(undefined) // true
<h4 name='isSymbol'>isSymbol</h4>
_.isSymbol(obj)
obj是否为一个Symbol
let symbol = new Symbol('s')
_.isSymbol(symbol) // true
<h2 name='实用功能'>实用功能</h2>
<h4 name='noConflict'>noConflict</h4>
_.noConflict()
放弃_的引用(在浏览端有效),返回 _ ;
let my = _.noConflict(); // _ is undefined
<h4 name='formatDate'>formatDate</h4>
_.formatDate(date,format)
格式化日期。如果不传参数,默认当前日期。 ;
let date = new Date('2020/5/1 18:35:5');
// 正常用法 _.formatDate(date,'yyyy-MM-dd')
// 固定参数重复使用,可用柯里化或偏函数`_.partial(_.formatDate,date,null)`
let formatDate = _.curry(_.formatDate)(date)
formatDate('yyyy-MM-dd') // 2020-05-01
formatDate('M月d日') // 5月1日
/*
yyyy 年
M 月
MM 月 补0
d 日
dd 补0
H 小时
HH 小时 补0
m 分钟
mm 分钟 补0
s 秒
ss 秒 补0
*/
<h4 name='random'>random</h4>
_.random(min,[max])
返回min - max 的随机数。只有一个参数,返回0- min ;不包括max .
_.random(2); // 0 1
_.random(2,4) // 2,3
<h4 name='checkValueType'>checkValueType</h4>
_.checkValueType(variable)
检测变量类型。
checkValueType([]) // 'array'
checkValueType({}) // 'object'
checkValueType(Promise) // 'promise'
checkValueType(()=>{}) // 'function'
checkValueType(/1/) // 'regexp'
checkValueType("") // 'string'
checkValueType(123) // 'number'
checkValueType(true) // 'boolean'
checkValueType(undefined) // 'undefined'
checkValueType(null) // 'null'
checkValueType(undefined) // 'symbol'
checkValueType(NaN) // 'NaN'
<h4 name='deepClone'>deepClone</h4>
_.deepClone(obj)
深拷贝。支持引用类型(Object Array Date)、基本数据类型(String Number Boolean undefined null NaN )
_.deepClone({a:1,b:2}) // {a:1,b:2}
_.deepClone([1,2]) // [1,2]