前端面试笔记(更新于2021-5-07)

面试血泪史

不要问我面的是否是架构师。我只是面的低级前端。总结不易点个赞吧。html

JS

1. 包装类跟普通类有什么区别?new String() 和String()的区别前端

答::js 提供了3个包装类 分别是 new String()new Number()new Boolean()。因为基础类型不能添加属性和方法,js的包装类的做用是将基础类型包装成一个对象,这样就能够有属性和方法。node

tips:当咱们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转换为对象,而后在调用对象的属性和方法;调用完之后,在将其转换为基本数据类型。react

2. promise.then 是怎么实现链式调用的webpack

: 经过从新return 一个new Promise 来实现链式调用nginx

3. 多调用几回bind 好比bind a bind b 最后this指向谁 为啥web

答: 永远指向第一次调用bind时传入的上下文,由于bind以后的调用都是绑定在这个上下文上。面试

4. v8引擎回收机制简述算法

答: v8垃圾回收主要经过两个策略:json

  • 标记清除

  • 引用计数

    标记清除是js最经常使用的垃圾回收机制。垃圾回收程序运行的时候,会标记内存中存储的全部变量。而后,它会将全部在上下文中的变量,以及被在上下文中的变量引用的变量的标记去掉。在此以后再被加上标记的变量就是待删除的了,缘由是任何在上下文中的变量都访问不到它们了。随后垃圾回收程序作一次内存清理,销毁带标记的全部值并收回它们的内存。

    引用计数是对每一个值都记录它被引用的次数。声明变量并给它赋一个引用值时,这个值的引用数为 1。若是同一个值又被赋给另外一个变量,那么引用数加 1。相似地,若是保存对该值引用的变量被其余值给覆盖了,那么引用数减 1。当一个值的引用数为 0 时,就说明没办法再访问到这个值了,所以能够安全地收回其内存了。垃圾回收程序下次运行的时候就会释放引用数为 0 的值的内存。(以上摘自js红宝书第四版)

5. v8回收算法运行时会阻塞js吗?为何

答: 会阻塞。

6. 怎么优化垃圾回收机制

答: www.cnblogs.com/chengxs/p/1… 总结就是多用新生代算法

7. 做用域链简述。怎么能获取函数内部变量?

答: 做用域链就是变量向上查找过程。能够经过函数内部return 一个携带函数内部变量的闭包使得外部能够访问函数内部的变量

8. 闭包简述,怎么避免内存泄漏

答: 不管什么时候声明新函数并将其赋值给变量,都要存储函数定义和闭包,闭包包含在函数建立时做用域中的全部变量,相似于背包,函数定义附带一个小背包,他的包中存储了函数建立时做用域中的全部变量。及时将指针指向null能够避免内存泄漏。

9. class 类能够枚举吗?类 instanceof Function 输出什么?

答: 类的内部全部定义的方法,都是不可枚举的类的数据类型就是函数,类自己就指向构造函数。 代码以下:

class Point {
  constructor(x, y) {
    // ...
  }

  toString() {
    // ...
  }
}

Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]
复制代码
class Fn{}
Fn instanceof Function // true

const a = new Fn()
a instanceof Function // false
复制代码

webpack

1. webpack 是怎么实现分模块打包的?

答: 能够经过splitChunks 实现。

webpack 中如下三种常见的代码分割方式:

  • 入口起点:使用 entry 配置手动地分离代码。
  • 动态导入:经过模块的内联函数调用来分离代码。
  • 防止重复:使用 splitChunks 去重和分离 chunk。 第一种方式,很简单,只须要在 entry 里配置多个入口便可。

splitChunks 代码拆分

splitChunks: {
    // 表示选择哪些 chunks 进行分割,可选值有:async,initial和all
    chunks: "async",
    // 表示新分离出的chunk必须大于等于minSize,默认为30000,约30kb。
    minSize: 30000,
    // 表示一个模块至少应被minChunks个chunk所包含才能分割。默认为1。
    minChunks: 1,
    // 表示按需加载文件时,并行请求的最大数目。默认为5。
    maxAsyncRequests: 5,
    // 表示加载入口文件时,并行请求的最大数目。默认为3。
    maxInitialRequests: 3,
    // 表示拆分出的chunk的名称链接符。默认为~。如chunk~vendors.js
    automaticNameDelimiter: '~',
    // 设置chunk的文件名。默认为true。当为true时,splitChunks基于chunk和cacheGroups的key自动命名。
    name: true,
    // cacheGroups 下能够能够配置多个组,每一个组根据test设置条件,符合test条件的模块,就分配到该组。
    // 模块能够被多个组引用,但最终会根据priority来决定打包到哪一个组中。默认将全部来自 
    // node_modules目录的模块打包至vendors组,将两个以上的chunk所共享的模块打包至default组。
    cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10 // 缓存组优先级
        },
        // 
    default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true  // 可设置是否重用该chunk
        }
    }
}

复制代码

经过 cacheGroups,咱们能够定义自定义 chunk 组,经过 test 条件对模块进行过滤,符合条件的模块分配到相同的组。

2. webpack4 的tree-shaking是什么?怎么实现的?在什么状况下会失效?为何?

答: tree-shaking本质是webpack打包时用来舍弃无用的代码。

工做原理: 在ES6之前,咱们可使用CommonJS引入模块:require(),这种引入是动态的,也意味着咱们能够基于条件来导入须要的代码

let module
if(true){
    module = require('a')
}else{
    module = require('b')
}
复制代码

CommonJS规范没法肯定在实际运行前须要或者不须要某些模块,因此CommonJS不适合tree-shaking机制

ES6的import语法能够完美使用tree shaking,由于能够在代码不运行的状况下就能分析出不须要的代码。

由于tree shaking只能在静态modules下工做。ECMAScript 6 模块加载是静态的,所以整个依赖树能够被静态地推导出解析语法树。

side effects是指那些当import的时候会执行一些动做,可是不必定会有任何export

tree shaking 不能自动的识别哪些代码属于side effects,所以手动指定这些代码显得很是重要。若是全部代码都不包含反作用,咱们就能够简单地将该属性标记为false,来告知 webpack,它能够安全地删除未用到的export导出。

总结: ES6 Module引入进行静态分析,故而编译的时候正确判断到底加载了那些模块。再判断那些模块和变量未被使用或者引用,进而删除对应代码。

另外,webpack中能够在项目package.json文件中,添加一个 “sideEffects” 属性,手动指定由反作用的脚本。

3. env 知道吗?是用来干什么的?项目须要单独安装吗?为何?

env是nodejs里内置的一个对象,能够利用process.env拿到当前项目运行环境的信息。不须要独立安装,由于是nodejs的内置对象。

4. import 和 require 的区别

答:

  1. CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

  2. CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

  3. CommonJs 是单个值导出,ES6 Module能够导出多个

  4. CommonJs 是动态语法能够写在判断里,ES6 Module 静态语法只能写在顶层

  5. CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined

5. 知道什么是静态分析吗?

答: es modules能够在代码不运行的状况下对代码进行分析,能够知道哪些模块有没有被使用。

6. webpack babel是如何工做的?

答:

    1. 词法解析 。将字符串形式的代码转换为Tokens(令牌),Tokens 能够视做是一些语法片断组成的数组。
    1. 语法解析。把Tokens转换为抽象语法树AST
    1. 转换阶段。会对 AST 进行遍历,在这个过程当中对节点进行增删查改。Babel 全部插件都是在这个阶段工做, 好比语法转换、代码压缩。
    1. 输出阶段。将通过转换的AST经过babel-generator再转换成js代码,过程就是深度优先遍历整个AST,而后构建能够表示转换后代码的字符串。同时这个阶段还会生成Source Map

7. webpack plugins的执行时机?

答: 加载文件完成后,输出文件前,不一样的plugins有不一样的执行时机。

node

1. koa 源码了解过,是怎么实现的?

答: koa经过对http模块的封装,在内部实现了一个context上下文的概念,把res跟req都放在ctx上面,而且对req和res进行优雅的setter/getter处理,调用方式更简单。

洋葱模型经过将中间件数组里的异步方法经过dispatch去递归调用,因为在app.use中去调用next方法时去调用下一个中间件。

洋葱模型实现伪代码

function compose(middlewares){
    return function(){
        return dispatch(0)
        function dispatch(i){
            let fn = middlewares[i]
            if(!fn) return Promise.resolve()
            return Promise.resolve(fn(function next(){
                // promise 完成以后在执行下一个
                return dispatch(i+1)
            }))
        }
    }
}

复制代码

2. koa 洋葱模型

答: 见上

3. cdn加速是怎么作的?

答: 简单的说就是缓存+负载均衡

  1. 浏览器向域名解析服务器发出解析请求,因为CDN 对域名解析过程进行了调整,因此用户端通常获得的是该域名对应的 CNAME 记录,此时浏览器须要再次对得到的 CNAME 域名进行解析才能获得缓存服务器实际的IP 地址。 注:在此过程当中,全局负载均衡DNS 解析服务器会根据用户端的源IP 地址,如地理位置(北京仍是上海)、接入网类型(电信仍是网通)将用户的访问请求定位到离用户路由最短、位置最近、负载最轻的Cache 节点(缓存服务器)上,实现就近定位。定位优先原则可按位置、可按路由、也可按负载等。
  2. 再次解析后浏览器获得该域名CDN 缓存服务器的实际IP 地址,向缓存服务器发出访问请求。
  3. 缓存服务器根据浏览器提供的域名,经过Cache 内部专用DNS 解析获得此域名源服务器的真实IP 地址,再由缓存服务器向此真实IP 地址提交访问请求。
  4. 缓存服务器从真实IP 地址获得内容后,一方面在本地进行保存,以备之后使用,同时把获得的数据发送到客户端浏览器,完成访问的响应过程。

4. cdn源服务器文件修改,负载均衡还有做用吗?

答: cdn通常用来存静态资源。拿网站来讲,当用户访问网站时静态资源从cdn加载。cdn向源服务器请求资源并缓存,这个请求过程是周期性的,自动的,称为回源。 当你更新了一个文件,如今正巧还没到cdn自动更新的时候,若是想让用户立刻看到新的就得手动刷cdn,通常cdn控制台都有此选项。

5. 负载均衡有哪些模式

  1. 轮询(默认) 每一个请求按时间顺序逐一分配到不一样的后端服务器,若是后端服务器down掉,能自动剔除。
  2. weight权重 指定轮询概率,weight和访问比率成正比,用于后端服务器性能不均的状况。权重越高,在被访问的几率越大。
  3. ip_hash 若是客户已经访问了某个服务器,当用户再次访问时,会将该请求经过哈希算法,自动定位到该服务器。
  4. fair(第三方) 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
  5. url_hash(第三方) 按访问url的hash结果来分配请求,使每一个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

6. 脱离了nginx怎么配置负载均衡

答: Redis,Zookeeper (ps:nt问题)

7. a服务器node服务怎么访问b服务器的脚本

答: (大佬跟我说的)用RPC RPC是指远程过程调用,也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,因为不在一个内存空间,不能直接调用,须要经过网络来表达调用的语义和传达调用的数据。

8. 通过网关转发下websocket还能够一直保持心跳吗

答: 不能

9. 前端页面设置强缓存,可是有东西更新了。怎么保证用户的页面是最新的

答:

  1. 静态资源设置协商缓存。
  2. 在静态资源后面配置版本号,时间戳等。
  3. (但愿你们能够帮忙提供一下更好的方案)

10. node 事件循环

答:

node中的微观,宏观任务

  1. 常见的 macro-task 好比:setTimeout、setInterval、 setImmediate、script(总体代码)、 I/O 操做等。
  2. 常见的 micro-task 好比: process.nextTick、new Promise().then(回调)等。

microtask 在事件循环的各个阶段之间执行。

  • timers 阶段:这个阶段执行timer(setTimeout、setInterval)的回调
  • I/O callbacks 阶段:处理一些上一轮循环中的少数未执行的 I/O 回调
  • idle, prepare 阶段:仅node内部使用
  • poll 阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close callbacks 阶段:执行 socket 的 close 事件回调
  1. timers阶段

timers 阶段会执行 setTimeout 和 setInterval 回调,而且是由 poll 阶段控制的。 一样,在 Node 中定时器指定的时间也不是准确时间,只能是尽快执行。

  1. callbacks阶段

此阶段执行某些系统操做的回调,例如 TCP 错误。

  1. 轮询 poll 阶段
  • 计算应该阻塞并 I/O 轮询的时间
  • 处理轮询队列 (poll queue) 中的事件

当事件循环进入轮询 (poll) 阶段而且没有任何计时器调度 (timers scheduled) 时,将发生如下两种状况之一:

  • 若是轮询队列 (poll queue) 不为空,则事件循环将遍历其回调队列,使其同步执行,直到队列用尽或达到与系统相关的硬限制为止

  • 若是轮询队列为空:若是已经过 setImmediate 调度了脚本,则事件循环将结束轮询 poll 阶段,并继续执行 check 阶段以执行那些调度的脚本。若是脚本并无 setImmediate 设置回调,则事件循环将等待 poll 队列中的回调,而后当即执行它们。

  1. 检查阶段 check

此阶段容许在轮询 poll 阶段完成后当即执行回调。 若是轮询 poll 阶段处于空闲,而且脚本已使用 setImmediate 进入 check 队列,则事件循环可能会进入 check 阶段,而不是在 poll 阶段等待。

  1. close callbacks 阶段

setImmediate vs setTimeout

setImmediatesetTimeout 类似,可是根据调用时间的不一样,它们的行为也不一样

  • setImmediate 设计为在当前轮询 poll 阶段完成后执行脚本。
  • setTimeout 计划在以毫秒为单位的最小阈值过去以后运行脚本。

11. node在require的时候发生了哪些事

答:

  1. 拿到要加载的文件绝对路径。没有后缀的尝试添加后缀
  2. 尝试从缓存中读取导出内容。若是缓存有,返回缓存内容。没有,下一步处理
  3. 新建一个模块实例,并输入进缓存对象
  4. 尝试加载模块
  5. 根据文件类型,分类处理
  6. 若是是js文件,读取到文件内容,拼接自执行函数文本,用vm模块建立沙箱实例加载函数文本,得到导出内容,返回内容
  7. 若是是json文件,读取到文件内容,用JSON.parse 函数转成js对象,返回内容
  8. 获取导出返回值。

http

1. http 和 https的区别

答: HTTPS就是将HTTP运行在TLS/SSL的加密安全措施下。

  • https须要申请CA证书
  • https更安全。运用了加密手段
  • https端口443 http是80

2. udp和tcp的区别

答: 见个人另外一篇文章TCP/IP

3. http3.0是基于udp的,为何udp面向无链接还会选择udp?

答: 由于udp高效。并且在应用层解决了udp的不可靠性问题。

4. http3.0怎么解决udp的丢包问题?

答: http3不只仅只是简单将传输协议替换成了 UDP。还基于 UDP 协议在「应用层」实现了 QUIC 协议。它具备相似 TCP 的链接管理、拥塞窗口、流量控制的网络特性,至关于将不可靠传输的 UDP 协议变成“可靠”的了,因此不用担忧数据包丢失的问题。并且, QUIC 协议会保证数据包的可靠性,每一个数据包都有一个序号惟一标识。当某个流中的一个数据包丢失了,即便该流的其余数据包到达了,数据也没法被 HTTP/3 读取,直到 QUIC 重传丢失的报文,数据才会交给 HTTP/3。

5. tcp除了你刚刚说的窗口控制,还有哪些控制?

答: 重发控制,流控制,拥塞控制

6. tcp重发机制是基于哪一个时间节点

答: 引入两个概念:

  • RTT(Round Trip Time):往返时延,也就是数据包从发出去到收到对应 ACK 的时间。RTT 是针对链接的,每个链接都有各自独立的 RTT。
  • RTO(Retransmission Time Out):重传超时,也就是前面说的超时时间。

我通常认为是两倍的RTT。

React

react 面试考点见个人react面试考点文章React面试

相关文章
相关标签/搜索