写点什么

手写函数

用户头像
wudaxue
关注
发布于: 2021 年 04 月 02 日

手写数组转树

// 例如将 input 转成output的形式let input = [    {        id: 1, val: '学校', parentId: null    }, {        id: 2, val: '班级1', parentId: 1    }, {        id: 3, val: '班级2', parentId: 1    }, {        id: 4, val: '学生1', parentId: 2    }, {        id: 5, val: '学生2', parentId: 3    }, {        id: 6, val: '学生3', parentId: 3    },]
let output = { id: 1, val: '学校', children: [{ id: 2, val: '班级1', children: [ { id: 4, val: '学生1', children: [] }, { id: 5, val: '学生2', children: [] } ] }, { id: 3, val: '班级2', children: [{ id: 6, val: '学生3', children: [] }] }]}
复制代码


//代码实现function arrayToTree(array) {	let root = array[0]  array.shift()  let tree = {  	id: root.id,    val: root.val,    children: array.length > 0 ? toTree(root.id, array) : []  }  return tree}
function 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}
console.log(arrayToTree(input))
复制代码

手写 ES6proxy 如何实现 arr[-1]的访问

const negativeArray = els =>    new Proxy(els, {        get: (target, propKey, receiver) =>            Reflect.get(                target,                +propKey < 0 ? String(target.length + +propKey) : propKey,                receiver            )    });const unicorn = negativeArray(["京", "程", "一", "灯"]);unicorn[-1]; 
复制代码

原生实现 ES5 的 Object.create()方法

Object.create = function(prototype, propertries) {	if (typeof prototype !== "object") {  	throw TypeError();  }  function Ctor() {}  Ctor.prototype = prototype;  var o = new Ctor();  if (prototype) {  	p.constructor = Ctor;  }  if (propertries !== undefined) {  	if (peopertries !== Object(propertries)) {    	throw TypeError()    }    Object.defineProperties(o, propertries)  }  return o}
复制代码

手写 Promise.all

function promiseAll(promiseArr) {	if (!Array.isArray(promiseArr)) {  	throw new Error('promiseArr is not array')  }    let count = 0;  let resultArr = []  let len = promiseArrs.length  return new Promise((resolve, reject) => {  	for (let val of promiseArr) {      Promise.resolve(val).then(res => {      	resultArr[count++] = res        if (count === len) {        	resolve(resultArr)        }      }).catch(err => {      	reject(err)      })    }  })}
复制代码

Promise.race

function promiseRace(promiseArr) {	if (!Array.isArray(promiseArr)) {    throw Error('arr must be an array')  }	return new Promise((resolve, reject) => {  	promiseArr.forEach(_item => {    	Promise.resolve(_item).then(res => {      	resolve(res)      }).catch(err => {      	reject(err)      })    })  })}
复制代码

New 的实现

  1. 获取构造函数

  2. 创建一个对象

  3. 将函数的作用域赋给新对象(这里实际为生产一个新的上下文)

  4. 执行函数中的代码(为新对象添加属性、方法)

  5. 返回值,无返回值或者返回一个非对象值,则将创建的新对象返回,否则会将返回值作为新对象返回。(也就是说一定会返回一个对象回来)

function myNew () {	let constructor = Array.prototype.shift.call(arguments) //取出构造函数  let obj = {} //创建新对象  obj.__proto = constructor.prototype //该对象原型等于构造函数prototype  var result = constructor.apply(obj, arguments) //执行函数中代码  return typeof result === 'object' ? result : obj  //返回值必须为对象}
复制代码

发布订阅模式

class EventEmitter {	constructor() {  	this.events = {} 	}	on (eventName, callback) {  	if (!this.events[eventName]) {    	this.events[eventName] = [callback]    } else {    	this.events[eventName].push(callback)    }  },  emit(eventName) {  	this.events[eventName] && this.events[eventName].forEach(callback => callback())  },  removeListener(eventName, callback) {  	if (this.events[eventName]) {    	this.events[eventName] = this.events[eventName].filter(cb => cb != callback())    }  },  once(eventName, callback) {    let fn = () => {      callback();      this.removeListener(eventName, fn)    }    this.on(eventName, fn)  }}
复制代码

渲染 js 表示 dom 对象

ELement.prototype.render = function() {	val el = document.createElement(this.tagName)  var props = this.props  for (var propName in props) {  	var propValue = props[propName]    el.setAttribute(propName, propValue)  }  var children = this.children || []  children.forEach(child => {  	var childEl = (child instanceof Element) ? child.render() : document.createTextNode(child)    el.appendChild(childEl)  })    return el}
复制代码

防抖函数

  1. 原理

  • 在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。

  1. 使用场景

  • 提交按钮场景: 防止多次提交按钮,只执行最后提交的一次

  • 搜索框联想场景:防止联想发送请求,只发送最后一次输入

  1. 简易版本

function debounce = (fn, delay) => {	let timer;  return (...args) => {  	clearTimeout(timer)    timer = setTimeout(() => {    	fn.apply(this, args)    }, delay)  }}
复制代码
  1. 立即执行版

  • 立即执行函数,然后等到停止触发 n 秒后,才可以重新触发执行。

function debounce(fn, delay, immediate) {  let timer;  return (...args) => {    if (timer) clearTimeout(timer)    if (immediate) {      const callNow = !timer      timer = setTimeout(() => {            timer = null      }, delay)      if (callNow) fn.apply(this, args)    } else {      timer = setTimeout(() => {        fn.apply(this, args)      }, delay)    }  }}
复制代码

节流

  1. 原理:规定一个单位时间内,只能触发一次函数。如果这个单位时间内多次触发函数,只有一次生效

  2. 使用场景

  • 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动

  • 缩放场景:监控浏览器 resize

  1. 使用定时器实现

function throttle(fn, delay) {  let timer  return (...args) => {    if (!timer) {      timer = setTimeout(() => {        timer = null        fn.apply(this, args)      }, delay)    }  }}
复制代码


用户头像

wudaxue

关注

还未添加个人签名 2020.11.26 加入

还未添加个人简介

评论

发布
暂无评论
手写函数