手写函数
发布于: 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 的实现
获取构造函数
创建一个对象
将函数的作用域赋给新对象(这里实际为生产一个新的上下文)
执行函数中的代码(为新对象添加属性、方法)
返回值,无返回值或者返回一个非对象值,则将创建的新对象返回,否则会将返回值作为新对象返回。(也就是说一定会返回一个对象回来)
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}复制代码
防抖函数
原理
在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。
使用场景
提交按钮场景: 防止多次提交按钮,只执行最后提交的一次
搜索框联想场景:防止联想发送请求,只发送最后一次输入
简易版本
function debounce = (fn, delay) => { let timer; return (...args) => { clearTimeout(timer) timer = setTimeout(() => { fn.apply(this, args) }, delay) }}复制代码
立即执行版
立即执行函数,然后等到停止触发 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) } }}复制代码
节流
原理:规定一个单位时间内,只能触发一次函数。如果这个单位时间内多次触发函数,只有一次生效
使用场景
拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
缩放场景:监控浏览器 resize
使用定时器实现
function throttle(fn, delay) { let timer return (...args) => { if (!timer) { timer = setTimeout(() => { timer = null fn.apply(this, args) }, delay) } }}复制代码
划线
评论
复制
发布于: 2021 年 04 月 02 日阅读数: 18
wudaxue
关注
还未添加个人签名 2020.11.26 加入
还未添加个人简介











评论