面试

50 阅读4分钟

http1和http2的区别

juejin.cn/post/700151…

http和https的区别

juejin.cn/post/684490…

webpack热更新原理

juejin.cn/post/695027…

JS设计模式

juejin.cn/post/719870…

JS面向对象

juejin.cn/post/738702…

组建挂在到vue原型

juejin.cn/post/710119…

限制请求并发JS

队列的「先进先出」特性可以保证任务并发执行的顺序,在 JavaScript 中可以通过「数组来模拟队列」 juejin.cn/post/691222…

使用生成器函数 juejin.cn/post/717618…

webpack 原理,附带常见面试题

juejin.cn/post/713820…

请求options方法

其实,这是因为在跨域的情况下,在浏览器发起"复杂请求"时主动发起的。跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。

某些请求不会触发 CORS 预检请求,这样的请求一般称为"简单请求",而会触发预检的请求则成为"复杂请求"。 juejin.cn/post/684490…

微任务宏任务执行、微任务有哪些、宏任务有哪些

JavaScript中任务被分为两种,一种叫宏任务,一种叫微任务,它们在Event Loop机制中也扮演着至关重要的角色,与各种异步任务的执行顺序息息相关。

宏任务(Macro Task):

整个script 定时器任务,如setTimeout、setInterval。 浏览器事件,如click、mouseover。 网络请求,如fetch、XMLHttpRequest。 UI渲染,如重绘。

微任务(Micro Task):

Promise的回调函数 Async/Await 函数 MutationObserver的回调函数 process.nextTick Node.js环境下

执行顺序

先执行整个script这个宏任务,其中会包含各种小的宏任务以及微任务,从上至下,碰到同步任务就执行,碰到宏任务先放进宏任务队列,碰到微任务就放到微任务队列,当script这个宏任务执行到底时,就开始执行微任务队列里面的任务,执行完里面的微任务后去宏任务队列拿一个任务出来,如果这个宏任务里面又有许多微任务那就照样放进微任务队列,等待这个宏任务执行完后再执行微任务队列中的任务。 总结一下:最开始执行的一定是宏任务,然后这个宏任务中的微任务会先于其中的宏任务执行。

nextTick 的作用是什么?他的实现原理是什么?

在下次 DOM 更新循环结束之后执行延迟回调。nextTick主要使用了宏任务和微任务。根据执行环境分别尝试采用

Promise MutationObserver setImmediate 如果以上都不行则采用setTimeout

定义了一个异步方法,多次调用nextTick会将方法存入队列中,通过这个异步方法清空当前队列

手写Promise

juejin.cn/post/736383… 完整版:juejin.cn/post/734651…

class myPromise {
    constructor(executor) {
        this.status = 'pending'
        this.value = undefined
        this.reason = undefined
        this.onFulfilledCallback = []   //then 的回调
        this.onRejectedCallback = []    //catch 的回调

        // 改变Promise状态为fulfilled,并调用所有成功的回调函数  
        const resolve = (value) => {
            if (this.status === 'pending') {
                this.status = 'fulfilled'
                this.value = value
                //then 的回调在这里触发
                this.onFulfilledCallback.forEach(callback => callback(value))
            }
        }

        // 改变Promise状态为rejected,并调用所有失败的回调函数  
        const reject = (reason) => {
            if (this.status === 'pending') {
                this.status = 'rejected'
                this.reason = reason
                //catch 的回调在这里触发
                this.onRejectedCallback.forEach(callback => callback(reason))
            }
        }
        executor(resolve, reject)
    }

    // then方法用于注册成功和失败的回调函数 
    then(onFulfilled, onRejected) {
         // 处理默认情况,如果没有提供回调函数,则使用默认函数  
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason => {throw reason}

        const newPromise =  new myPromise((resolve, reject) => {
            if(this.status === 'fulfilled') {
                setTimeout(() => {
                    try {
                        const result = onFulfilled(this.value)
                        resolve(result)
                    }
                    catch (error) {
                        reject(error)
                    }
                }, 0)
            }

            if(this.status === 'rejected') {
                setTimeout(() => { // 模拟异步,但是模拟不了微任务
                    try {
                        const result = onRejected(this.reason)
                        resolve(result)
                    }
                    catch (error) {
                        resolve(error)
                    }
                }, 0)
            }
    
            // 如果Promise处于pending状态,则将回调函数保存到队列中
            if (this.status === 'pending') {
                this.onFulfilledCallback.push(() => {
                    setTimeout(() => {
                        try {
                            const result = onFulfilled()
                            resolve(result)
                        } catch (error) {
                            reject(error)
                        }
                    },0)
                })
                this.onRejectedCallback.push(()=> {
                    setTimeout(() => {
                        try {
                            const result = onRejected()
                            resolve(result)
                        } catch (error) {
                            reject(error)
                        }
                    },0)
                })
            }
        })
        return newPromise
    }
}


constructor(executor) {...}:myPromise类的构造函数,它接受一个executor函数作为参数。这个executor函数应该有两个参数:resolve和reject。resolve和reject是两个函数,用于改变 Promise 的状态并传递相应的值。

then(onFulfilled, onRejected) {...}:then方法用于注册成功和失败的回调函数。它接受两个可选参数:onFulfilled和onRejected。如果onFulfilled或onRejected没有被提供,then方法将使用默认的函数。

冒泡排序

Array.prototype.bubbleSort=function(){
    for(let i=0;i<this.length-1;i++){
        for(let j=0;j<this.length-1-i;j++){
            if(this[j]>this[j+1]){
                const temp=this[j]
                this[j]=this[j+1]
                this[j+1]=temp
            }
        }
    }
	return this
}

选择排序

const arr = [1, 3, 5, 3, 2, 18, 26, 1, 33, 92, 157, 48, 9, 762, 128];

const selectSort = (arr) => {
    const len = arr.length;
    let temp, minIndex;
    
    for (let i = 0; i < len - 1; i++) {
        minIndex = i;
        for (let j = i + 1; j < len; j++) {
            if (arr[j] <= arr[minIndex]) {
                minIndex = j
            }
        }
        temp = arr[i];
        arr[i] = arr[minIndex];
        arr[minIndex] = temp;
    }
    return arr;
};

console.log(selectSort(arr));