石墨文档两面后,我整理了这些面试题
背景
本人开学大三,非科班,苦逼机械学生,从大一下自学前端,如今练习时长还不够两年半,临近开学 ,试着面了一下武汉的石墨文档。8.23约的hr,8.24上午11点进行1面,下午两点半进行2面。先说下感受,难度不大,他们公司技术栈是react,而我是vue,所以没问框架。主要考察js,css,计网,设计模式等方面知识。一面考察基础,二面考察深度。
一面
一面持续了1个小时,主要考察js,css 我把问题整理一下。
- 1.请说出js中几种声明变量的方式?
答: es6之前都是用var,es6之后推出了let const声明,用var声明会造成变量提升,let和const是块级作用域就不会,还有一种是不用关键字,直接声明,效果和var类似。
- 既然谈到变量提升请你说一下啥是变量提升?
答:在执行代码之前,变量的声明会被提升到其作用域的顶部。
出个题你看看
console.log(a)
var a = 1
console.log(a)
求输出结果:undefined和1 这个题没难度不用多说
- 2.说一下js在点击一个dom之后,js引擎如何处理? 这个题,开始没思路,就往事件冒泡和事件捕获方向考虑了,结果还真是,思路差不多
答:javaScript 引擎会检查该元素是否已经绑定了点击事件的监听器。如果已经绑定了监听器,引擎会执行该监听器函数。如果没有绑定监听器,引擎会继续向该元素的父元素冒泡,直到找到已经绑定了监听器的元素,或者冒泡到文档根节点时停止。
那既然说到了事件冒泡,说一下如何阻止冒泡
答:用api stopPropagation()
那如何在事件捕获阶段执行事件呢?
这个题,我当时没答出来,这个问题蛮基础的,傻了当时唉。
答案:
const btn = document.querySelector('#btn')
btn.addEventListener('click', () => {}, true)
将最后一个参数改为true,这个真是基础问题,默认是false表示开启冒泡,改为true就是捕获阶段执行,w3c上面有。
- 3.说一下css垂直居中的方式
这个题答的还不错,这个还是要记住,面试了好几家都问过。
答:
- 子设置absolute,父relative 子元素left:50%, top:50%, 再用平移translate(-50%)
- flex布局,父元素设置flex justify-content:center align-items:center
- 利用line-height搭配vertical-align也可以实现
补充:如果会grid布局实现,也是可以的
- 4.如何判断是不是一个数组?
答:js中有几种检查数据类型的方式,typeof intanceof Array.isArray(), Object.prototype.toString.call() 这几种。
- typeof只能检测出是一个对象,不能检测是不是数组。
- intanceof可以,判断是不是一个数组,返回布尔值。
- Array.isArray()也是返回一个布尔值。
- Object.prototype.toString.call()可以精确的返回一个数据的类型
- 5.下面给你出个题看看
var length = 1
function fn() {
console.log(this.length)
}
var obj = {
length: 4,
test: function(t) {
t()
arguments[0]()
}
}
obj.test(fn, 6)
说实话刚开始看不难,后面那个arguments打印出来的值就蒙蔽了
答:这个题是作用域以及this指向问题,函数的作用域要看,定义的位置,这里的fn定义在全局,所以在obj.test(fn, 6)
第一个参数是1, 第二个arguments[0]这个我只知道是剩余参数,这个没答出来
arguments是接受形参的数量 , arguments[0]就是fn,再调用一次,但是此时this指向arguments了,打印的应当rguments的length,是2,因为后面又传入了一个形参,所以有两个参数,即length为2
- 6.知道事件循环吗? 看个题
let button = document.querySelector('#button');
button.addEventListener('click', function CB1(){
console.log('Listener 1');
setTimeout(() => console.log('Timeout 1'))
promise.resolve().then(() => console.log('Promise 1'))
})
button.addEventListener('click', function CB1(){
console.log('Listener 2');
setTimeout(() => console.log('Timeout 2'))
promise.resolve().then(() => console.log('Promise 2'))
})
这个题就是典型的宏任务,微任务的考察。宏任务,微任务,我在很多评论区,看过大家争吵。我按我的理解来说,每次事件循环,都先看有没有宏任务, 有的话,给他放进宏任务队列中,再看看宏任务中有没有微任务,如果有,进入微任务队列中。在每轮事件循环中,都需要将宏任务中的微任务清空。所以宏任务先执行还是微任务先执行都是相对的。
这个题输出顺序是,首先有两个点击事件是宏任务, 进入宏任务队列。接下来执行里面的逻辑,同步代码优先执行,所以先打印 'Listener 1', 接着遇到定时器,是宏任务,放到宏任务队列中,等下轮执行,promise.then()是微任务,所以需要将本轮宏任务的微任务执行完,因此接着输出'Promise 1'。
这个宏任务就执行完了,接下来执行第二个,同第一个的逻辑,因此题目输出顺序为
Listener 1 -> Promise 1 -> Listener 2 -> Promise 2 -> Timeout 1 -> Timeout 2
- 7.子元素的margin-top:10%的10%是多少?
这个题答错了,很多人可能跟我一样觉得是相对于父元素的高度来计算,实际不是,是相对于父元素的宽度来计算的,这个要注意, 属于知识盲区了。
- 8.css3选择器说一下,知道多少说多少
答:通配符,id,class 标签,伪类, 后代,兄弟,子 :root, :where, :is :empty, :not, :has 这个题答的还是蛮多的。
那你知道他们的权重吗?
答:
id:0100
类、伪类、属性选择器: 0010
标签:001
拓展一下:继承的样式没有权重,即* + >这些为0000
-
- 实现动画的方式
答: css用animation属性,js用requestAnimation函数也可以实现。
那你说说requestAnimation吗?
答:requestAnimation有些情况下可以当作定时器使用,它的时间一般是17ms, 在react fiber中也有应用。
那你说说为啥是17ms
答:因为浏览器一帧是16.66666ms,而requestAnimation执行时间取决于浏览器绘制频率。
- 10.有没有处理过跨域?
答:在前端vue中使用proxy代理,在后端设置cors允许指定域名通过,在nginx中设置反向代理。
当时漏了一个jsonP,面试官问了一下jsonP的原理
答: 通过script标签请求服务器, 浏览器不会对scrpit进行拦截,所以可以,但是缺点是只能通过get请求。
- 11.有了解过websocket吗?
- 时 答:了解过,websocket是一种全双工通信,原理利用tcp协议,WebSocket 在建立握手时,数据是通过 HTTP 传输的。但是建立之后,在真正传输时候是不需要 HTTP 协议的。
那你说说如果浏览器不支持websocket如何替代?
这个真把我问住了,我以为sse不可以,没想到是可以的,当时答的一塌糊涂😭
答案:
- 轮询(Polling):客户端定时向服务器发送请求,服务器返回最新数据,客户端再进行更新。这种方式会造成不必要的网络开销,但是兼容性好,可以在所有浏览器上使用。
- 长轮询(Long Polling):客户端向服务器发送请求,服务器一直保持连接打开状态,直到有新数据可返回时才返回响应。这种方式可以减少网络开销,但是需要服务器支持。
- Server-Sent Events(SSE):服务器向客户端推送数据,客户端通过 EventSource API 接收数据。这种方式只能由服务器向客户端推送数据,不支持双向通信,但是可以实现实时更新数据,而且兼容性较好。
- 11.有用过git吧,那你说说git rebase和git merge的区别?
这个也没答好,果然git是一生的痛。 git merge我倒是知道是合并分支,这个rebase听说过,但是没用过。
答案是:git merge合并分支后,会提交一个新的分支上去,并且会有新的提交记录,也会保存原来两个分支的记录,而rebase则不会保存原来的分支记录,比较简洁,但是不利于管理。
到最后,面试官有点事情,就给了我两个题目做,2选1,因为不会react 就做了那个节流函数的
function throttle<T extends Function>(
func: T,
wait: number,
options?: { leading?: boolean; trailing?: boolean } // Bonus,可省略该参数的实现
): T;
让我根据这个ts类型,写出节流函数,也不难
function throttle (func, wait) {
let flag = true
if(!flag) return
return (...args) => {
flag = false
setTimeout(() => {
flag = true
func.call(this, args)
})
}
}
另外一个是react的题目, 请用 React hooks 重构下面的 React component
import React, { PureComponent } from 'react';
export default class FormInput extends PureComponent<{ id: number }> {
private text: string = '';
private onChange = e => {
this.text = e.target.value;
};
private submit = () => {
processInput(this.text);
};
public componentDidMount() {
fetchData(this.props.id);
}
public render() {
return (
<>
<input type="text" onChange={this.onChange} />
<button onClick={this.submit} />
</>
);
}
}
到这里一面就结束了,然后结束后hr说,一面过了,下面约的二面。
二面
因为上午问的比较基础,我就觉得下午肯定不好搞。下午两点半开始,持续半个小时。题型确实深入,有设计模式,ts装饰器,mvc在前端的应用,http状态码,js模块之间的依赖。
首先就说自我介绍环节,介绍完毕后开始技术拷打。
- 1.有了解过设计模式吗?
这里我说了几种,工厂模式,单例模式,观察者模式,发布订阅模式,责任链模式,策略模式。
对于工厂和策略还行,主要项目有用过,其他几种在框架中看到过,答的一般般。如果感兴趣,可以去其他博主那里看看。这里我就不细说了,我也得补补。
那你说说发布订阅模式和观察者模式区别和联系
这个我没答出来,难崩
答案:
发布订阅模式和观察者模式都是用于解决对象间的耦合问题,它们的本质都是基于事件的消息通信机制。它们的区别在于:
- 发布订阅模式中,发布者和订阅者之间没有直接的联系,发布者只管发布事件,而订阅者只管订阅事件,彼此之间不需要知道对方的存在;而观察者模式中,观察者和被观察者之间是直接联系的,观察者需要知道被观察者的存在,并且需要注册到被观察者的通知列表中。
- 在发布订阅模式中,发布者和订阅者之间通过事件通道进行通信,发布者发布事件后,所有订阅了该事件的订阅者都会收到通知;而在观察者模式中,被观察者通过调用观察者的方法进行通信,被观察者通知观察者的方式是直接调用观察者的方法。
- 发布订阅模式中,事件通道可以支持多级事件的传递,即一个事件可以触发另一个事件,形成事件的层级关系;而观察者模式中,被观察者只能通知观察者,不能形成事件的层级关系。
联系方面,发布订阅模式和观察者模式都是基于事件的消息通信机制,都可以实现对象间的解耦,提高系统的灵活性和可维护性。同时,它们也都可以支持异步编程,通过事件回调函数实现异步处理。
- 2.有了解过ts装饰器吗?
这个我在前端很少用,在后端nestjs中装饰器比较常见,就给面试官说了一下。
- 3.ts中的泛型说一下
答:ts中的泛型相当于一个占位符,不指明数据类型,当我们需要传递具体类型时,可以根据这个泛型推断出所有需要用到这个泛型的数据类型。
- 4.有了解MVC风格吗
答:这个因为我在nestjs中用的比较多,因为nestjs就是MVC风格的框架,也就module,view,controller。
那在前端有使用过吗?
这个又被问住了,在前端的框架中都是MVVM的视图,数据模型,对如何使用这个MVC真不了解。
5.有了解过react吧,说说vue和react的区别
这个答的不全面,我只说了部分,因为对react只是了解,我觉得差不多
答:写法上:vue是template写法,react是jsx写法 组件上: vue是定义单文件组件.vue文件, react是类组件以及函数组件,
相同点:都是利用了虚拟dom来处理,减少dom操作
6.有遇到过模块依赖循环的问题吗
这个直接不会了,因为对框架开发比较多,我遇到过vue3 hooks依赖的问题,这个js模块化的问题,没有遇到过。
2面的问题差不多就这些,深度还是有的,被面试官拷打了,总结经验,继续学习。
结束后,跟面试官闲聊了一会儿,问了他对我感觉咋样,他说和上午一面面试官聊了,感觉都不错。这两个面试官,给人的感觉还是挺和善的
总结
人总是在失败中吸取教训,这次面试不会的题,也是查缺补漏,每一次都要有提升,另外技术的深度和广度都很重要,希望大家没事看看技术博客, 多学习学习。另外英语也很重要,跟面试官聊天的过程中,也是有提到有没有用过chatGpt这种ai产品,遇到问题咋解决的,我是对博客社区比较青睐的,在社区查问题比较多。另外对于去外网学习也是很重要,多看看英文文档和纯英文视频也是不错的。
另外这家在武汉还在招前端开发实习,感兴趣的可以投递。
最后希望这份新鲜出炉的面试题能帮助到大家, 如果觉得不错,不妨点赞加收藏!😘
转载自:https://juejin.cn/post/7270822872707252276