web前端JS高阶面试题,面试技巧总结

if (request.readyState!==4) {
return
}
// 如果响应状态码在[200, 300)之间代表成功, 否则失败
const {status, statusText} = request
// 2.1. 如果请求成功了, 调用resolve()
if (status>=200 && status<=299) {
// 准备结果数据对象response
const response = {
data: JSON.parse(request.response),
status,
statusText
}
resolve(response)
} else { // 2.2. 如果请求失败了, 调用reject()
reject(new Error('request error status is ’ + status))
}
}
})
}
/* 发送特定请求的静态方法 */
axios.get = function (url, options) {
return axios(Object.assign(options, {url, method: ‘GET’}))
}
axios.delete = function (url, options) {
return axios(Object.assign(options, {url, method: ‘DELETE’}))
}
axios.post = function (url, data, options) {
return axios(Object.assign(options, {url, data, method: ‘POST’}))
}
axios.put = function (url, data, options) {
return axios(Object.assign(options, {url, data, method: ‘PUT’}))
}
export default axios

#####自定义事件总线

/*

  • 自定义事件总线
    /
    const eventBus = {}
    /

    {
    add: [callback1, callback2]
    delete: [callback3]
    }
    /
    let callbacksObj = {}
    /

    绑定事件监听
    /
    eventBus.on = function (eventName, callback) {
    const callbacks = callbacksObj[eventName]
    if (callbacks) {
    callbacks.push(callback)
    } else {
    callbacksObj[eventName] = [callback]
    }
    }
    /

    分发事件
    /
    eventBus.emit = function (eventName, data) {
    const callbacks = callbacksObj[eventName]
    if (callbacks && callbacks.length > 0) {
    callbacks.forEach(callback => {
    callback(data)
    })
    }
    }
    /

    移除事件监听
    */
    eventBus.off = function (eventName) {
    if (eventName) {
    delete callbacksObj[eventName]
    } else {
    callbacksObj = {}
    }
    }
    export default eventBus

#####自定义消息订阅与发布

/*
自定义消息订阅与发布
/
const PubSub = {}
/

{
add: {
token1: callback1,
token2: callback2
},
update: {
token3: callback3
}
}
/
let callbacksObj = {} // 保存所有回调的容器
let id = 0 // 用于生成token的标记
// 1. 订阅消息
PubSub.subscribe = function (msgName, callback) {
// 确定token
const token = ‘token_’ + ++id
// 取出当前消息对应的callbacks
const callbacks = callbacksObj[msgName]
if (!callbacks) {
callbacksObj[msgName] = {
[token]: callback
}
} else {
callbacks[token] = callback
}
// 返回token
return token
}
// 2. 发布异步的消息
PubSub.publish = function (msgName, data) {
// 取出当前消息对应的callbacks
let callbacks = callbacksObj[msgName]
// 如果有值
if (callbacks) {
// callbacks = Object.assign({}, callbacks)
// 启动定时器, 异步执行所有的回调函数
setTimeout(() => {
Object.values(callbacks).forEach(callback => {
callback(data)
})
}, 0)
}
}
// 3. 发布同步的消息
PubSub.publishSync = function (msgName, data) {
// 取出当前消息对应的callbacks
const callbacks = callbacksObj[msgName]
// 如果有值
if (callbacks) {
// 立即同步执行所有的回调函数
Object.values(callbacks).forEach(callback => {
callback(data)
})
}
}
/

4. 取消消息订阅
1). 没有传值, flag为undefined
2). 传入token字符串
3). msgName字符串
*/
PubSub.unsubscribe = function (flag) {
// 如果flag没有指定或者为null, 取消所有
if (flag === undefined) {
callbacksObj = {}
} else if (typeof flag === ‘string’) {
if (flag.indexOf(‘token_’) === 0) { // flag是token
// 找到flag对应的callbacks
const callbacks = Object.values(callbacksObj).find(callbacks => callbacks.hasOwnProperty(flag))
// 如果存在, 删除对应的属性
if (callbacks) {
delete callbacks[flag]
}
} else { // flag是msgName
delete callbacksObj[flag]
}
} else {
throw new Error(‘如果传入参数, 必须是字符串类型’)
}
}
export default PubSub

#####自定义数组声明式系列方法

/*
实现数组声明式处理系列工具函数
/
/

实现map()
/
export function map (array, callback) {
const arr = []
for (let index = 0; index < array.length; index++) {
arr.push(callback(array[index], index))
}
return arr
}
/

实现reduce()
/
export function reduce (array, callback, initValue) {
let result = initValue
for (let index = 0; index < array.length; index++) {
// 调用回调函数将返回的结果赋值给result
result = callback(result, array[index], index)
}
return result
}
/

实现filter()
/
export function filter(array, callback) {
const arr = []
for (let index = 0; index < array.length; index++) {
if (callback(array[index], index)) {
arr.push(array[index])
}
}
return arr
}
/

实现find()
/
export function find (array, callback) {
for (let index = 0; index < array.length; index++) {
if (callback(array[index], index)) {
return array[index]
}
}
return undefined
}
/

实现findIndex()
/
export function findIndex (array, callback) {
for (let index = 0; index < array.length; index++) {
if (callback(array[index], index)) {
return index
}
}
return -1
}
/

实现every()
/
export function every (array, callback) {
for (let index = 0; index < array.length; index++) {
if (!callback(array[index], index)) { // 只有一个结果为false, 直接返回false
return false
}
}
return true
}
/

实现some()
*/
export function some (array, callback) {
for (let index = 0; index < array.length; index++) {
if (callback(array[index], index)) { // 只有一个结果为true, 直接返回true
return true
}
}
return false
}
export function test() {
console.log(‘test()222’)
}

#####手写Promise

const PENDING = ‘pending’ // 初始未确定的状态
const RESOLVED = ‘resolved’ // 成功的状态
const REJECTED = ‘rejected’ // 失败的状态
/*
Promise构造函数
/
function Promise(excutor) {
const self = this // Promise的实例对象
self.status = PENDING // 状态属性, 初始值为pending, 代表初始未确定的状态
self.data = undefined // 用来存储结果数据的属性, 初始值为undefined
self.callbacks = [] // {onResolved(){}, onRejected(){}}
/

将promise的状态改为成功, 指定成功的value
/
function resolve(value) {
// 如果当前不是pending, 直接结束
if (self.status !== PENDING) return
self.status = RESOLVED // 将状态改为成功
self.data = value // 保存成功的value
// 异步调用所有缓存的待执行成功的回调函数
if (self.callbacks.length > 0) {
// 启动一个延迟时间为0的定时器, 在定时器的回调中执行所有成功的回调
setTimeout(() => {
self.callbacks.forEach(cbsObj => {
cbsObj.onResolved(value)
})
})
}
}
/

将promise的状态改为失败, 指定失败的reason
/
function reject(reason) {
// 如果当前不是pending, 直接结束
if (self.status !== PENDING) return
self.status = REJECTED // 将状态改为失败
self.data = reason // 保存reason数据
// 异步调用所有缓存的待执行失败的回调函数
if (self.callbacks.length > 0) {
// 启动一个延迟时间为0的定时器, 在定时器的回调中执行所有失败的回调
setTimeout(() => {
self.callbacks.forEach(cbsObj => {
cbsObj.onRejected(reason)
})
})
}
}
// 调用excutor来启动异步任务
try {
excutor(resolve, reject)
} catch (error) { // 执行器执行出错, 当前promise变为失败
console.log(‘-----’)
reject(error)
}
}
/

用来指定成功/失败回调函数的方法
1). 如果当前promise是resolved, 异步执行成功的回调函数onResolved
2). 如果当前promise是rejected, 异步执行成功的回调函数onRejected
3). 如果当前promise是pending, 保存回调函数
返回一个新的promise对象
它的结果状态由onResolved或者onRejected执行的结果决定
2.1). 抛出error ==> 变为rejected, 结果值为error
2.2). 返回值不是promise ==> 变为resolved, 结果值为返回值
2.3). 返回值是promise ===> 由这个promise的决定新的promise的结果(成功/失败)
/
Promise.prototype.then = function (onResolved, onRejected) {
const self = this
onResolved = typeof onResolved === ‘function’ ? onResolved : value => value // 将value向下传递
onRejected = typeof onRejected === ‘function’ ? onRejected : reason => {
throw reason
} // 将reason向下传递
return new Promise((resolve, reject) => { // 什么时候改变它的状态
/

  1. 调用指定的回调函数
  2. 根据回调执行结果来更新返回promise的状态
    /
    function handle(callback) {
    try {
    const result = callback(self.data)
    if (!(result instanceof Promise)) { // 2.2). 返回值不是promise ==> 变为resolved, 结果值为返回值
    resolve(result)
    } else { // 2.3). 返回值是promise ===> 由这个promise的决定新的promise的结果(成功/失败)
    result.then(
    value => resolve(value),
    reason => reject(reason)
    )
    // result.then(resolve, reject)
    }
    } catch (error) { // 2.1). 抛出error ==> 变为rejected, 结果值为error
    reject(error)
    }
    }
    if (self.status === RESOLVED) {
    setTimeout(() => {
    handle(onResolved)
    })
    } else if (self.status === REJECTED) {
    setTimeout(() => {
    handle(onRejected)
    })
    } else { // PENDING
    self.callbacks.push({
    onResolved(value) {
    handle(onResolved)
    },
    onRejected(reason) {
    handle(onRejected)
    }
    })
    }
    })
    }
    /

    用来指定失败回调函数的方法
    catch是then的语法糖
    /
    Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected)
    }
    /

    用来返回一个指定vlaue的成功的promise
    value可能是一个一般的值, 也可能是promise对象
    /
    Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
    // 如果value是一个promise, 最终返回的promise的结果由value决定
    if (value instanceof Promise) {
    value.then(resolve, reject)
    } else { // value不是promise, 返回的是成功的promise, 成功的值就是value
    resolve(value)
    }
    })
    }
    /

    用来返回一个指定reason的失败的promise
    /
    Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
    reject(reason)
    })
    }
    /

    返回一个promise, 只有当数组中所有promise都成功才成功, 否则失败
    /
    Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
    let resolvedCount = 0 // 已经成功的数量
    const values = new Array(promises.length) // 用来保存成功promise的value值
    // 遍历所有promise, 取其对应的结果
    promises.forEach((p, index) => {
    p.then(
    value => {
    resolvedCount++
    values[index] = value
    if (resolvedCount === promises.length) { // 都成功了
    resolve(values)
    }
    },
    reason => reject(reason)
    )
    })
    })
    }
    /

    返回一个promise, 由第一个完成promise决定
    /
    Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
    // 遍历所有promise, 取其对应的结果
    promises.forEach(p => {
    // 返回的promise由第一个完成p来决定其结果
    p.then(resolve, reject)
    })
    })
    }
    /

    返回一个延迟指定时间才成功(也可能失败)的promise
    /
    Promise.resolveDelay = function (value, time) {
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    // 如果value是一个promise, 最终返回的promise的结果由value决定
    if (value instanceof Promise) {
    value.then(resolve, reject)
    } else { // value不是promise, 返回的是成功的promise, 成功的值就是value
    resolve(value)
    }
    }, time)
    })
    }
    /

    返回一个延迟指定时间才失败的promise
    */
    Promise.rejectDelay = function (reason, time) {
    return new Promise((resolve, reject) => {
    setTimeout(() => {
    reject(reason)
    }, time)
    })
    }
    export default Promise

#####自定义数组扁平化

/*
数组扁平化: 取出嵌套数组(多维)中的所有元素放到一个新数组(一维)中
如: [1, [3, [2, 4]]] ==> [1, 3, 2, 4]
/
/

方法一: 递归 + reduce() + concat()
/
export function flatten1 (array) {
return array.reduce((pre, item) => {
if (Array.isArray(item)) {
return pre.concat(flatten1(item))
} else {
return pre.concat(item)
}
}, [])
}
/

方法二: … + some() + concat()
*/
export function flatten2 (array) {
let arr = [].concat(…array)
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(…arr)
}
return arr
}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

计算机网络

  • HTTP 缓存

  • 你知道 302 状态码是什么嘛?你平时浏览网页的过程中遇到过哪些 302 的场景?

  • HTTP 常用的请求方式,区别和用途?

  • HTTPS 是什么?具体流程

  • 三次握手和四次挥手

  • 你对 TCP 滑动窗口有了解嘛?

  • WebSocket与Ajax的区别

  • 了解 WebSocket 嘛?

  • HTTP 如何实现长连接?在什么时候会超时?

  • TCP 如何保证有效传输及拥塞控制原理。

  • TCP 协议怎么保证可靠的,UDP 为什么不可靠?

算法

  • 链表

  • 字符串

  • 数组问题

  • 二叉树

  • 排序算法

  • 二分查找

  • 动态规划

  • BFS

  • DFS

  • 回溯算法

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
img

WebSocket与Ajax的区别

  • 了解 WebSocket 嘛?

  • HTTP 如何实现长连接?在什么时候会超时?

  • TCP 如何保证有效传输及拥塞控制原理。

  • TCP 协议怎么保证可靠的,UDP 为什么不可靠?

算法

  • 链表

  • 字符串

  • 数组问题

  • 二叉树

  • 排序算法

  • 二分查找

  • 动态规划

  • BFS

  • DFS

  • 回溯算法

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-qKszPIWK-1712928440788)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值