谈面试前端工程师

谈面试前端工程师

  • 打战需要周全的准备,而找一份年薪几十万的工作对于个人来说不亚于一场大战
  • 有一天,你若需要招人,则需要在极短的时间内从各方面考核对方是否合适
  • 通过面试可以推动自己主动了解行业新技术,尤其是长期呆在一家技术不那么好的公司
  • 面试的内容数不胜数(亦或千奇百怪),面试官和面试者的背景也不尽相同,或许我们只能尽力而为。将每次面试当成一次修炼,好好享受

以下是近期朋友去面试前端工程师所遇到的一些问题,整理如下:

vue

v-model 修饰符有哪些

答:.number、.trim、.lazy

Tip: 用法如下:

<input v-model.lazy="msg">

<input v-model.number="age" type="number">

<input v-model.trim="msg">

v-model 的原理

答:v-model 可以在表单或组件上创建双向绑定。v-model 的本质其实是一个语法糖,即名为 value 的 props 以及 input 事件。

  • 在组件上使用
<custom-input v-model="count"></custom-input>   

等于

<custom-input :value="count" @input='changCount'></custom-input> 
  • 在表单上使用
<input v-model="message" placeholder="edit me">

等于

<input type="text" :value='message' @input='handleInput' placeholder="edit me">

Tip:更多介绍请看 v-model

v-if 与 v-for 一起使用

答:不推荐同时使用 v-if 和 v-for。若一定要一起使用,可以使用 template,就像这样:

<li v-for="todo in todos" >
    <template v-if="!todo.isComplete">
        {{ todo }}
    </template>
</li>

computed 和 watch 谁先执行

答:从 vue 源码中可知晓,先初始化计算属性,后初始化 watch,笔者做了一个实验,即在一个组件中同时添加 watch、computed,却先执行 watch ,再执行 computed。

计算属性有缓存吗

答:计算属性有缓存。因为假如计算属性需要遍历一个巨大的数组并计算得来,而其他地方也需要使用这个计算属性,没有缓存,将再次计算。

请简单介绍下 vuex

答:在 vue 中我们可以使用 props 和 emit 解决父子组件之间的通信,而非父子之间的通信则可以使用 bus(中央事件总线)。而 Vuex 作为 vue 的一个插件,解决的问题与 bus 类似,更具体些,就是 vuex 能解决多个组件共享状态的需求。

Vuex 的核心概念有 State、Getters、Mutations、Actions:

  • state,即 vuex 的数据
  • getters,可以认为是 store 的计算属性
  • mutations,更改 vuex 中 state(数据)的唯一方式
  • actions,类似 mutation,但不能直接修改 state

Tip: 更多介绍请看 vuex基础

vuex重刷还有吗,如何做持久化

答:没有了。可以配合 sessionStorage 做持久化,亦或使用 npm 包(vuex-persistedstate)。

Tip:

// App.vue
created(){
    //页面加载时读取 localStorage 里的状态信息
    if(localStorage.getItem("userMsg")){
        this.$store.replaceState(...)
    }
    //在页面刷新时保存到 localStorage
    window.addEventListener("beforeunload",()=>{
        localStorage.setItem(...)
    })
  }

vue-router 默认是什么模式

答:hash

$router 和 $route 的区别

答:$router 指 router 实例。例如 this.$router.push('/')$route 指当前激活的路由信息对象。例如 this.$route.params

javascript

是否了解 es11,?.??用过吗

答:有所了解。例如 es11 中有 BigInt、可选链操作符( ?. )、空值合并操作符(??)。

?. 和 ?? 用法如下:

const obj = {
  a: 1,
  b: {
    c: 2
  }
};

// ?. 操作符的功能类似于 . 链式操作符,不同之处在于,
// 在引用为空 null 或者 undefined 的情况下不会引起错误,该表达式短路返回值是 undefined。
console.log(obj.d?.c) // undefined

console.log(obj.b?.c) // 2

console.log(obj?.someNonExistentMethod?.()) // undefined
// 当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数
console.log(null ?? 'default string') // default string

// || vs ??
console.log(0 || 42) // 42
console.log(0 ?? 42) // 0

Tip:有关 ES2020、ES2021、ES2022 等特性可以查阅:kangax es2016plusbabel 插件列表

什么是事件循环

答:js 是单线程的语言,同一时刻只能执行也给任务,只有第一个任务完成,才能接着做第二个任务,如果上一个任务是计算量很大,cup 很忙导致无法接着做下一个任务,这种情况没问题,但如果上一个任务是只是在等待(如 ajax 请求),cup 很闲而导致下一个任务也只能跟着一起等待,那么就不好了,所以需要事件循环这个机制来解决此问题。

事件循环机制如下:

  1. 所有同步任务都在主线程上执行,形成一个执行栈
  2. 除了主线程,还有一个任务队列,只要异步任务有了结果就会往任务队列中放一个事件
  3. 当执行栈为空,主线程就会去读任务队列,放入执行栈中执行
  4. 如此循环

Tip:关于事件循环更详细的介绍,有多种不同版本,笔者倾向于下面这种

主线程:
同步代码1->同步代码2->...->同步代码N

事件队列:
- 宏任务队列:事件1->事件2->...->事件N
- 微任务队列: 事件1->事件2->...->事件N

①,执行栈中所有同步任务执行完毕
②,执行完微任务队列中所有事件对应回调
③,取出宏任务队列中一个事件,将对应回调加入执行栈

依次循环①②③①②③...

宏任务和微任务都有哪些

答:

  • 微任务:Pormise.then、MutationObserver
  • 宏任务:setTimeout、setInterval、requestAnimationFrame

什么时候用 promise,什么时候用 async

答:async/await 的本质是生成器和执行器,而执行器是通过 Promise 实现。所以 async 也就是 Promise 的语法糖,并且是一个实现了固定功能的语法糖。

所以,就灵活程度来讲,Promise 可能更好。

所以,这两个东西就不是替换关系,而是有他们各自使用的场景。

以下是我的一些个人习惯:

  • 只有一个异步请求,并且需要处理错误情况,倾向 Promise
  • 逻辑比较复杂,比如异步嵌套、条件、中间值等等,使用 async
  • async 有时会比 Promise 更容易调试

Tip:详细介绍请看 这里

给数组增加一个方法,只能存入唯一的值

答:

Array.prototype.uniquePush = function (...values) {
  values.forEach(v => {
    if (!this.includes(v)) {
      this.push(v)
    }
  })
}

let array = [1, 2, 3]
array.uniquePush(4, 3)
// array:  [ 1, 2, 3, 4 ]
console.log('array: ', array)

扁平化嵌套数组

例如有这么一个数组:

const arr = [1, 2, [3, 4, 5, [6, 7, 8], 9], 10, [11, 12]]

将其扁平化(层级不限)成:

[ 1,  2, 3, 4,  5, 6,  7, 8, 9, 10, 11, 12 ]

可提供多种方式

答:

  • 使用数组的 flat() 方法
const flated1 = arr.flat(Infinity)
console.log('flated1: ', flated1);
  • 使用递归
function flat(arr, result = []) {
  arr.forEach(item => {
    let wrap = Array.isArray(item) ? flat(item) : [item]
    result.push(...wrap)
  })
  return result
}

const flated2 = flat(arr)
console.log('flated2: ', flated2);
  • 使用 toString() 方法
const flated3 = arr.toString().split(',').map(item => Number(item))
console.log('flated3: ', flated3)

Tip:Array.prototype.toString() 返回一个表示数组及其元素的字符串。并会调用每项的 toString() 方法:

let obj = {
  toString() {
    return 'i am obj'
  }
}

let arr2 = ['a', 3, obj]
// a,3,i am obj
console.log(arr2.toString())

请完成 getTree() 方法

// 将数据转成树的结构
function getTree(arr) {
 
}

// parent 为 -1 的是根节点。只有一个根节点
let flatTree = [
  { name: 'b', id: 2, parent: 1 },
  { name: 'a', id: 1, parent: -1 },
  { name: 'c', id: 3, parent: 1 },
  { name: 'd', id: 4, parent: 3 },
  { name: 'e', id: 5, parent: 3 },
]

let tree = getTree(flatTree)
// {"name":"a","id":1,"parent":-1,"children":[{"name":"b","id":2,"parent":1},{"name":"c","id":3,"parent":1,"children":[{"name":"d","id":4,"parent":3},{"name":"e","id":5,"parent":3}]}]}
console.log(JSON.stringify(tree))

答:

function getTree(arr) {
  arr.forEach(item => {
    if (item.parent === -1) {
      return
    }
    let pId = item.parent
    let parentNode = arr.find(item => item.id === pId)
    if (!parentNode.children) {
      parentNode.children = []
    }
    parentNode.children.push(item)
  })

  const root = arr.find(item => item.parent === -1)
  return root
}

刷新页面 sesstionStorage 会清空吗?

答:不会

刷新页面,将在控制台依次输出1、2、3...;若用新的 tab 访问,又会依次输出1、2、3...

let msg = sessionStorage.getItem('a')
if (!msg) {
    sessionStorage.setItem('a', '1')
} else {
    sessionStorage.setItem('a', (+msg) + 1)
}

console.log(sessionStorage.getItem('a'));

Tip: 更多介绍请看 sessionStorage

new Date('abc') 会如何

答:控制台输出 Invalid Date

async 中的 await 后面如果报错,会发生什么

答:会中断 await 后续代码的执行,async 方法会立即结束。

Tip

  • 不明白题意,请看如下代码
async function foo() {
  // obj 是一个不存在的变量
  await obj
  return 1
}

foo().then(v => {
  console.log(v)
}).catch(v => {
  console.log(`catch, ${v}`)
})

// 输出:catch, ReferenceError: obj is not defined
  • 为什么会这样可以查看:async

class 的构造函数能否使用 async

答:不能。

请看示例:

class Dog {
  async constructor() {
    this.name = 'apple'
  }
  async say() {
    console.log(this.name);
  }
}

new Dog().say()

// Class constructor may not be an async method

若用数组来实现栈、队列,需要用到数组的什么方法

答:栈是先进后出,所以会用到 push 、pop;而队列是先进先出,故用到 push、shift

如何解决 0.1 + 0.2 != 0.3

答:此问题的出现是因为浮点数不能精确地用二进制表示所有小数,会出现一些意外的结果,比如:

let a = 0.1
let b = 0.2
let c = 0.3

// 0.30000000000000004
console.log(a + b)

有三种方法可以解决:

  • Number.EPSILON
  • 转为整数再比较。即将数字提升 10 的 N 次方
  • 使用 toFixed()

请看示例:

function equal(a, b) {
  return Math.abs(a - b) < Number.EPSILON
}
let isEqual = equal(a + b, c)
// isEqual:  true
console.log('isEqual: ', isEqual)
let seed = Math.pow(10, 10)
let isEqual2 = (a * seed + b * seed) === c * seed
// isEqual2:  true
console.log('isEqual2: ', isEqual2);
let isEqual3 = parseFloat((a + b).toFixed(10)) === c
// isEqual3:  true
console.log('isEqual3: ', isEqual3)

http

什么是协商缓存、什么是强制缓存

答:缓存的作用很好理解,通过复用以前的资源,可以提高网站的性能,提升用户体验。

通常第一次获取资源后,会根据返回的信息(respone header)得知如何缓存,例如做强缓存、协商缓存或不做缓存。

强缓存的特性是,下次直接从缓存中读取,不会发送到服务器,返回的状态码是 200(from cache)

协商缓存的特性,也是直接从缓存中读取,不过得先到服务器那里询问一下缓存资源是否可用,返回的状态码是 304(not modified)

与强缓存相关的 http 头有 cache-controlExpires。比如Cache-control: max-age=N的头,相应的缓存的寿命就是N,对于不含这个属性的请求,则会去查看是否包含 Expires 属性。

与协商缓存相关的是 EtagLast-Modified。比如,用户再次访问给定的URL(设有ETag字段),若资源过期了,客户端就发送值为ETag的If-None-Match header字段。Last-Modified 由于精确度比 ETag 要低,所以这是一个备用机制

Tip: 对于单页面,我们可以通过更新页面(例如 index.html)中引用资源的路径,让浏览器重新加载资源,更多介绍请看 MDN HTTP 缓存静态资源的缓存

描述下浏览器输入 url 回车后的整个过程

答:
大概流程:

  1. 首先拿到服务器 ip(即域名解析)
  2. 接着和服务器建立连接,传递数据(即相互通信)
  3. 服务器处理请求
  4. 浏览器接收响应

更具体一些:

域名解析
拿到服务器 ip 需要用到 域名解析(将好记的域名解析成 ip)。

解析流程大致如下图所示:

  1. 客户端:我要访问 www.163.com,请告诉我 ip
  2. 本地 dns 服务器:缓存里找不到,去 dns 根服务器询问
  3. dns 根服务器:这个域名由 .com 负责
  4. .com 域服务器:163.com 域名应该知道
  5. 163.com 域服务器:ip 是 1.1.1.xx
  6. 本地 dns 服务器取得 www.163.com 对应的 ip,写入缓存,返回 ip 给客户端

Tip

  • 真实的解析过程情况会更多,比如会搜索系统中 hosts 文件。笔者很久以前用过一个叫 SwitchHosts(能管理、切换多个 hosts) 的工具,开发中用于切换不同的环境,比如开发环境、测试环境等等。
  • dns(即域名系统),用于管理有意义的域名和ip的对应关系

相互通信
主要是涉及 TCP/IP协议(一个协议族,能够在多个不同网络间实现信息传输,也是 Internet 最基本的协议)。

大致流程如下:

  1. 浏览器发起 http 请求
  2. 经由应用层
  3. 然后到传输层,其中 tcp 会使用三次握手建立连接,后面则会使用四次握手中断连接
  4. 在往下就是网络层,比如 ip 寻址
  5. 最后是网络接口层,这里有传输数据的物理媒介
  6. 服务端接收则会反过来,依次是网络接口层,网络层,传输层,应用层

Tip:不同种类的应用程序会根据自己的需要来使用应用层的不同协议,比如浏览器在这里会使用 http 协议。

浏览器接收响应
大致流程如下:

  • 浏览器接收到资源后,会根据响应内容做不同的处理
  • 比如响应码是 301 则永久重定向,如果是 304 则去读缓存
  • 比如资源使用 gzip 压缩了,就得解压
  • 比如资源类型是视频(Content-Type:video/mp4),浏览器则会播放
  • 比如是否对资源做缓存

Tip:有关构建 dom 树、预加载扫描器、构建 cssom树、回流、重绘等可以看 这里

零碎

  • 如果输入的不是合法的 url,而是关键字,那么浏览器就会去搜索该关键字
  • 如果之前已经访问过,那么会先走强缓存,如果过期就走协商缓存
  • 可能还会涉及 sts,例如通过 http 而非 https 来访问淘宝、百度、京东的首页,则会发生一个 307 的重定向,并转到 https 上来

应用层的协议有哪些?例如 http 就属于应用层

答:应用层协议 还有 dns,ftp、smtp、snmp、telnet。

使用 tcp 传输的应用层协议有哪些?

答:http、ftp、telnet、smtp

Tip:如何验证“smtp”是 tcp,百度百科 SMTP 即可知晓。

使用 udp 传输的应用层协议有哪些?

答:dns、snmp、tftp

三次握手、四次挥手是针对 tcp,亦或 udp 吗?

答:三次握手、四次挥手只针对 tcp。

Tip:使用 tcp 的应用层协议,例如 http、ftp等,都会有三次握手、四次挥手

什么是三次握手、为什么又是四次挥手(亦称四次握手)?

答:
三次握手建立连接如下:

  1. 客户端发送报文(例如 x)给服务端
  2. 服务端接收后,回复报文给客户端,例如 y x+1
  3. 客户端接收到后,再次发送报文给服务端,例如 y+1
  4. 这样,双方都知道对方接收并理解了自己(例如发送 x,收到 x+1),于是可以开始通信

四次挥手过程如下:

  1. 客户端执行”主动关闭“,会给服务端发送 FIN。表明客户端不再发送数据,但仍可以接收数据
  2. 服务端接收 FIN 后执行“被动关闭”,发送 ACK 表明我已知晓,但我还有数据得处理
  3. 等服务端不再发送数据,就给客户端发送 FIN,表明对端可以关闭
  4. 客户端收到 FIN,发送 ACK 给服务端。
  5. 主要由于有数据可能需要处理,不能即使关闭,所以这里使用四次。若服务端将 FINACK 合并成一次,则可变成三次挥手

Tip:更多介绍请看 TCP

https 也有三次握手、四次挥手吗?

答:是的。因为 https 建立在 http 基础上。

https 使用对称加密还是非对称加密

答:传输时使用对称加密。

TipSSL 初始化时会用到非对称加密。

请描述一下 https 连接通信的过程

答:
由于 https 相对 http 多了一层,即安全层,所以这个过程会稍微复杂一些。

在 https 中,客户端首先打开一条到 Web 服务器端口 443(https 默认端口。http 的是 80),先建立 TCP 连接,之后客户端和服务端就会初始化 SSL 层(术语 SSL 来表示 SSL 或者 TLS),对加密参数进行沟通,并交换密钥。等到 SSL 初始化完成,就可以开始正式通信。客户端将请求报文发送给安全层,在发送给 tcp 之前,会先对其进行加密;服务端也在 SSL 层上发送 HTTP 响应,然后在 TCP 中发送已加密的响应。完成双方通信后,SSL关闭通知,TCP 连接关闭。

SSL 初始化大致流程:

  1. 发送客户端支持的加密协议给服务端
  2. 服务端筛选合适的加密协议,返回证书给客户端。证书中携带公钥,服务端自己保留私钥
  3. 客户端根据根证书验证证书合法性,倘若非法,浏览器则警告提醒;客户端生成对称密钥(即:加密和解密使用相同的密钥),通过公钥加密,发送给服务器(除了对称密钥,应该还有其他信息)
  4. 服务端使用私钥解密,获取对称密钥,使用对称密钥加密数据
  5. 客户端使用对称密钥解密数据,确认服务端已正确接收对称密钥

tip

  • 所有连网的应用都会提供端口
  • HTTPS (安全的HTTP)是 HTTP 协议的加密版本。它通常使用 SSL (en-US) 或者 TLS 来加密客户端和服务器之间所有的通信 —— mdn https
  • 传输层安全性协议(英语:Transport Layer Security,缩写:TLS)及其前身安全套接层(英语:Secure Sockets Layer,缩写:SSL)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障
  • http 传输分层,从上至下为:应用层(http)、传输层(tcp)、网络层(ip)、数据链路层。而 https 较 http 多一层,即安全层
  • https 传输分层,从上至下为:应用层(http)、安全层(SSL or TLS)、传输层(tcp)、网络层(ip)、数据链路层
  • 加密算法和解密算法统称为密码算法
  • 密钥是使用密码算法中输入的一段参数。同一个明文在相同的密码算法和不同的密钥下会产生不同的密文。根据密钥的使用方法,可分为对称加密和公钥加密
  • 对称加密,加密和解密使用相同的密钥
  • 公钥加密,分为加密密钥(或称公钥)和解密密钥(私钥),其中任何人都可以获取公钥,而私钥只能自己使用

webpack

简单说一下 tree-shaking (树摇)

答:用于描述移除 JavaScript 上下文中的未引用代码

Tip: 更多细节请看 tree-shaking

说一下你知道的 loader

答:由于 webpack 只能识别 javascript,其他资源都需要相应的 loader 来做翻译。

与css相关的有:css-loader、style-loader、less-loader、sass-loader、postcss-loader

配合图片的有:url-loader、file-loader

与 svg 相关的有:svgo-loader

与 js 有关的有:babel-loader、ts-loader

与 vue 相关的有:vue-loader、vue-style-loader

Tip:以下是相应 loader 的简易介绍:

  • css-loader,将 css 文件翻译成 webpack 能识别
  • style-loader,将 css 注入 dom。
  • less-loader,用于将 less 转为 css。类似的有 sass-loader、stylus-loader
  • postcss-loader,webpack 它用来使用 postcss
  • url-loader,将图片转为 base64
  • file-loader,配合 url-loader 可以生成图片
  • label-loader,用于在 webpack 中使用 babel
  • ts-loader,与 typescript 相关
  • svgo-loader,与 svg 相关,用于 svg 优化
  • vue-loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件
  • vue-style-loader,是一个基于 style-loader 的 fork,作为依赖项包含在 vue-loader 中,无需下载 1. vue-style-loader 即可使用。

请说一说 loader 和 plugin

答:
webpack 没有特殊配置只能识别 javascript,而前端还有css、图片等其他资源。

loader 用于对模块的源代码进行转换,可以理解成”翻译官“,比如我们需要使用 css,那么可以用 css-loader,如果需要使用图片,我们可以使用 url-loader 和 file-loader,如果需要将箭头函数翻译成普通函数,可以使用 babel-loader。loader 本质上是导出为函数的 JavaScript 模块。

而插件的目的是用于解决 loader 无法是现实其他事,plugin 强调一个事件监听能力,能在 webpack 内部监听一些事件,并且能改变一些文件打包后输出的结果。比如我们可以使用 html-webpack-plugin 来帮我们创建 html 并自动引用打包后的资源。plugin 本质上是一个具有 apply 方法的类。

Tip:有关 loader 和 plugin 的本质介绍可以查看 这里

请说一下 vue-loader

答:vue-loader 是一个 webpack 的 loader,它允许我们能以单文件组件的格式编写 vue 组件。同时它也提供了一些其他特性,比如:提供热重载、提供 scoped css、允许为 vue 组件的每个部分使用其他的 webapck loader(如 style 部分使用 sass,template 部分使用 pug)。总之,webpack 配合 vue-loader 能帮助我们编写 vue 应用。

Tip: 更多介绍请看 vue-loader

其他

能否说说 lodash.js 的深拷贝

答:没看过 lodash.js,但我用过 jQuery 的 extend 方法,如果要深拷贝,则传 true 给第一个参数

深度作用选择器

修改 element-ui 样式,比如将表格组件的表头改为红色,通常是不起作用,就像下面这样:

<template>
  <el-table></el-table>
</template>
  
<style scoped>
.el-table thead {
  color: red;
}
</style>

我们可以怎么做?

答:可以使用 深度作用选择器。即三个大于号(>>>),就像这样:

<style scoped>
>>> .el-table thead {
  color: red;
}
</style>

子域名跨域 Document.domain

不修改后端服务器,只在前端设置,如何让 a.baidu.com 和 b.baidu.com 能相互访问

答:可以使用 Document.domain

平时你是如何封装 axios

答:会简单封装下 axios。比如创建一个 request.js 的文件,里面返回一个 axios 实例,再做一下请求拦截和响应拦截。请求拦截器可以统一给所有请求传递一些信息给服务器,比如 token,在响应拦截中,比如返回 code 不是2000,则抛出错误,比如是 3000 就说明需要重新登录等等。

如何将二进制数据显示成图片

答:或许可以利用 URL、Blob。就像这样:

var blob = new Blob(...);
var url = URL.createObjectURL(blob)
imageElement.setAttribute('src', url)

一般通过什么途径来学习

答:比较杂,比如:腾讯 Web 前端、百度前端、淘宝前端、凹凸实验室、奇舞团,或者 github(看开源项目)、npm、babel、掘金、简书、博客园、纸质书、线上视频(如 慕课网、bilibili、极客学院)、技术相关的官网(如 node、express、webpack)、mdn、维基百科等等

简单谈一下跨域

答:跨域方式有很多,但现在主流的有两种,一种是开发环境和生成环境都使用 cors(跨域资源共享),一种是开发环境用 proxy,而生产环境用 nginx。

推荐的是 cors,它能决定浏览器是否阻止前端 JavaScript 代码获取跨域请求的响应。前端无需变化,工作量在后端。而后端的开发环境和生成环境是一套代码,所以也很方便使用。如果后端不愿意,前端就用 proxy + nginx。

Tip:更多细节可以查看 这里

请说一下 bfc(块级格式化上下文)

答:bfc 有个特性,如果一个元素具有 bfc,那么内部子元素在怎么折腾,都不会影响外部元素。

所以 bfc 元素不会有 margin 重叠。bfc 元素也能用来清除浮动的影响,子元素浮动会导致父元素高度塌陷,则会影响后面布局,这有悖于前面的特性。

创建 bfc 有多种方式,比如 overflow:auto/hiddendisplay:table-cell

是否用过 chrome 中 Performance

答:用过。通常在无痕模式下进行来分析性能,比如可以通过勾选内存其来分析内存使用情况,或使用调用树来找出花费时间较长的函数等。

是否了解过微服务、微前端

答:微前端首次提出是在 2016 年底,它将微服务这个应用于服务端的技术扩展到前端领域。

微前端背后的想法是:将网站或 web 应用程序视为由独立团队负责的子应用(或模块、功能)的组合。

微前端的核心是拆和合。为前端框架有 single-spa、qiankun。

Tip:更多介绍请看 初步认识微前端

是否自己写过 npm 包

答:写过。

Tip:如何发布一个 npm 包请看 这里

前端要不要学习后端

答:了解和掌握后端会更好。

例如:

  • 不会后端,纯前端能干的事太少,比如在某些小公司或it部门很小的大公司
  • 一个产品,前端只是一部分,如果不会后端,就不能把握住整个产品,和后端沟通也不会很顺利

所以学习后端:

  • 能更快的找到问题的根源并提出解决方案
  • 更高效的沟通和协作
  • 能独立完成一些简单任务,节约时间并提高团队生产力
  • 拓宽职业发展道路

结束

在罗列一点剩余的题目:

  • 介绍一下 vue,就当我是 vue 小白
  • 是否了解 csrf,能否简单谈一下
  • 如果做单页面应用的首页优化
  • 是否了解 vue 中的 $listeners、$attrs
  • 请介绍一下 http1 和 http2 的关系和区别
  • 比如让你制定项目规范,你会从什么方面着手
  • 请说说你知道的 http 头部(headers)
  • 请说说你知道的 http 状态码
  • 是否使用过 corss-env

把心放平,轻装上阵,祝君好运。

posted @ 2021-12-15 23:19  彭加李  阅读(330)  评论(0编辑  收藏  举报