likes
comments
collection
share

石墨文档两面后,我整理了这些面试题

作者站长头像
站长
· 阅读数 25

背景

本人开学大三,非科班,苦逼机械学生,从大一下自学前端,如今练习时长还不够两年半,临近开学 ,试着面了一下武汉的石墨文档。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垂直居中的方式

这个题答的还不错,这个还是要记住,面试了好几家都问过。

答:

  1. 子设置absolute,父relative 子元素left:50%, top:50%, 再用平移translate(-50%)
  2. flex布局,父元素设置flex justify-content:center align-items:center
  3. 利用line-height搭配vertical-align也可以实现

补充:如果会grid布局实现,也是可以的

  • 4.如何判断是不是一个数组?

答:js中有几种检查数据类型的方式,typeof intanceof Array.isArray(), Object.prototype.toString.call() 这几种。

  1. typeof只能检测出是一个对象,不能检测是不是数组。
  2. intanceof可以,判断是不是一个数组,返回布尔值。
  3. Array.isArray()也是返回一个布尔值。
  4. 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

    1. 实现动画的方式

答: 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不可以,没想到是可以的,当时答的一塌糊涂😭

答案:

  1. 轮询(Polling):客户端定时向服务器发送请求,服务器返回最新数据,客户端再进行更新。这种方式会造成不必要的网络开销,但是兼容性好,可以在所有浏览器上使用。
  2. 长轮询(Long Polling):客户端向服务器发送请求,服务器一直保持连接打开状态,直到有新数据可返回时才返回响应。这种方式可以减少网络开销,但是需要服务器支持。
  3. 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.有了解过设计模式吗?

这里我说了几种,工厂模式,单例模式,观察者模式,发布订阅模式,责任链模式,策略模式。

对于工厂和策略还行,主要项目有用过,其他几种在框架中看到过,答的一般般。如果感兴趣,可以去其他博主那里看看。这里我就不细说了,我也得补补。

那你说说发布订阅模式和观察者模式区别和联系

这个我没答出来,难崩

答案:

发布订阅模式和观察者模式都是用于解决对象间的耦合问题,它们的本质都是基于事件的消息通信机制。它们的区别在于:

  1. 发布订阅模式中,发布者和订阅者之间没有直接的联系,发布者只管发布事件,而订阅者只管订阅事件,彼此之间不需要知道对方的存在;而观察者模式中,观察者和被观察者之间是直接联系的,观察者需要知道被观察者的存在,并且需要注册到被观察者的通知列表中。
  2. 在发布订阅模式中,发布者和订阅者之间通过事件通道进行通信,发布者发布事件后,所有订阅了该事件的订阅者都会收到通知;而在观察者模式中,被观察者通过调用观察者的方法进行通信,被观察者通知观察者的方式是直接调用观察者的方法。
  3. 发布订阅模式中,事件通道可以支持多级事件的传递,即一个事件可以触发另一个事件,形成事件的层级关系;而观察者模式中,被观察者只能通知观察者,不能形成事件的层级关系。

联系方面,发布订阅模式和观察者模式都是基于事件的消息通信机制,都可以实现对象间的解耦,提高系统的灵活性和可维护性。同时,它们也都可以支持异步编程,通过事件回调函数实现异步处理。

  • 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产品,遇到问题咋解决的,我是对博客社区比较青睐的,在社区查问题比较多。另外对于去外网学习也是很重要,多看看英文文档和纯英文视频也是不错的。

另外这家在武汉还在招前端开发实习,感兴趣的可以投递。

最后希望这份新鲜出炉的面试题能帮助到大家, 如果觉得不错,不妨点赞加收藏!😘