让前端飞Web前端之路

javscript 函数式编程库

2020-05-02  本文已影响0人  visitor009

下载地址:gitee
)

javascript 函数式编程的接口库

模仿underscore.js实现自己的函数库,增加额外自己常用的函数,用于学习函数式编程

目录结构

+ 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

使用

安装

统一

集合(数组或对象)

数组

函数

对象

实用功能

<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]
上一篇下一篇

猜你喜欢

热点阅读