脚本宝典收集整理的这篇文章主要介绍了谈面试前端工程师,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
以下是近期朋友去面试前端工程师所遇到的一些问题,整理如下:
答:.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 的本质其实是一个语法糖,即名为 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。若一定要一起使用,可以使用 template,就像这样:
<li v-for="todo in todos" >
<template v-if="!todo.isComplete">
{{ todo }}
</template>
</li>
答:在 vue 中我们可以使用 props 和 emit 解决父子组件之间的通信,而非父子之间的通信则可以使用 bus(中央事件总线)。而 Vuex 作为 vue 的一个插件,解决的问题与 bus 类似,更具体些,就是 vuex 能解决多个组件共享状态的需求。
Vuex 的核心概念有 State、Getters、Mutations、Actions:
Tip: 更多介绍请看 vuex基础
答:没有了。可以配合 sessionStorage 做持久化,亦或使用 npm 包(vuex-persistedstate)。
Tip:
// App.vue
created(){
//页面加载时读取 localStorage 里的状态信息
if(localStorage.getItem("userMsg")){
this.$store.replaceState(...)
}
//在页面刷新时保存到 localStorage
window.addEventListener("beforeunload",()=>{
localStorage.setItem(...)
})
}
答:hash
?.
和 ??
用过吗答:有所了解。例如 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 es2016plus、babel 插件列表。
答:js 是单线程的语言,同一时刻只能执行也给任务,只有第一个任务完成,才能接着做第二个任务,如果上一个任务是计算量很大,cup 很忙导致无法接着做下一个任务,这种情况没问题,但如果上一个任务是只是在等待(如 ajax 请求),cup 很闲而导致下一个任务也只能跟着一起等待,那么就不好了,所以需要事件循环这个机制来解决此问题。
事件循环机制如下:
执行栈
任务队列
,只要异步任务有了结果就会往任务队列中放一个事件主线程
就会去读任务队列,放入执行栈中执行Tip:关于事件循环更详细的介绍,有多种不同版本,笔者倾向于下面这种
主线程:
同步代码1->同步代码2->...->同步代码N
事件队列:
- 宏任务队列:事件1->事件2->...->事件N
- 微任务队列: 事件1->事件2->...->事件N
①,执行栈中所有同步任务执行完毕
②,执行完微任务队列中所有事件对应回调
③,取出宏任务队列中一个事件,将对应回调加入执行栈
依次循环①②③①②③...
答:
答:
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 ]
可提供多种方式
答:
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);
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())
// 将数据转成树的结构
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
}
答:不会
刷新页面,将在控制台依次输出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
答:控制台输出 Invalid Date
答:会中断 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
答:不能。
请看示例:
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
答:此问题的出现是因为浮点数不能精确地用二进制表示所有小数,会出现一些意外的结果,比如:
let a = 0.1
let b = 0.2
let c = 0.3
// 0.30000000000000004
console.log(a + b)
有三种方法可以解决:
请看示例:
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)
答:缓存的作用很好理解,通过复用以前的资源,可以提高网站的性能,提升用户体验。
通常第一次获取资源后,会根据返回的信息(respone header)得知如何缓存,例如做强缓存、协商缓存或不做缓存。
强缓存的特性是,下次直接从缓存中读取,不会发送到服务器,返回的状态码是 200(from cache)
协商缓存的特性,也是直接从缓存中读取,不过得先到服务器那里询问一下缓存资源是否可用,返回的状态码是 304(not modified)
与强缓存相关的 http 头有 cache-control
和 Expires
。比如Cache-control: max-age=N
的头,相应的缓存的寿命就是N,对于不含这个属性的请求,则会去查看是否包含 Expires
属性。
与协商缓存相关的是 Etag
和 Last-Modified
。比如,用户再次访问给定的URL(设有ETag字段),若资源过期了,客户端就发送值为ETag的If-None-Match
header字段。Last-Modified 由于精确度比 ETag 要低,所以这是一个备用机制
Tip: 对于单页面,我们可以通过更新页面(例如 index.html)中引用资源的路径,让浏览器重新加载资源,更多介绍请看 MDN HTTP 缓存、静态资源的缓存。
答:https 即超文本传输安全协议。https 经由 http 进行通信,但利用 SSL/TLS
(安全协议) 来加密数据包。之所以说 https 安全,主要是因为它有一套比较好的数据传输方案。
比如 A 向 B 发送消息,A 会通过 B 提供的公钥
对数据进行加密后再传输。并且 A 不是直接从 B 那里获得公钥,而是从认证机构
取得。
也就能保证:
私钥
进行解密公钥
来自认证机构,保证了公钥确实是 B 的,而非伪造的Tip:相关术语介绍:
密码算法
密钥
是使用密码算法中输入的一段参数。同一个明文在相同的密码算法和不同的密钥下会产生不同的密文。根据密钥的使用方法,可分为对称加密和公钥加密对称加密
,加密和解密使用相同的密钥公钥加密
,分为加密密钥(或称公钥
)和解密密钥(私钥
),其中任何人都可以获取公钥,而私钥只能自己使用TLS
)及其前身安全套接层(英语:Secure Sockets Layer,缩写:SSL
)是一种安全协议,目的是为互联网通信提供安全及数据完整性保障注:http 的默认端口是 80,而 https 的默认端口是 443。
答: 大概流程:
更具体一些:
域名解析 拿到服务器 ip 需要用到 域名解析(将好记的域名解析成 ip)。
解析流程大致如下图所示:
www.163.com
,请告诉我 ip本地 dns 服务器
:缓存里找不到,去 dns 根服务器询问dns 根服务器
:这个域名由 .com 负责.com 域服务器
:163.com 域名应该知道163.com 域服务器
:ip 是 1.1.1.xx
www.163.com
对应的 ip,写入缓存,返回 ip 给客户端Tip:
相互通信 主要是涉及 TCP/IP协议(一个协议族,能够在多个不同网络间实现信息传输,也是 Internet 最基本的协议)。
大致流程如下:
Tip:不同种类的应用程序会根据自己的需要来使用应用层的不同协议,比如浏览器在这里会使用 http 协议。
浏览器接收响应 大致流程如下:
Content-Type:video/mp4
),浏览器则会播放Tip:有关构建 dom 树、预加载扫描器、构建 cssom树、回流、重绘等可以看 这里
零碎
答:用于描述移除 JavaScript 上下文中的未引用代码
Tip: 更多细节请看 tree-shaking
答:由于 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-loaderpostcss-loader
,webpack 它用来使用 postcssurl-loader
,将图片转为 base64file-loader
,配合 url-loader 可以生成图片label-loader
,用于在 webpack 中使用 babelts-loader
,与 typescript 相关svgo-loader
,与 svg 相关,用于 svg 优化vue-loader
,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件vue-style-loader
,是一个基于 style-loader 的 fork,作为依赖项包含在 vue-loader 中,无需下载 1. vue-style-loader 即可使用。答: 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 是一个 webpack 的 loader,它允许我们能以单文件组件的格式编写 vue 组件。同时它也提供了一些其他特性,比如:提供热重载、提供 scoped css、允许为 vue 组件的每个部分使用其他的 webapck loader(如 style 部分使用 sass,template 部分使用 pug)。总之,webpack 配合 vue-loader 能帮助我们编写 vue 应用。
Tip: 更多介绍请看 vue-loader
答:没看过 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>
不修改后端服务器,只在前端设置,如何让 a.baidu.com 和 b.baidu.com 能相互访问
答:可以使用 Document.domain
答:会简单封装下 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 元素不会有 margin 重叠。bfc 元素也能用来清除浮动的影响,子元素浮动会导致父元素高度塌陷,则会影响后面布局,这有悖于前面的特性。
创建 bfc 有多种方式,比如 overflow:auto/hidden
、display:table-cell
答:用过。通常在无痕模式下进行来分析性能,比如可以通过勾选内存
其来分析内存使用情况,或使用调用树
来找出花费时间较长的函数等。
答:是的。微前端第一提出好似在 2016年底,将微服务这个被应用于服务端的技术扩展到前端领域。微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。比如 蚂蚁金融开源一套完整的微前端解决方案,即 qiankun(对于用户而言只是一个类似 jQuery 的库)。
答:写过。
Tip:如何发布一个 npm 包请看 这里
在罗列一点剩余的题目:
把心放平,轻装上阵,祝君好运。
以上是脚本宝典为你收集整理的谈面试前端工程师全部内容,希望文章能够帮你解决谈面试前端工程师所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。