前端面试

Posted by Qz on February 25, 2018

“Yeah It’s on. ”

前端工程师手册

前端面试基础

20道大厂面试题等你查收

并发和并行的区别

并发:concurrent

并行:parallel

并发在微观时间层面不是同时进行的,而并行是平行的意思,就是一直同时推进的。

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。并发的关键是你有处理多个任务的能力,不一定要同时。 并行的关键是你有同时处理多个任务的能力。所以我认为它们最关键的点就是:是否是『同时』。

编译器和解释器

编译器和解析器:V8如何执行一段JavaScript代码的

机器码所占用的空间远远超过了字节码,所以使用字节码可以减少系统的内存使用。


生成字节码之后,接下来就要进入执行阶段了。

通常,如果有一段第一次执行的字节码,解释器 Ignition 会逐条解释执行。在执行字节码的过程中,如果发现有热点代码(HotSpot),比如一段代码被重复执行多次,这种就称为热点代码,那么后台的编译器 TurboFan 就会把该段热点的字节码编译为高效的机器码,然后当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。

其实字节码配合解释器和编译器是最近一段时间很火的技术,比如 Java 和 Python 的虚拟机也都是基于这种技术实现的,我们把这种技术称为即时编译(JIT)

解释型语言和编译型语言的区别

http://c.biancheng.net/view/4136.html

  • 有的编程语言要求必须提前将所有源代码一次性转换成二进制指令,也就是生成一个可执行程序(Windows 下的 .exe),比如C语言、C++、Golang、Pascal(Delphi)、汇编等,这种编程语言称为编译型语言,使用的转换工具称为编译器。
  • 有的编程语言可以一边执行一边转换,需要哪些源代码就转换哪些源代码,不会生成可执行程序,比如 PythonJavaScriptPHP、Shell、MATLAB 等,这种编程语言称为解释型语言,使用的转换工具称为解释器。

JavaC# 是一种比较奇葩的存在,它们是半编译半解释型的语言,源代码需要先转换成一种中间文件(字节码文件),然后再将中间文件拿到虚拟机中执行。Java 引领了这种风潮,它的初衷是在跨平台的同时兼顾执行效率;C# 是后来的跟随者,但是 C# 一直止步于 Windows 平台,在其它平台鲜有作为。

编译型语言

编译型语言一般是不能跨平台的,也就是不能在不同的操作系统之间随意切换。

  • 可执行程序不能跨平台
  • 源代码不能跨平台

解释型语言

因为每次执行程序都需要重新转换源代码,所以解释型语言的执行效率天生就低于编译型语言,甚至存在数量级的差距。计算机的一些底层功能,或者关键算法,一般都使用 C/C++ 实现,只有在应用层面(比如网站开发、批处理、小工具等)才会使用解释型语言。

在运行解释型语言的时候,我们始终都需要源代码和解释器,所以说它无法脱离开发环境。

渲染机制类

DOCTYPE

DTD(document type definition,文档类型定义)是一系列的语法规则,用来定义XML或(X)HTML的文件类型。浏览器会使用它来判断文档类型,决定使用何种协议来解析,以及切换浏览器模式。

DOCTYPE是用来声明文档类型和DTD规范的,一个主要的用途便是文件的合法性检验。如果文件代码不合法,那么浏览器解析时便会出错。

HTML5 <!DOCTYPE html>

浏览器渲染过程

  1. 根据HTML结构生成DOM Tree
  2. 根据CSS生成CSSOM
  3. 将DOM和CSSOM整合形成RenderTree,同时进行Layout
  4. 根据RenderTree 开始渲染(Painting) => 光栅化 => 展示(Display)
  5. 遇到<script>时,会执行并阻塞渲染

浏览器页面最终渲染是通过GPU

光栅化

光栅化(rasterization)是将矢量图形转换为像素图形的过程。在计算机图形学中,图形需要经过光栅化才能在屏幕上显示或输出,因为计算机屏幕上显示的图像是由一系列像素点组成的,而矢量图形都是由图形语言表达的点线面,无法直接显示。光栅化就是将计算机计算的矢量图形转为像素图形的过程,并通过 GPU 渲染后就可以在屏幕上以图像的形式显示

浏览器页面渲染光栅化是指将网页中的各种元素(如文本、图片等)转换为最终的像素图像的过程。


Painting 和 Display 中间要进行一个 光栅化 阶段

Painting 绘制会交由光栅化做 3D 或 2D 转变为 2D 的过程,在这个过程中如果使用了 CSS3 的 transition 会开启 GPU 加速渲染,最后展示在屏幕上的像素点。

在渲染过程中,光栅化是发生在绘制操作之后的一个步骤。当页面需要显示在屏幕上时,绘制操作会生成一个绘制列表,其中包含了要显示在页面上的所有元素的细节。而光栅化过程则是将这个绘制列表转换为位图,也就是将各个元素绘制到像素网格上,使得最终可以在屏幕上显示出来。

在光栅化过程中,浏览器会根据屏幕分辨率等因素来确定图像的大小和质量。同时,光栅化也会考虑各种提升渲染性能和视觉效果的技术,如图像压缩、抗锯齿等。

CSS加载会造成阻塞吗

css加载会造成阻塞吗?

  • CSS不会阻塞DOM解析,但会阻塞DOM渲染。
  • CSS会阻塞JS执行,并不会阻塞JS文件下载

DOM 和 CSSOM通常是并行构建的,所以「CSS 加载不会阻塞 DOM 的解析」

然而由于Render Tree 是依赖DOM Tree和 CSSOM Tree的,所以它必须等到两者都加载完毕后,完成相应的构建,才开始渲染,因此,「CSS加载会阻塞DOM渲染」

加载css的时候,可能会修改下面DOM节点的样式,如果css加载不阻塞DOM树渲染的话,那么当css加载完之后,DOM树可能又得重新重绘或者回流了,这就造成了一些没有必要的损耗。所以我干脆就先把DOM树的结构先解析完,把可以做的工作做完,然后等你css加载完之后,在根据最终的样式来渲染DOM树,这种做法性能方面确实会比较好一点。

由于 JavaScript 是可操纵 DOM 和 css 样式 的,如果在修改这些元素属性同时渲染界面(即 JavaScript 线程和 UI 线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。

因此为了防止渲染出现不可预期的结果,浏览器设置 「GUI 渲染线程与 JavaScript 引擎为互斥」的关系。


  1. DOM解析和CSS解析是两个并行的进程,所以这也解释了为什么CSS加载不会阻塞DOM的解析。
  2. 然而,由于Render Tree是依赖于DOM Tree和CSSOM Tree的,所以他必须等待到CSSOM Tree构建完成,也就是CSS资源加载完成(或者CSS资源加载失败)后,才能开始渲染。因此,CSS加载是会阻塞Dom的渲染的。
  3. 由于js可能会操作之前的Dom节点和css样式,因此浏览器会维持html中css和js的顺序。因此,样式表会在后面的js执行前先加载执行完毕。所以css会阻塞后面js的执行。

SSR

SSR,服务器渲染。简单来说就是,服务器将每个要展示的页面都运行完成后,将整个相应流传送给浏览器,所有的运算在服务器端都已经完成,浏览器只需要解析 HTML 就行。

浏览器输入url到加载的过程

网页链接

1、解析URL:首先会对 URL 进行解析,分析所需要使用的传输协议和请求的资源的路径。
2、缓存判断:浏览器会判断所请求的资源是否在缓存里,如果请求的资源在缓存里并且没有失效,那么就直接使用,否则向服务器发起新的请求。
3、DNS解析: 下一步首先需要获取的是输入的 URL 中的域名的 IP 地址。
4、获取MAC地址: 当浏览器得到 IP 地址后,数据传输还需要知道目的主机 MAC 地址,因为应用层下发数据给传输层,TCP 协议会指定源端口号和目的端口号,然后下发给网络层。
5、TCP三次握手: 
6、HTTPS握手:
7、返回数据: 当页面请求发送到服务器端后,服务器端会返回一个 html 文件作为响应,浏览器接收到响应后,开始对 html 文件进行解析,开始页面的渲染过程。
8、页面渲染:

DNS查询

  • 浏览器缓存:浏览器会记录DNS一段时间,因此,只是第一个地方解析DNS请求;
  • 操作系统缓存:如果在浏览器缓存中不包含这个记录,则会使系统调用操作系统,获取操作系统的记录(保存最近的DNS查询缓存);
  • 路由器缓存:如果上述两个步骤均不能成功获取DNS记录,继续搜索路由器缓存;
  • ISP缓存:若上述均失败,继续向ISP搜索。

Internet Service Provider,互联网服务提供商

迭代查询的过程如下: . => com. => .exampl.com. => www.example.com. => IP adress

重排Reflow

DOM结构中的各个元素都有自己的盒子(模型),这些都需要浏览器根据各种样式来计算并根据计算结果将元素放到它应该出现的位置,这个过程称之为Reflow。

触发Reflow

当你增加,删除,修改DOM结点时,会导致Reflow或Repaint 当你移动DOM位置时,或者搞个动画的时候 当你修改CSS样式的时候 当你Resize窗口的时候(移动端没有这个问题),或者是滚动的时候 当你修改网页的默认字体时

重绘Repaint

当各种盒子的位置,大小以及其他属性,例如颜色、字体大小等都确定下来后,浏览器于是便把这些元素按照各自的特性绘制一遍,于是页面的内容出现了,这个过程称之为repaint。

触发Repaint

  • DOM改动
  • CSS改动

减少Repaint次数

利用DocumentFragment

DocumentFragment 接口表示一个没有父级文件的最小文档对象。它被当做一个轻量版的 Document 使用,用于存储已排好版的或尚未打理好格式的XML片段。最大的区别是因为DocumentFragment不是真实DOM树的一部分,它的变化不会引起DOM树的重新渲染的操作(reflow) ,且不会导致性能等问题。

所有的节点会被一次插入到文档中,而这个操作仅发生一个重渲染的操作,而不是每个节点分别被插入到文档中,因为后者会发生多次重渲染的操作。

可以使用document.createDocumentFragment 方法或者构造函数来创建一个空的 DocumentFragment.

渲染优化

  • CSS放前面,JS放后面
  • 懒加载
  • 减少DOM查询,对DOM查询做缓存
  • 减少DOM操作,多个操作尽量合并在一起执行
  • 事件节流
  • 尽早执行操作(如DOMContentLoaded)

合并DOM插入

    var listNode = document.getElementById('list');
    var frag = document.createDocumentFragment();
    var x, li;
    for (x = 0; x < 10; x++) {
        li = document.createElement('li');
        li.innerHTML = "List item" + x;
        frag.appendChild(li);
    }
    listNode.appendChild(frag);

事件节流

    var textarea = document.getElementById('text');
    var timeoutId;
    textarea.addEventListener('keyup', function () {
        if (timeoutId) {
            clearTimeout(timeoutId);
        }
        timeoutId = setTimeout(function () {
            //触发 change 事件
        }, 1000);
    })

尽早操作

    window.addEventListener('load', function () {
        // 页面的全部资源加载完才会执行,包括图片,视频等
    });

    document.addEventListener('DOMContentLoaded', function () {
        // DOM 渲染完成即可,此时图片,视频还可能没有加载完
    });

加载资源优化

  • 静态资源的压缩合并
  • 静态资源的缓存
  • 使用CND让资源加载更快
  • 使用SSR后端渲染,数据直接突入到HTML中

JavaScript动画比css动画更消耗性能

有几个原因可以解释为什么JavaScript动画会更消耗性能:

  1. JavaScript是一种解释性语言,运行时需要实时解析和执行代码。相比于使用硬件加速的CSS动画,JavaScript动画需要更多的计算和处理时间,导致性能消耗更大。
  2. JavaScript动画使用的是Web API中的requestAnimationFrame方法,该方法在每一帧渲染前都会执行一次回调函数,这使得每个动画帧都要执行一次JavaScript代码,导致性能消耗增加。
  3. 使用JavaScript进行动画时,必须手动处理动画的每一帧,包括计算位置、绘制图像等操作,这些都需要占用CPU资源,而硬件加速的CSS动画则可以由浏览器自动处理,减少了CPU的负担。
  4. JavaScript动画往往需要频繁地修改DOM元素的属性和样式,这会导致一次次的重渲染,消耗了大量的性能。相比之下,CSS动画使用CSS Transitions或CSS Animations属性来实现动画效果,浏览器可以利用硬件加速来优化渲染,性能更高。

因此,为了提高性能,如果可能的话,应该尽量使用CSS动画而不是JavaScript动画。

页面性能类

提升页面性能的方法有哪些?

  1. 资源压缩合并,减少HTTP请求
  2. 非核心代码异步加载(异步加载方式,异步加载原理)
  3. 利用浏览器缓存(缓存的分类,缓存的原理)
  4. 利用CDN
  5. 预解析DNS <meta http-equiv="x-dns-prefetch-control" content="on"> <link rel="dns-prefetch" href="//host_name_to_prefetch.com">

域名收敛

域名收敛的意思就是建议将静态资源只放在一个域名下面,而非发散情况下的多个域名下。 上面也说到了,域名发散可以突破浏览器的域名并发限制,那么为要反其道而行之呢?因为因地制宜,不同情况区别对待,域名发散是 PC 时代的产物,而现在进入移动互联网时代,通过无线设备访问网站,App的用户已占据了很大一部分比重,而域名收敛正是在这种情况下提出的。

首先要知道,使用一个 http 请求去请求一个资源时,会经历些什么。简单而言:

  1. DNS 域名解析 –>
  2. 发起 TCP 的 3 次握手 –>
  3. 建立 TCP 连接后发起 http 请求 –>
  4. 服务器响应 http 请求
  5. ……略

在这里第一步,也是关键的第一步 DNS 解析,在移动端的 http 请求耗时中,DNS 解析占据了大部分时间。

因为在增加域的同时,往往会给浏览器带来 DNS 解析的开销。所以在这种情况下,提出了域名收敛,减少域名数量可以降低 DNS 解析的成本。

js 延迟加载

  1. 动态脚本加载
  2. defer
  3. async
<script src="xxx.js" defer></script>		
<script src="xxx.js" async></script>

异步加载的区别:

  1. 给 js 脚本添加 defer属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。多个设置了 defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是这样。(defer 属性的脚本先于DOMContentLoaded事件执行)

  2. 给 js 脚本添加 async属性,这个属性会使脚本异步加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行 js脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async 属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次执行

Web Worker 和 Service Worker

Web Worker

Web Workers 可以将耗时任务拆解出去,降低主线程的压力,避免主线程无响应。

  1. 高效。
  2. 并行。

Web Worker使得js可以多线程

主线程与 Web Workers 之间的通信,并不是对象引用的传递,而是序列化/反序列化的过程

当对象非常庞大时,序列化和反序列化都会消耗大量计算资源,降低运行速度。


Service Worker API

https://developer.chrome.com/docs/workbox/service-worker-overview/

Service workers 本质上充当 Web 应用程序、浏览器与网络(可用时)之间的代理服务器。这个 API 旨在创建有效的离线体验,它会拦截网络请求并根据网络是否可用来采取适当的动作、更新来自服务器的的资源。它还提供入口以推送通知和访问后台同步 API。

Service worker运行在worker上下文,因此它不能访问DOM

相对于驱动应用的主JavaScript线程,它运行在其他线程中,所以不会造成阻塞。

出于安全考量,Service workers只能由HTTPS承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险。

Service workers也可以用来做这些事情:

  • 后台数据同步
  • 响应来自其它源的资源请求
  • 集中接收计算成本高的数据更新,比如地理位置和陀螺仪信息,这样多个页面就可以利用同一组数据
  • 在客户端进行CoffeeScript,LESS,CJS/AMD等模块编译和依赖管理(用于开发目的)
  • 后台服务钩子
  • 自定义模板用于特定URL模式
  • 性能增强,比如预取用户可能需要的资源,比如相册中的后面数张图片

错误监控类

前端错误的分类

  • 即时运行错误(代码错误)
  • 资源加载错误

即时运行错误的捕获方式:

  1. try…catch
  2. window.onerror

资源加载错误捕获方式:

  1. object.onerror
  2. performance.getEntries()
  3. Error事件捕获
Error事件捕获

window.addEventListener('error',function(e){
    console.log('捕获',e)
},false)  //设置false 因为只能在捕获阶段响应

延伸:跨域的js运行错误可以捕获吗,错误提示什么?

  1. 在script标签增加 crossorigin属性
  2. 设置js资源响应头Access-Control-Allow-Origin:*

上报错误的基本原理

  1. 采用Ajax通信方式上报
  2. 利用Image对象上报
利用Image对象上报


    (new Image()).src = 'http://baidu.com/test?error=tksjk...'
    // ?后面就可以添加错误信息了
    

算法类

逻辑题

检验毒药

1000 个瓶子中有一瓶毒药,一只老鼠吃到毒药一周之内会死,如果要在一周之内检测出有毒药的一瓶,问至少需要几只老鼠?

答案: 10只

根据2^10=1024,所以10个老鼠可以确定1000个瓶子具体哪个瓶子有毒。

具体实现跟3个老鼠确定8个瓶子原理一样。

000=0
001=1
010=2
011=3
100=4
101=5
110=6
111=7

一位表示一个老鼠,0-7表示8个瓶子。也就是分别将1、3、5、7号瓶子的药混起来给老鼠1吃,2、3、6、7号瓶子的药混起来给老鼠2吃,4、5、6、7号瓶子的药混起来给老鼠3吃,哪个老鼠死了,相应的位标为1。如老鼠1死了、老鼠2没死、老鼠3死了,那么就是101=5号瓶子有毒。 同样道理10个老鼠可以确定1000个瓶子

赛马

https://www.zhihu.com/question/19856916

25匹马,5个赛道,最快可以多少次找到最快的三匹马?

答案: 7次

tip:6轮可以得出最快的一匹。

首先分成5组A,B,C,D,E,赛5场

得到a1,b1,c1,d1,e1 (每一组中跑的最快的)

a1,b1,c1,d1,e1 在进行一场比赛,得出a1>b1>c1>d1>e1 (假设)

推出a1为第一的马

d1,e1不可能是前三的马,所以d1,e1不用参加最后一场

同时推理出可能是第二第三的马是:a2,a3,b1,b2,c1

然后a2,a3,b1,b2,c1再赛一场,其中前二的马即是第二,第三的马。

来回运水

【11】有一人有240公斤水,他想运往干旱地区赚钱。他每次最多携带60公斤,并且每前进一公里须耗水1公斤(均匀耗水)。假设水的价格在出发地为0,以后,与运输路程成正比,(即在10公里处为10元/公斤,在20公里处为20元/公斤......),又假设他必须安全返回,请问,他最多可赚多少钱?

1350

马驮石头

【12】现在共有100匹马跟100块石头,马分3种,大型马;中型马跟小型马。其中一匹大马一次可以驮3块石头,中型马可以驮2块,而小型马2头可以驮一块石头。问需要多少匹大马,中型马跟小型马?(问题的关键是刚好必须是用完100匹马)

12 20 48

排队买票

14有2n个人排队进电影院票价是50美分在这2n个人当中其中n个人只有50美分另外n个人有1美元纸票子)。愚蠢的电影院开始卖票时1分钱也没有
 有多少种排队方法 使得 每当一个拥有1美元买票时电影院都有50美分找钱
 
1美元=100美分
拥有1美元的人拥有的是纸币没法破成2个50美分 

体育竞赛

16有一种体育竞赛共含M个项目有运动员ABC参加在每一项目中第一,第二,第三名分别的XYZ分其中X,Y,Z为正整数且X>Y>Z最后A得22分B与C均得9分B在百米赛中取得第一求M的值并问在跳高中谁得第二名



M=5 C得第二名

因为ABC三人得分共40分,三名得分都为正整数且不等,所以前三名得分最少为6分,40=5*8=4*10=2*20=1*20,不难得出项目数只能是5.即M=5.

A得分为22分,共5项,所以每项第一名得分只能是5,故A应得4个第一名一个第二名.22=5*4 2,第二名得2分,又B百米得第一,9=5 1 1 1 1 所以跳高中只有C得第二名

B的5项共9分,其中百米第一5分,其它4项全是1分,9=5 1=1 1 1.即B除百米第一外全是第三,跳高第二必定是C所得

女孩概率

【22】一个家庭有两个小孩,其中有一个是女孩,问另一个也是女孩的概率
(假定生男生女的概率一样) 

正常: 男男 男女 女男 女女
其中有一个是女孩: 男女 女男 女女
另一个也是女孩的概率: 1/3

砝码称盐

【24】有7克、2克砝码各一个,天平一只,如何只用这些物品三次将140克的盐分成50、90克各一份? 


1. 天平一边放7 2=9克砝码,另一边放9克盐。
2. 天平一边放7克砝码和刚才得到的9克盐,另一边放16克盐。
3. 天平一边放刚才得到的16克盐和再刚才得到的9克盐,另一边放25克盐。

找出坏鸡蛋

26话说有十二个鸡蛋有一个是坏的重量与其余鸡蛋不同),现要求用天平称三次称出哪个鸡蛋是坏的 

及格人数

27100个人回答五道试题有81人答对第一题91人答对第二题85人答对第三题79人答对第四题74人答对第五题答对三道题或三道题以上的人算及格 那么在这100人中至少有 人及格

下一行输出

【29】 
1 
1 1 
2 1 
1 2 1 1 
1 1 1 2 2 1 
下一行是什么?


下行是对上一行的解释 所以新的应该是3个1 2个2 1个1 :312211

选硬币

【41】有23枚硬币在桌上,10枚正面朝上。假设别人蒙住你的眼睛,而你的手又摸不出硬币的 
反正面。让你用最好的方法把这些硬币分成两堆,每堆正面朝上的硬币个数相同。 

汽车概率

【10】某城市发生了一起汽车撞人逃跑事件
该城市只有两种颜色的车,蓝色15% 绿色85%
事发时有一个人在现场看见了
他指证是蓝车
但是根据专家在现场分析,当时那种条件能看正确的可能性是80%
那么,肇事的车是蓝车的概率到底是多少? 

罐子选球

【61】你有两个罐子,50个红色弹球,50个蓝色弹球,随机选出一个罐子,随机选取出一个弹球放入罐子,怎么给红色弹球最大的选中机会?在你的计划中,得到红球的准确几率是多少?

三面/四面

  • 业务能力
  • 团队协作能力
  • 事务推动能力
  • 带人能力
  • 其他能力

业务能力

  • 做过什么业务?
  • 负责的业务有什么业绩?
  • 使用了什么技术方案?
  • 突破了什么技术难点?
  • 遇到了什么问题?
  • 最大收获是什么?

终面(hr面)

  • 乐观积极
  • 主动沟通
  • 逻辑顺畅
  • 上进有责任心
  • 有主张,做事果断

谈薪

最重要的,千万不要把自己,和HR,当成对立的两方。

每一次的跳槽、升职、加薪,都是以前一份工作为重要参考标准。

薪酬不是一个简单的数字,而是一个计算公式。

薪酬=固定工资+绩效+奖金+补贴+其他福利

谈薪时,公积金的缴纳基数和比例建议明确一下。

话题

  1. 职业竞争力
  2. 职业规划

职业竞争力

为什么这个岗位要给你?

  1. 业务能力
  2. 思考能力(对一件事可以从不同的角度去思考,找到最优解)
  3. 学习能力(不断学习新的业务和技术,沉淀,总结)
  4. 无上限的付出(对于无法解决的问题可以加班)

职业规划

  1. 目标是什么(在业务上成为专家,在技术上成为大牛)
  2. 近阶段的目标(不断的学习积累各方面的经验,以学习为主)
  3. 长期目标(做几件很有价值的事情,如开源作品,技术框架)
  4. 方式方法(先完成业务上的主要问题,做到极致,然后逐步向目标靠拢)

适当赞美hr,希望多得到公司的资源,定期举办分享会…

面试紧张

首先,我们为什么紧张,最原始最根本的一个原因,是来自于我们对未知的恐惧,在面试上的这种未知,最大的是你不知道你会不会通过,细分的点是你不知道面试官是个怎样的人,你不知道他会问你什么问题,你不知道你的回答会不会让他喜欢,你不知道他会不会针对你的回答问出可能更难回答的问题

  • 基本大家都会紧张。

  • 列出所有可能让你紧张的压力场景。

  • 全部提前预演一遍。
  • 准备充分,有备而来
  • 心理暗示

  • 逐个排除风险点。
  • 抓住每一次面试机会,锻炼自己的临场发挥能力

面试注意点

  • 1、回答问题不要过于着急,一定要耐心等待面试官把问题说完
  • 2、回答问题要有逻辑、干练简洁
  • 3、如果面试官打断你说话,此时一定要谨慎回答,因为很有可能你回答过于繁琐且他对你当下的回答不满意

把面试当作一场交流,而不是一场考试

心理上的,要意识到这是个双向考察的机会。一般面试的时候,求职者出于略弱势的地位,这时更要提醒自己,这个机会未必是适合自己的。有时候强扭的瓜不甜。这是本人亲身体会。所以,不要对这个机会过于执着,战略上藐视。


每场面试后的分析也至关重要

而是要对每一次面试进行全过程的复盘反思,到底自己为什么在紧张,太过重视这个机会?会在实战中审视自身得失,每次提高一点点,就已经很棒啦。

准备简历

反例:

罗列大量技术工具工具:Ruby,Java,jQuery,React,Git,Jira等

提升:

给我们的项目体检一系列的移动客户端的API,如来记录各个国家地区的爆米花热狗的价格。通过etags实现缓存,来减少移动设备在消费 API时 60%的API响应时间。领导团队升级到 Rails5。在此之前,实施和验证几个 Rails4 的安全补丁。


反例:『优秀的沟通技巧』

在简历上仅仅写出『拥有优秀的沟通技巧』恰恰体现了你不咋地的沟通能力。

提升:

主导和对齐一个正在进展中的平台优化的例会(用来定期偿还我们之前留下的技术债)。我给例会中引入了一套代码准则来避免直接指责同事和确保所有团队成员都能有机会说出和提议对目前技术债的解决方案。


反例:

模糊不清的导师工作

提升:

每周会花费5个小时左右去指导我手下计算机科学的本科实习生加速相关最佳实践在他最后一个学期里。最终让他在毕业后能够以全职正式员工身份入职。

怎么看待分享和写技术博客

我觉得分享更像是一种工具一种方法,帮你回过头来梳理你最近做的事情,沉淀的东西,分享和写文章,往往作者和分享人本身受益是最大的,听者能吸收进去 30% 你的分享就已经算很成功了。

问题背后到底在问什么

https://juejin.cn/post/6922623997980966926?utm_source=gold_browser_extension

询问过去的工作中碰到过的一个项目或者解决过的问题

面试官的角度:

这类问题的主要目的是通过一个具体的案例考察候选人对于自己业务的熟悉和理解程度,以及碰到业务问题的时候是如何面对问题的。需要注意一定要尽可能按照 STAR(Situation, Task, Action, Result) 的技巧来组织对话,了解问题背后的信息,候选人本人的贡献,以及反映出来的能力。

对于候选人的回答,需要判断其语言的信息量,如果形容词比较多,比如做得很好,客户反应不错之类的回答,应该要求其给出明确的描述,到底好在什么地方,有没有明确的内容和数据,而不是含糊的形容一下。通常如果一个技术人员在得到明确提示情况下还是不能切换到陈述事实的方式,那么我们基本上可以认为这个人对于平常的工作是缺乏理性思考的。

辞职信

尊敬的领导:

  感谢领导对我的信任,给我机会来公司工作。其间我认识了不少朋友,学到不少新的知识,也有过很多愉快的时间,但是我因个人原因,特辞去现在的保安工作,望公司领导能够谅解。

  希望公司领导能理解,并批准我的辞职请求。 祝公司前程似锦,生意蒸蒸日上。

  此致

敬礼!

   辞职人:

   时间:

礼貌地拒绝 offer

https://www.zhihu.com/question/19905845

你好 非常感谢贵公司对我的认可。但是由于个人的一些原因,我思虑良久,选择了另外一个可能更适合自己的offer,所以不能接受贵公司的offer。给贵公司带来的不便还请谅解,希望贵公司能找到更加适合这个职位的人选。谢谢。

最大的缺点

https://juejin.cn/post/7120805355042373662

  • 面试官认为不是弱点的弱点

  • 格局变相大
  • 如何去解决弱点

你可以挑一个与你目前所在层次相隔较远的能力缺陷来说。

比如你以后想要做管理层,你可以说:你x年的职业规划是做好什么事情,然后在x年后想要往管理层方向去走,虽然我现在对开发和业务等基本功没有什么问题,但是呢对于管理方面的了解等不够深刻,这也是我以后要去学习的。

总结

JD描述(job description) 对于社招一定要看,对于校招可以忽略

简历 对照JD改写出相吻的简历,对于未掌握的技术栈快速复习理解。

自我介绍 一定要打草稿,展示什么优势,描述什么项目,切忌临场发挥

不要一味低头做事,多思考,学会沟通。

校招看潜力,社招看价值

其他

什么是前端工程化

所有能降低成本,并且能提高效率的事情总称为工程化。

在前端项目中能够减少重复工作、扩展 javascript\html\css 本身的语言能力、解决功能复用和变更问题、解决开发和产品环境差异问题、任何时间任何地点生成可部署的软件、解决发布流程问题,都属于前端工程化。

什么是持续集成

持续集成是前端工程化中的一部分,是一种软件开发实践,即团队开发成员经常集成他们的工作,通常每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括自动化编译,自动化测试,自动化发布)来验证项目代码,从而尽早地发现错误。

Web项目持续集成怎么做

Web项目的持续集成方案选择比较多,并且相对成熟,这里介绍一下 gitlab-ci 持续集成方案。

这种方式的原理就是为项目在自己的 linux 服务器安装并注册 gitlab-runner ,注册会有一个 token ,服务器上运行 gitlab-runner 后, runner 会轮询的发送带 token 的 http 请求给 gitlab ,如果 gitlab 有任务了,(一般是 git push ),那么会把任务信息返回给 runner ,然后 runner 就开始调用注册时选的 Executor 来执行项目根目录下的配置文件 .gitlab-ci.yml ,执行后把结果反馈给 gitlab 。

此时我们可以编写 .gitlab-ci.yml 脚本,比如设定当 test 分支发生 push 时,自动运行测试用例、自动构建代码、自动将代码更新到测试人员在测的环境等任何你想在提测时需要做的事情。当 merge 到 master 时,自动更新线上代码完成上线等各种你想在上线时做的事情。

这里只要考虑的足够全面,那么之后的项目开发你只需要 push 到对应的分支,gitlab-runner 会自动完成你想做的所有构建、提测、上线操作。减少重复工作,这就是持续集成的意义所在。

npm install 原理

https://juejin.cn/post/6844904022080667661#heading-49

一道export import 题目

来自:微信小程序 前端面试星球 Day214

写出下面代码的输出结果:

// counter.js
let counter = 10
const add = () => {
  console.log(conter)
}
export {
  counter,add
}
// index.js
add()
import {conter,add} from './counter'
counter += 1 
console.log(counter)
// 答案:
10 报错

解析:

  • 引入模块是只读的,不能修改。并且import命令具有提升效果
  • import是静态执行,所以不能使用表达式和变量
  • import语句是Singleton模式

如何实现选中复制的功能

它一般可以使用第三方库 clipboard.js 来实现,源码很简单,可以读一读

主要有两个要点

  1. 选中: Selection API
  2. 复制: document.execCommand

Selection API

const selection = window.getSelection();
const range = document.createRange();

range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);

selectedText = selection.toString();

复制: execCommand

document.execCommand('copy')

大文件快速上传

怎么实现大文件快速上传?

  • 首先是选择上传的文件资源,接着就可以得到对应的文件对象 File,而 File.prototype.slice 方法可以实现资源的分块
  • 由于前端会将资源分块,然后单独发送请求,也就是说,原来1个文件对应 1 个上传请求,现在可能会变成1个文件对应 n 个上传请求,基于 Promise.allSettled 将这多个接口整合,上传完成在发送一个合并的请求,通知服务端进行合并。
  • 后端合并时可通过 nodejs 中的读写流(readStream/writeStream),将所有切片的流通过管道(pipe)输入最终文件的流中。

在发送请求资源时,前端会定好每个文件对应的序号,并将当前分块、序号以及文件 hash 等信息一起发送给服务端,服务端在进行合并时,通过序号进行依次合并即可。

注意不要使用Promise.all 这样万一reject 会影响后面的任务

// 获取文件分块
const getFileChunk = (file, chunkSize = DefualtChunkSize) => {
  return new Promise((resovle) => {
    let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
      chunks = Math.ceil(file.size / chunkSize),
      currentChunk = 0,
      spark = new SparkMD5.ArrayBuffer(),
      fileReader = new FileReader();

    fileReader.onload = function (e) {
      console.log('read chunk nr', currentChunk + 1, 'of');

      const chunk = e.target.result;
      spark.append(chunk);
      currentChunk++;

      if (currentChunk < chunks) {
        loadNext();
      } else {
        let fileHash = spark.end();
        console.info('finished computed hash', fileHash);
        resovle({ fileHash });
      }
    };

    fileReader.onerror = function () {
      console.warn('oops, something went wrong.');
    };

    function loadNext() {
      let start = currentChunk * chunkSize,
        end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
      let chunk = blobSlice.call(file, start, end);
      fileChunkList.value.push({ chunk, size: chunk.size, name: currFile.value.name });
      fileReader.readAsArrayBuffer(chunk);
    }

    loadNext();
  });
}

秒传

其实所谓的秒传就是不用传,在正式发起上传请求时,先发起一个检查请求,这个请求会携带对应的文件 hash 给服务端,服务端负责查找是否存在一模一样的文件 hash,如果存在此时直接复用这个文件资源即可,不需要前端在发起额外的上传请求.

断点续传

断点续传其实就是让请求可中断,然后在接着上次中断的位置继续发送,此时要保存每个请求的实例对象,以便后期取消对应请求,并将取消的请求保存或者记录原始分块列表取消位置信息等,以便后期重新发起请求.

取消请求的几种方式

  • 如果使用原生 XHR 可使用 (new XMLHttpRequest()).abort() 取消请求
  • 如果使用 axios 可使用 new CancelToken(function (cancel) {}) 取消请求
  • 如果使用 fetch 可使用 (new AbortController()).abort() 取消请求

扫码登录

进程通信

进程之间有哪些通信方式

管道:

mkfifo  test
echo "this is a pipe" > test   // 写数据
cat < test  // 读数据

消息队列:

例如 a 进程要给 b 进程发送消息,只需要把消息放在对应的消息队列里就行了,b 进程需要的时候再去对应的 消息队列里取出来

共享内存:

系统加载一个进程的时候,分配给进程的内存并不是实际物理内存,而是虚拟内存空间。那么我们可以让两个进程各自拿出一块虚拟地址空间来,然后映射到相同的物理内存中,这样,两个进程虽然有着独立的虚拟内存空间,但有一部分却是映射到相同的物理内存,这就完成了内存共享机制了。

信号量:

信号量的本质就是一个计数器,用来实现进程之间的互斥与同步

例如信号量的初始值是 1,然后 a 进程来访问内存1的时候,我们就把信号量的值设为 0,然后进程b 也要来访问内存1的时候,看到信号量的值为 0 就知道已经有进程在访问内存1了,这个时候进程 b 就会访问不了内存1。所以说,信号量也是进程之间的一种通信方式。

Socket:

那两个相隔几千里的进程能够进行通信吗?

这个时候 Socket 这家伙就派上用场了

Socket通信原理

Socket通信原理

Socket通信则是在双方建立连接后,可以直接进行数据的传输,在连接时可实现信息的主动推送,而不需要每次由客户端向服务器发送请求

socket又称套接字,在程序内部提供了与外界通信的端口,即端口通信。

通过建立socket连接,可为通信双方的数据传输提供通道。socket的主要特点数据丢失率低使用简单且易于移植

简单来说,Socket提供了程序内部与外界通信的端口并为通信双方提供数据传输通道

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

web rtc 的理解