JS基础之常用的通用方法总结

108 阅读2分钟

1、深拷贝

/** 
* 深拷贝 
* @param {Object} obj 要拷贝的对象 
* @param {Map} map 用于存储循环引用对象的地址 
*/ 
function deepClone(obj = {}, map = new Map()) { 
    //不是对象类型,直接返回数据
    if (typeof obj !== "object") return obj;
    if (map.get(obj)) { 
        return map.get(obj); 
    } 
    // 初始化返回结果 
    let result = {};
    //判断是数组,定义返回类型为数组,双重判断是否数数组类型,预防Array 的 prototype 被重写
    if ( obj instanceof Array || Object.prototype.toString(obj) === "[object Array]" ) { 
        result = []; 
    } 
    // 防止循环引用 
    map.set(obj, result); 
    for (const key in obj) { 
        // 保证 key 不是原型属性 
        if (obj.hasOwnProperty(key)) { 
            // 递归调用 
            result[key] = deepClone(obj[key], map); 
        } 
    } 
    // 返回结果 
    return result; 
}

2、数组去重

/** 
* 数组去重 方法一 利用object的键唯一性
* @param {Array} arr 需要去重的数组 
*/ 
function uniqueArr(arr){
    let result = [];
    const hashMap = {};
    for(let i = 0; i < arr.length; i++){
        const temp = arr[i]
        if(!hashMap[temp]){
            hashMap[temp] = true
            result.push(temp)
        }
    }
    return result;
}
//方法二  利用set 的值唯一性
Array.from(new Set(arr))
//方法三
[...new Set(arr)]

3、多维数组的展平

// 展平一级
function flat(arr){
    var result = [];
    for(var i = 0; i < arr.length; i++){
        if(Array.isArray(arr[i])){
            result = result.concat(flat(arr[i]))
        }else{
            result.push(arr[i]);
        }
    }
    return result;
}
// 展平多级
function flattenByDeep(array,deep){
      var result = [];
      for(var i = 0 ; i < array.length; i++){
          if(Array.isArray(array[i]) && deep > 1){
                result = result.concat(flattenByDeep(array[i],deep -1))
          }else{
                result.push(array[i])
          }
      }
      return result;
}

4、Compose 函数的实现  从右执行

compose函数

compose函数可以将需要嵌套执行的函数平铺,嵌套执行就是一个函数的返回值将作为另一个函数的参数。他的顺序是从右往左,可用使用reduceRight实现

//es5 实现方式
const compose = function(){     
    const args = [].slice.apply(arguments);
    return function(x) { 
        return args.reduceRight((res, cb) => cb(res), x); 
    } 
}
//es6 实现方式
const compose = (...args) => x => args.reduceRight((res, cb) => cb(res), x);

5、Pipe 函数的实现   从左执行

pipe函数

pipe函数跟compose函数的左右是一样的,也是将参数平铺,只不过他的顺序是从左往。我们来实现下,只需要将reduceRight改成reduce就行了:

//es5 实现
const pipe = function(){     
    const args = [].slice.apply(arguments);
    return function(x) { 
        return args.reduce((res, cb) => cb(res), x); 
    } 
}
//es6 实现
const pipe = (...args) => x => args.reduce((res, cb) => cb(res), x)

6、柯里化 函数实现 curry

什么是curried 函数

curried函数是个一次一个的去获取多个参数的函数。  再明白点,就是比如 给定一个带有3个参数的函数,curried版的函数将接受一个参数并返回一个接受下一个参数的函数,该函数返回一个接受第三个参数的函数。最后一个函数返回将函数应用于其所有参数的结果

实现思路

  1. 通过闭包的方式储存传入参数
  2. 通过函数的length属性获得参数个数
  3. 当参数个数不够时直接返回方法
  4. 存储的参数个数等于原函数参数个数时执行原函数
  • 如果使用ES6参数默认值,length将不等于实际参数个数
  • 参数由arguments获取,ES6直接使用rest参数实现
function curry(fn) {
    const length = fn.length;
    const curryFn = (args) => (arg) => {
        const curryArgs = args.concat(arg);
        if (curryArgs.length === length) {
            return fn(...curryArgs);
        }
        return curryFn(curryArgs);
    }
    return curryFn([]);
}