貌似闲置了两周没写了。
这次直接完成util系列的方法,在实现array系列的时候,开始发现一些示例用了其他utils,所以就不完全按顺序来实现,而且在实现过程中发现,其实有些方法其实是另一个方法的进阶使用。

这次主要实现了除match、mixin几个还没理解透的函数。

简单方法:

function identity(value){
  return value
}
function noop(){}
function stubArray(){
  return []
}
function stubFalse(){
  return false
}
function stubObject(){
  return {}
}
function stubString(){
  return ''
}
function stubTrue(){
  return true
}

工具函数:

// 运行函数,如果函数调用异常则返回异常。
function attempt(func, ...args){
  let result;
  try{
    result = func.apply(null, args);
  }catch(e){
    result = e;
  }finally{
    return result
  }
}
// 按次数执行函数,次数序号为函数调用参数
function times(n, iteratee){
  return Array(n).fill(1).map((_, i)=>iteratee(i))
}
// 判断参数是否为NaN、null或undefined
function isN(val){
  if(typeof val === 'number' && val !== val) {
    return true
  }
  return val == null;
}
// 用于设定默认值
function defaultTo(val, defaultValue){
  return isN(val)?defaultValue:val
}
// 把路径字符串转换成数组
function toPath(path){
  return path.replace(/\]/g,'').split(/\.|\[/)
}
let idIndex = 0
function uniqueId(prefix){
  return prefix!=null?`${prefix}${idIndex++}`:`${idIndex++}`;
}
function constant(value){
  return () => value;
}

function bindAll(obj, methodNames){
  methodNames.forEach(m => {
    obj[m] = obj[m].bind(obj)
  })
}

高阶函数:

// 条件判断函数,类似if判断
function cond(pairs){
  return (...args)=>{
    for(let i=0;i<pairs.length;i++){
      if(pairs[i][0].apply(this, args)){
        return pairs[i][1].apply(this, args)
      }
    }
    return
  }
}
// 满足source所有条件才返回true
function conforms(source){
  return (obj) => {
    const keys = Object.keys(source)
    for(let i=0;i<keys.length;i++){
      if(!source[keys[i]](obj[keys[i]])){
        return false;
      }
    }
    return true
  }
}

function flow(funcs){
  return (...args)=>{
    return funcs.reduce((pre, cur)=>{
      return cur.apply(this, [].concat(pre))
    }, args)
  }
}
function flowRight(funcs){
  return (...args)=>{
    return funcs.reverse().reduce((pre, cur)=>{
      return cur.apply(this, [].concat(pre))
    }, args)
  }
}

function iteratee(arg){
  let func;
  if(typeof arg === 'string'){
    func = obj => obj[arg]
  }else if(arg instanceof Array){
    func = obj => obj[arg[0]] === arg[1]
  }else if(typeof arg === 'function') {
    func = arg
  }else{
    const keys = Object.keys(arg);
    func = obj => {
      for(let i=0;i<keys.length;i++){
        if(obj[keys[i]]!==arg[keys[i]]) return false
      }
      return true
    }
  }
  return func
}

function method(path, ...args){
  return obj => {
    return propertyOf(obj)(path).apply(obj,args)
  }
}
function methodOf(obj, ...args){
  return path => {
    return method.call(this, path,...args)(obj)
  }
}

function nthArg(n){
  return (...args)=>{
    return nth(args, n)
  }
}
function over(iteratees){
  return (...args)=>{
    return iteratees.map(it=>{
      return it.apply(this, args);
    })
  }
}
function overEvery(predicates){
  return (...args)=>{
    for(let i=0;i<predicates.length;i++){
      if(!predicates[i].apply(this, args)){
        return false
      }
    }
    return true;
  }
}
function overSome(predicates){
  return (...args)=>{
    for(let i=0;i<predicates.length;i++){
      if(predicates[i].apply(this, args)){
        return true
      }
    }
    return false;
  }
}
function property(path){
  const pathArr = path instanceof Array?path:toPath(path);
  return obj=>{
    return pathArr.reduce((pre, cur)=>{
      return pre[cur]
    }, obj)
  }
}
function propertyOf(obj){
  return path => {
    return property(path)(obj)
  }
}
// 当step为0的时候baseRange的做法是先确定数组个数,step会取1,但是在构造元素的时候通过start+=step, 这里我在实现上放弃了这种方式。
function range(...args){
  let start = 0;
  let end;
  let step = 1;
  if(args.length===1) {
    end = args[0];
    if(end<0){
      step = -1
    }
    if(end===0){
      return [];
    }
  }else if(args.length===2){
    start = args[0]
    end = args[1]
    if(start<0) {
      step = -1;
    } 
  }else {
    start = args[0]
    end = args[1]
    step = args[2]
  }
  if(step===0) {
    return [];
  }
  if(step>0&&end<start){
    return [];
  }
  if(step<0&&end>start){
    return [];
  }
  let tmp = start;
  let result = [];
  let length = (end - start)/step;
  while(length--){
    result.push(tmp)
    tmp+=step
  }
  return result;
}
function rangeRight(...args){
  return range.apply(this. args).reverse();
}
posted @ 2022-07-17 16:02 Dont 阅读(403) 评论(0) 推荐(0) 编辑
摘要: 前面说unzip其实就是数组转置,那其实zip也就是逆向,那还是转置了 导致zipObjectDeep费了点脑细胞,写了个勉强过了官方文档示例的实现。 function zip(...arr){ const result = []; arr.forEach((item, index)=>{ if(i 阅读全文
posted @ 2022-07-04 16:42 Dont 阅读(43) 评论(0) 推荐(0) 编辑
摘要: unzip是zip的逆向操作,但zip还没实现呢,先理解一下unzip,可以理解为二维数组的转置吧。 without则是和pull类似,只是它返回一个新的数组。 function unzip(arr){ const result = []; arr.forEach((item, index)=>{ 阅读全文
posted @ 2022-07-03 00:17 Dont 阅读(45) 评论(0) 推荐(0) 编辑
摘要: xor 数组类异或,其实是找出一堆数组里面,只出现一次的元素集合。 所以在最开始实现时,我的逻辑是,所有数遍历一次组合起来,并且记录每个元素出现的次数,再遍历一次全部,只把出现一次的元素丢到结果里返回。 上述想法是可以实现,但后续要实现xorBy和xorWith就有点不方便. 查看了下lodash源 阅读全文
posted @ 2022-07-03 00:16 Dont 阅读(107) 评论(0) 推荐(0) 编辑
摘要: union将传入的参数数组进行合并,生成一个新数组,虽然这种用map来做可能快一些吧,但不能保证元素加入的顺序,所以可以考虑通过遍历的方式,不断从收集的数组里查找遍历到的元素是否存在,不存在则加入(打不过就加入)。 function union(...arrs){ return arrs.reduc 阅读全文
posted @ 2022-07-01 01:03 Dont 阅读(44) 评论(0) 推荐(0) 编辑
摘要: uniq数组去重,只保留第一次出现的元素,也就是要保证元素的顺序,刚实现的union利用数组遍历来做,实际uniq也可以这么搞。 function uniq(arr){ return arr.reduce((pre, cur)=>{ if(!pre.includes(cur)) { pre.push 阅读全文
posted @ 2022-06-30 09:07 Dont 阅读(147) 评论(0) 推荐(0) 编辑
摘要: tail是很简单的函数方法了,就是返回数组除了开头元素外的数组。 take则是从数组中挑出指定个数的元素组成数组。 takeRight则是往后开始挑元素。 takeWhile则是根据传入的函数来判断,直到函数返回falsey时,结束挑选。 function tail(arr){ return arr 阅读全文
posted @ 2022-06-29 20:36 Dont 阅读(49) 评论(0) 推荐(0) 编辑
摘要: sortedUniq 和 uniq很像(uniq还没讲到就已经开始说sortedUniq了) 将排好序的数组去重,因为数组本身就排序了,那就好办了,遍历数组,重复的元素只会是连续的,所以只要用一个变量记录遍历时经过的不同数,下一个遍历只要遇到不同的数,就推入结果,并赋值给变量即可。 function 阅读全文
posted @ 2022-06-28 20:10 Dont 阅读(43) 评论(0) 推荐(0) 编辑
摘要: 拖了一周了,上周一直在忙(其实是sortedIndex没咋理解好) sortedIndex 从有序数组中找到指定数该插入的位置,用的是二分法的方式解决。 有两个关键点:有序数组,二分法 所以实现上是这样的: function sortedIndex(arr, value){ let head = 0 阅读全文
posted @ 2022-06-27 00:09 Dont 阅读(57) 评论(0) 推荐(0) 编辑
摘要: 又遇到简单的函数实现了 remove 移除数组中命中的元素,并返回移除元素组成的数组,会改变原数组。 和pullAt有点像 function remove(arr, iteratee){ const removes = []; for(let i=0;i<arr.length;i++){ if(it 阅读全文
posted @ 2022-06-19 16:17 Dont 阅读(62) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示