前端日常使用函数实现

458 阅读2分钟

数组去重

Set + Array

function uniqueArray(arr) {
  return Array.from(new Set(arr));
};

splice

function uniqueArray(arr) {
  for(let i = 0; i < arr.length - 1; i++) {
    for(let j = i + 1; j < arr.length; j++) {
      if(arr[j] === arr[i]) {
        arr.splice(j--,1);
      }
    }
  }
  return arr
};

扁平化数组

es6 中 flat

[1,2,[3,3]].flat() // [1,2,3,3]

reduce

function flat(arr) {
  return arr.reduce((prev, next) => {
    return prev.concat(Array.isArray(next) ? flat(next) : next);
  }, [])
}

自定义 instanceof

function customInstanceof(left, right) {
  let proto = Object.getPrototypeOf(left);
  while(proto) {
    if (proto === right.prototype) {
      return true;
    }
    proto = Object.getPrototypeOf(proto);
  }
  return false;
}

实现 getElementById

递归

const getElementById = (node, id) => {
  if (node == null) {
    return null;
  }
  if (node.id === id) {
    return node;
  }
  for (let i = 0; i < node.children.length; i++) {
    const result = getElementById(node.children[i], id);
    if (result != null) {
      return result;
    }
  }
  return null;
}

非递归

const nextElement = (node) => {
  if (node.children.length) {
    return node.children[0]
  }
  if (node.nextElementSibling) {
    return node.nextElementSibling;
  }
  while(node.parentNode) {
    if (node.parentNode.nextElementSibling) {
      return node.parentNode.nextElementSibling;
    }
    node = node.parentNode;
  }
  return null
}
const getElementById = (node, id) => {
  while(node) {
    if (node.id === id) {
      return node;
    }
    node = nextElement(node);
  }
  return node;
}

实际上浏览器是使用的一个映射,直接将id映射到dom上

call、apply、bind

call

Function.prototype.customCall = function(obj, ...args) {
  const call = Symbol('call');
  const thisObject = obj || window;
  thisObject[call] = this;
  const result = obj[call](...args);
  delete thisObject[call];
  return result;
}

apply

Function.prototype.customApply = function(obj, ...args) {
  const call = Symbol('call');
  const thisObject = obj || window;
  thisObject[call] = this;
  const result = obj[call](...args);
  delete thisObject[call];
  return result;
}

bind

Function.prototype.myBind = function(obj, ...args) {
  const self = this;
  function result (otherArgs) {
    const allArgs = args.concat(otherArgs);
    return self.apply(this instanceof self ? this : obj, allArgs);
  }
  result.prototype = Object.create(self.prototype);
  return result;
}

bind 利用了 apply,处理了通过 new 调用的情况

new

function customNew(constructorFunc, ...args) {
  const obj = {};
  Object.setPrototypeOf(obj, constructorFunc.prototype);

  // const obj = Object.create(constructorFunc.prototype);

  const result = constructorFunc.apply(obj, args);

  return result instanceof Object ? result : obj;
}

函数式

curry

function curry(func) {
  const argLength = func.length;
  return function deepCurry(...args) {
    if (args.length >= argLength) {
      return func.apply(null, args);
    } else {
      return function(...args2) {
        return deepCurry.apply(null, args.concat(args2));
      }
    }
  }
}

compose

function compose(...args) {
  return args.reduce((final, next) => {
    return (...args) => {
      return final(next(...args));
    }
  }, result => result);
}

浅拷贝

数组

API解决

  • Array.from()
  • [].concat()
  • Array.propertype.slice.call()
  • [...arr]

对象

API解决

  • Object.assign
  • {...otherObj}

自定义

function shallowClone(source) {
  const result = Object.create(null);
  for(let i in source) {
    if(source.hasOwnProperty(i)) {
      result[i] = source[i]
    }
  }
  return result
}

深拷贝

自定义

function cloneDeep(source) {
  if(source == null) {
    return source;
  }
  if (Array.isArray(source)) {
    return source.map(cloneDeep);
  };
  if (typeof source === 'object') {
    const result = Object.create(null);
    for (const key in source) {
      if (source.hasOwnProperty(key)) {
        result[key] = cloneDeep(source[key]);
      }
    }
    return result
  }
  return source;
}

JSON.parse(JSON.stringify())

缺陷:函数会在转换中丢失

Base64转File

function dataURLtoFile(str, filename) {
  const [type, content] = str.split(',')
  const bstr = window.atob(content)
  let n = bstr.length
  const u8arr = new Uint8Array(n)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n)
  }
  return new File([u8arr], filename, {
    type: type.replace(/(data:)|(;base64)/g, ''),
  })
}

File 转 Base64

这里得通过 FileReader,而且是异步操作

function fileToBase64(file) {
  return new Promise(function(resolve, reject) {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onloadend = (event) => {
      resolve(event.target.result)
    }
  })
}

ArrayToTree

const toTree = (parentId, array) => {
  let children = [];
  let len = array.length;
  for (let i = 0; i < len; i++) {
    let node = array[i];
    if (node.parentId === parentId) {
      children.push({
        id: node.id,
        val: node.val,
        children: toTree(node.id, array)
      })
    }
  }
  return children;
}

const arrayToTree = (array) => {
  let root = array[0];
  array.shift();
  let tree = {
    id: root.id,
    val: root.val,
    children: array.length ? toTree(root.id, array) : []
  }
  return tree;
}