「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!」
大家在面试当中经常会被问到“你了解XXX的原理吗?”“你可以用自己的思路实现XXX吗?”此篇文章旨在使用自己的思路实现某些函数,希望对大家有些许的帮助。
数组的 map 方法
数组的 map 方法实现的是创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
Array.prototype.map = function(fn){
let result = []
for(let i; i<this.length; i++){
if(i in this){
result.push(fn(this[i], i, this))
}
}
return result
}
Promise
class Promise {
constructor(executor) {
// 初始化状态为 pending
this.state = 'pending'
// 成功的值
this.value = undefined
// 失败的原因
this.reason = undefined
// 成功存放的数组
this.onResolvedCallbacks = []
// 失败存放的数组
this.onRejectedCallbacks = []
let resolve = value => {
if (this.state === 'pending') {
// resolve 调用成功后,将状态改变为 fulfilled
this.state = 'fulfilled'
// 储存成功的值
this.value = value
// 一旦 resolve 执行,调用成功数组的函数
this.onResolvedCallbacks.forEach(fn => fn())
}
}
let reject = reason => {
if (this.state === 'pending') {
// reject 调用后,状态改变为 rejected
this.state = 'rejected'
// 储存失败的原因
this.reason = reason
// 一旦r eject 执行, 调用失败数组的函数
this.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulfilled, onRejected) {
if (this.state === 'fulfilled') {
onFulfilled(this.value)
}
if (this.state === 'rejected') {
onRejected(this.reason)
}
// 当状态为 pending 的时候
if (this.state === 'pending') {
// onFulfilled 的值传入成功数组
this.onResolvedCallbacks.push(() => {
onFulfilled(this.value)
})
// onRejected 的值传入失败数组
this.onRejectedCallbacks.push(() => {
onRejected(this.reason)
})
}
}
}
深拷贝
function deepClone(obj, hash = new WeakMap()) {
if (obj instanceof RegExp) return new RegExp(obj)
if (obj instanceof Date) return new Date(obj)
if (obj === null || typeof obj !== 'object') {
return obj
}
if (hash.has(obj)) {
return hash.get(obj)
}
let t = new obj.constructor()
hash.set(obj, t)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
t[key] = deepClone(obj[key], hash)
}
}
return t
}
call/apply
Function.prototype.call = function() {
let [thisArg, ...args] = [...arguments];
if (!thisArg) {
//context为null或者是undefined
thisArg = typeof window === 'undefined' ? global : window;
}
//this的指向的是当前函数 func (func.call)
thisArg.func = this;
//执行函数
let result = thisArg.func(...args);
delete thisArg.func; //thisArg上并没有 func 属性,因此需要移除
return result;
}
Function.prototype.apply = function(thisArg, rest) {
let result; //函数返回结果
if (!thisArg) {
//context为null或者是undefined
thisArg = typeof window === 'undefined' ? global : window;
}
//this的指向的是当前函数 func (func.call)
thisArg.func = this;
if(!rest) {
//第二个参数为 null / undefined
result = thisArg.func();
}else {
result = thisArg.func(...rest);
}
delete thisArg.func; //thisArg上并没有 func 属性,因此需要移除
return result;
}
防抖/节流
// 节流(一段时间执行一次之后,就不执行第二次)
function throttle(fn, delay) {
let canUse = true
return function() {
if (canUse) {
fn.apply(this, arguments)
canUse = false
setTimeout(() => (canUse = true), delay)
}
}
}
const throttled = throttle(() => console.log('hi'))
throttled()
// 防抖(一段时间会等,然后带着一起做了)
function debounce(fn, delay) {
let timerId = null
return function() {
const context = this
if (timerId) {
window.clearTimeout(timerId)
}
timerId = setTimeout(() => {
fn.apply(context, arguments)
timerId = null
}, delay)
}
}
const debounced = debounce(() => console.log('hi'))
debounced()
AJAX
var request = new XMLHttpRequest()
request.open('GET', '/a/b/c', true)
request.onreadystatechange = function() {
if (request.readyState === 4 && request.status === 200) {
console.log(request.responseText)
}
}
request.send('name=abc&age=20')
最终用 TS 实现的 EventHub
class EventHub {
private cache: { [key: string]: Array<(data: unknown) => void> } = {}
on(eventName: string, fn: (data: unknown) => void) {
this.cache[eventName] = this.cache[eventName] || []
this.cache[eventName].push(fn)
}
emit(eventName: string, data?: unknown) {
(this.cache[eventName] || []).forEach(fn => fn(data))
}
off(eventName: string, fn: (data: unknown) => void) {
this.cache[eventName] = this.cache[eventName] || []
let index = indexOf(this.cache[eventName], fn)
if (index === -1) return
this.cache[eventName].splice(index, 1)
}
}
export default EventHub;
/**
* 帮助函数 indexOf
* @param arr
* @param item
*/
function indexOf(arr, item) {
if (arr === undefined) return -1
let index = -1
for (let i = 0; i < arr.length; i++) {
if (arr[i] === item) {
index = i
break
}
}
return index
}
最后说一句
如果这篇文章对您有所帮助,或者有所启发的话,帮忙点赞关注一下,您的支持是我坚持写作最大的动力,多谢支持。