浅聊一下
又是两个礼拜没有发文,这两个礼拜中,我用两天时间速通了百度...面试的是前端搜索岗位的实习生,所以难度不大...
面试了这么多天,觉得一个人的力量还是太过薄弱,如果你和我一样有向前冲的勇气,欢迎掘友们私聊我交流面经(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
对象。
不太明白的掘友可以去看看这篇文章this到底是谁的舔狗???😍 - 掘金 (juejin.cn)
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输出题你要注意的有以下几点:
- 在
new Promise
的时候,接收的回调函数是要立即调用的 - 先执行同步代码,宏任务存入宏任务队列,微任务存入微任务队列,当同步任务全部执行完毕以后,执行微任务队列,最后执行宏任务队列
resolve
或者reject
后面的代码也会执行,很多同学认为resolve
或者reject
后面的代码就不执行了await
会将后面的代码全部存入微任务队列
掌握这几点,promise输出题对你来说就是手到擒来了
手写发布订阅
面试官给了一段代码,补全代码
class EventEmitter{
on(){}
emit(){}
}
这里主要就是实现一个发布订阅,我在之前也写过发布订阅的文章由浅入深手撕发布订阅模式 - 掘金 (juejin.cn),掘友们要深入了解可以看看(虽然我也没有很深入哈哈哈)
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;
}
懒加载
之前也写过懒加载的文章懒加载是如何实现的 - 掘金 (juejin.cn),当我讲完这个方法的时候,面试官问我有没有更好的办法,那就要使用到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)
})
- 首先,它通过
document.querySelectorAll('img')
选取了文档中的所有图片元素,并将它们存储在imgs
变量中。 - 接下来定义了一个回调函数
callback
,用于处理Intersection Observer的触发事件。当被观察的元素(图片)进入或离开视口时,触发该回调函数。在这个回调函数中,首先通过console.log(entries)
输出观察到的所有元素的信息,然后遍历每一个观察到的元素(图片)。 - 对于每一个观察到的图片,判断它是否进入了视口(即
entry.isIntersecting
属性为true
)。如果是,则获取图片的data-src
属性值,将其设置为src
属性的值,从而触发图片的加载。然后调用observer.unobserve(image)
取消对该图片的观察,以避免重复加载。 - 最后,通过
IntersectionObserver
构造函数创建了一个Intersection Observer对象observer
,并将前面定义的回调函数callback
传递给它。然后,对imgs
数组中的每一个图片元素调用observer.observe(img)
,开始观察它们的可见性。
性能优化
- 防抖节流
防抖和节流-‘帕金森’网友的良方 - 掘金 (juejin.cn),较为简单,掘友们看文章就好
- 懒加载
- 分页和虚拟列表
打不过后端,十万条数据咱咬咬牙也能干 - 掘金 (juejin.cn),前两天刚做总结
- 使用http2.0
因为http2.0使用了多路复用,解决了http1.1带宽用不满的问题,使用推荐使用http2.0。 面试官总问我http,今天就来总结总结 - 掘金 (juejin.cn)
- 强缓存
强缓存我暂时还没有写过总结,这两天将总结一下...我主要讲了当我们的一些资源万年不变的时候,就可以使用浏览器的强缓存来将资源缓存到本地,这样再次加载页面上就不需要再去请求这些资源了,举个例子
百度的这张图片,就是一个强缓存的例子
再问:如果我后台更改了图片怎么办?
其实强缓存一张图片时,如果你更换一张图片,但是名字不变,实际上是检测不到的,所以我当时想不到什么好方法,只能硬着头皮说更换不同名字的图片...
一面大概就这些,12点面完,下午1点就收到了二面通知,选择在第二天上午...
百度二面
感觉百度二面是有点简单了,一直在聊天...
自我介绍
首先还是自我介绍,这里就不多说了
实习经历
有过一段实习经历,问我在实习中遇到的困难是什么,巴拉巴拉讲了一下,主要表达了我的学习能力强
项目
- 懒加载
可以在上面看哦
- 大文件上传
灵机一动的我连夜抛弃Vant的uploader组件 - 掘金 (juejin.cn)
- jwt鉴权
这个我已经讲过很多遍了...
讲一下你的优点和缺点
稍微讲了一下
二面很快,半个小时就结束了,可能一面面试官说了我逻辑算法强一点,所以没有考我算法和手写...
上午面完,下午就告诉我过了,总流程不到两天
结尾
我感觉稀里糊涂就过了...整体难度不大,然后目前这个岗位招人比较多,掘友们找实习的可以冲哦~~