手写函数
发布于: 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 加入
还未添加个人简介
评论