两天时间速通百度...

发布于:2024-04-30 ⋅ 阅读:(30) ⋅ 点赞:(0)

浅聊一下

又是两个礼拜没有发文,这两个礼拜中,我用两天时间速通了百度...面试的是前端搜索岗位的实习生,所以难度不大...

面试了这么多天,觉得一个人的力量还是太过薄弱,如果你和我一样有向前冲的勇气,欢迎掘友们私聊我交流面经(wechat: LongLBond

百度一面

自我介绍

自我介绍少不了,我在之前的文章中也提到过,要讲明白: 我是谁+从哪里来+我做过什么+有什么成绩+为什么能胜任...

this

首先考了一道this的题目,问输出是多少

let obj1 = {
    fn:function(){
        console.log(this);
    }
}
obj1.fn()
let obj2 = {
    fn:()=>{
        console.log(this);
    }
}
obj2.fn()

这里主要是考察this绑定和箭头函数没有this

当你调用obj1.fn()时,函数fn()被作为obj1对象的方法调用,因此this指向调用该方法的对象,也就是obj1。所以,this在这种情况下指向obj1对象。

而在obj2.fn()中,fn是一个箭头函数。箭头函数没有自己的this绑定,它会继承外层作用域的this。在这种情况下,箭头函数fn的外层作用域是全局作用域(或者是最接近的非箭头函数的作用域)。因此,在浏览器环境中,它通常会指向window对象,而在Node.js环境中可能会指向global对象。

image.png

不太明白的掘友可以去看看这篇文章

Promise

promise具体的题目内容我忘记了,大家可以参考蔚来的Promise输出题

const promise = new Promise((resolve, reject) => {
    console.log(1);
    setTimeout(() => {
        console.log("6");
        setTimeout(() => { console.log(8); }, 0)
        resolve('success')
        console.log(7);
    }, 0);
    console.log(2);
});
setTimeout(() => {
    console.log(5);
}, 0)

promise.then((res) => {
    console.log(res);
})
console.log(4);

在写这类promise输出题你要注意的有以下几点:

  1. new Promise的时候,接收的回调函数是要立即调用的
  2. 先执行同步代码,宏任务存入宏任务队列,微任务存入微任务队列,当同步任务全部执行完毕以后,执行微任务队列,最后执行宏任务队列
  3. resolve或者reject后面的代码也会执行,很多同学认为resolve或者reject后面的代码就不执行了
  4. await会将后面的代码全部存入微任务队列

掌握这几点,promise输出题对你来说就是手到擒来了

手写发布订阅

面试官给了一段代码,补全代码

class EventEmitter{
    on(){}
    emit(){}
}

这里主要就是实现一个发布订阅,我在之前也写过发布订阅的文章,掘友们要深入了解可以看看(虽然我也没有很深入哈哈哈)

class EventEmitter{
    constructor(){
        this.event = {}//'run':[fun]
    }
    on(type,cb){
        if(!this.event[type]){
            this.event[type] = [cb]
        }else{
            this.event[type].push(cb)
        }
    }
    emit(type,...args){//派发事件
        if(!this.event[type]){
            return
        }else{
            this.event[type].forEach(cb=>{
                cb(...args)
            })
        }
    }

想清楚,emit是发布者,on是订阅者

  • 构造函数constructor初始化了一个event对象,用于存储事件类型及其对应的回调函数。
  • on方法用于注册事件监听器,接受事件类型和回调函数作为参数。如果该事件类型尚未存在,则创建一个数组存储回调函数;否则,将新的回调函数添加到已存在的数组中。
  • emit方法用于派发事件,接受事件类型和参数。如果该事件类型不存在,直接返回;否则,遍历该事件类型对应的回调函数数组,依次执行回调函数并传入参数。

手写map

没有看过手写map之类的知识,我还是第一次遇见,所以分析了一下临场发挥

Array.prototype.myMap = function(fn){
    let arr = this
    let res = []
    for(let i of arr){
        let ans = fn(i)
        res.push(ans)
    }
    return res
}
let arr = [1,2,3]
console.log(arr.myMap((i)=>i+1));
  • myMap方法接受一个函数fn作为参数。
  • 在方法内部,首先将this关键字指向的数组赋值给变量arr,这样就可以在方法中访问到调用该方法的数组。
  • 然后,创建一个空数组res,用于存储函数fn对数组每个元素执行后的结果。
  • 使用for...of循环遍历数组arr的每个元素,在循环中,将当前元素传递给函数fn,并将返回值存储在变量ans中。
  • 最后,将变量ans的值添加到结果数组res中。
  • 循环结束后,返回结果数组res,其中包含了对原数组每个元素执行函数fn后的结果。

斐波那契

题目意思主要是给你一个n,要求得到f(n)

function fibonacci(n) {
    if (n <= 1) {
        return n;
    }
    let fib = [0, 1];
    for (let i = 2; i <= n; i++) {
        fib[i] = fib[i - 1] + fib[i - 2];
    }
    return fib[n];
}

这题我说了两种方法,另一种时间复杂度为O(n),空间复杂度为O(1)

function fibonacci(n) {
    if (n <= 1) {
        return n;
    }
    let prev = 0;
    let curr = 1;
    for (let i = 2; i <= n; i++) {
        let next = prev + curr;
        prev = curr;
        curr = next;
    }
    return curr;
}

懒加载

之前也写过懒加载的文章,当我讲完这个方法的时候,面试官问我有没有更好的办法,那就要使用到InsectionObserver

    const imgs = document.querySelectorAll('img');
    const callback = entries=>{
        console.log(entries);
        entries.forEach(entry=>{
            if(entry.isIntersecting){
                const image = entry.target
                const data_src = image.getAttribute('data-src')
                image.setAttribute('src',data_src)
                observer.unobserve(image)
            }
        })
        console.log('懒加载触发')
    }
    const observer  = new IntersectionObserver(callback)
    imgs.forEach(img=>{
        observer.observe(img)
    })
  1. 首先,它通过document.querySelectorAll('img')选取了文档中的所有图片元素,并将它们存储在imgs变量中。
  2. 接下来定义了一个回调函数callback,用于处理Intersection Observer的触发事件。当被观察的元素(图片)进入或离开视口时,触发该回调函数。在这个回调函数中,首先通过console.log(entries)输出观察到的所有元素的信息,然后遍历每一个观察到的元素(图片)。
  3. 对于每一个观察到的图片,判断它是否进入了视口(即entry.isIntersecting属性为true)。如果是,则获取图片的data-src属性值,将其设置为src属性的值,从而触发图片的加载。然后调用observer.unobserve(image)取消对该图片的观察,以避免重复加载。
  4. 最后,通过IntersectionObserver构造函数创建了一个Intersection Observer对象observer,并将前面定义的回调函数callback传递给它。然后,对imgs数组中的每一个图片元素调用observer.observe(img),开始观察它们的可见性。

性能优化

  • 防抖节流

,较为简单,掘友们看文章就好

  • 懒加载
  • 分页和虚拟列表

,前两天刚做总结

  • 使用http2.0

因为http2.0使用了多路复用,解决了http1.1带宽用不满的问题,使用推荐使用http2.0。

  • 强缓存

强缓存我暂时还没有写过总结,这两天将总结一下...我主要讲了当我们的一些资源万年不变的时候,就可以使用浏览器的强缓存来将资源缓存到本地,这样再次加载页面上就不需要再去请求这些资源了,举个例子

image.png

百度的这张图片,就是一个强缓存的例子

再问:如果我后台更改了图片怎么办?

其实强缓存一张图片时,如果你更换一张图片,但是名字不变,实际上是检测不到的,所以我当时想不到什么好方法,只能硬着头皮说更换不同名字的图片...

一面大概就这些,12点面完,下午1点就收到了二面通知,选择在第二天上午...

百度二面

感觉百度二面是有点简单了,一直在聊天...

自我介绍

首先还是自我介绍,这里就不多说了

实习经历

有过一段实习经历,问我在实习中遇到的困难是什么,巴拉巴拉讲了一下,主要表达了我的学习能力强

项目

  • 懒加载

可以在上面看哦

  • 大文件上传

  • jwt鉴权

这个我已经讲过很多遍了...

讲一下你的优点和缺点

稍微讲了一下

二面很快,半个小时就结束了,可能一面面试官说了我逻辑算法强一点,所以没有考我算法和手写...

上午面完,下午就告诉我过了,总流程不到两天

结尾

我感觉稀里糊涂就过了...整体难度不大,然后目前这个岗位招人比较多,掘友们找实习的可以冲哦~~


网站公告

今日签到

点亮在社区的每一天
去签到