文章目录
HTML
HTML里常见的单位
video标签会预加载视频吗
h5 的新特性有哪些
简述下对 webWorker 的理解?
CSS
CSS盒模型[★]
如何实现盒子水平垂直居中[★★★★]
左边固定,右边自适应的布局(尽可能多的方法)[★★★]
选择器排序[★]
怎么实现动画一个元素从左滑到右[★★]
inline、inline-block、block的区别[★★★]
外边距重叠[★★]
src和href区别[★]
flex 的常用 用法和场景
移动端,3 个盒子并排,宽高自适应,间距固定
分析比较 opacity: 0、visibility: hidden、display: none 优劣和适用场景
如何解决移动端 Retina 屏 1px 像素问题
居中为什么用transform,而不是margin top/left
rem, 计算出375的屏幕,1rem,单位出现小数怎么处理
rem和vw的使用场景
PC/移动端兼容性
平常遇到过哪些 Pc 端兼容,兼容到哪些版本,怎么处理的
遇到过哪些移动端兼容问题
平常 PC 端做过页面缓存吗,怎么做
除了 Etag,还有哪些缓存手段(一共 4 个,Cache-Control、Last-Modified 等等),哪些是 HTTP1.0 的?
前端存储有哪些
DOM/BOM/事件
DOM事件的捕获、冒泡和委派[★★]
实现图片懒加载[★★]
脚本如何全局检测错误[★]
如何监听input里内容的改变[★]
事件的target/currentTarget的区别[★★]
JavaScript基础
数据类型的判断
类型转换的原理是什么?
类型转换的规则有哪些?
typeof 是否正确判断类型? instanceof呢? instanceof 的实现原理是什么?
手写instanceof
function InstanceOf(son,farther){
while(true){
son=son.__proto__
if(!son) return false
if(son===farther.prototype) return true
}
}
变量提升问题
0.1+0.2为什么不等于0.3?
javascript精度问题的原因
你是怎么理解JavaScript 中的执行上下文和执行栈的?
谈一下js中的作用域链
说一下js中的词法作用域和动态作用域
作用域是指程序源代码中定义变量的区域。 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。 JavaScript采用词法作用域,也就是静态作用域。
因为 JavaScript 采用的是词法作用域,变量的作用域在定义的时候就决定了。
而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。
async 和 defer 的不同
闭包的含义、作用、使用场景、意义
内存泄漏的意义、场景、判断
undefined和null区别
for、forEach、map的性能对比
为什么普通 for 循环的性能远远高于 forEach 的性能,请解释其中的原因
手写forEach
从这儿也能看出为什么for的性能要比forEach要好
Array.prototype.forEach = function(fn,arg){
for(let i = 0, len = this.length; i < len; i++){
fn.call(arg,this[i],i,this)
}
}
手写reduce
Array.prototype.reduce = function(fn,initialVal){
//初始值设置,确定是从哪儿开始累积
let [val,index] = initialVal ? [initialVal,0]:[this[0],1]
for(let i = index, len = this.length; i < len; i++){
//循环调用函数
val = fn(val,this[i],i,this)
}
return val
}
let params = "a=b&c=d&e=f"
let t = null
let a = params.split("&").reduce((res,v)=>(t=v.split("="),res[t[0]]=t[1],res),{})
console.log(a)//{ a: 'b', c: 'd', e: 'f' }
call 和 apply 的区别,第一个参数必须是 this 吗
手写apply()
Function.prototype.apply=function(context,args) {
context.fn=this//为context设置函数属性
let result=context.fn(...args)//调用函数
delete context.fn//删除context的函数属性
return result
}
手写call()
Function.prototype.call=function(context,...args) {
context.fn=this
let result=context.fn(...args)
delete context.fn
return result
}
手写bind
Function.prototype.bind=function(context) {//使用[闭包+apply]实现
const args1 = Array.from(arguments)
return (...args2)=>this.apply(context,[...args1,...args2]);
}
JavaScript中怎么判断相等[★]
catch 之后的 then 还会执行吗
会执行,catch()是then()的语法糖,then()返回的还是一个promise,后续调用可以串联起来
// 函数A只返回一个reject异常
function A() {
return Promise.reject(new Error(Math.random()));
}
// 这样会先执行catch,然后执行后面的then
A().then(() => console.log('第一个then'))
.catch(e => console.error(e))
.then(() => console.log('第二个then'))
// 任意Promise中的catch异常,都会阻断后面代码的执行,并跳转到try中的catch,被捕获
// 多个Proimise也一样
try {
A().then(() => console.log('第一个then'))
.then(() => console.log('第二个then'))
} catch(e) {
console.error(e);
}
如何在ES5环境下实现const
如何在ES5环境下实现let
this指向/变量声明提升/作用域链问题
匿名函数(自执行函数IIFE)的作用是什么
数组去重[★]
let arr = [1,2,1,2,3,4,5,3];
let _newArr = [];
方法一:循环遍历判断
arr.forEach(v=> _newArr.indexOf(v) === -1&&_newArr.push(v));//indexOf内部隐含着循环,所以进行了两层循环
方法二:集合处理
let _set = {};
arr.forEach(v=> _set[v] || (_set[v] = true, _newArr.push(v)));//只进行了一层循环
方法三:es6 Set
_newArr = Array.form(new Set(arr))
数组的常用方法(indexOf、map 等等的作用以及他们的区别)
判断数组的方法,并对比它们的优劣
const foo = []
Array.isArray(foo) // 1
foo.constructor === Array // 2
foo instanceof Array // 3
Object.prototype.toString.call(foo) === '[object Array]' // 4
fastclick 解决点击穿透的 原理
继承问题
什么是原型?什么是原型链?原型链解决的是什么问题?
原型链/原型链继承[★★★]
多重继承怎么实现
封装个可以检测所有数据类型的函数[★]
每隔一秒打印数组里的元素[★★]
实现数组的扁平化[★]
async函数与Promise的区别[★]
对async、await的理解,内部原理
Promise 构造函数是同步执行还是异步执行,那么 then 方法呢?
Promise 构造函数是同步执行,它属于宏任务;then 方法为异步执行,属于微任务
JS 异步解决方案的发展历程以及优缺点
项目中websocket是解决了什么问题
webWorker的使用:为什么不在worker里面发出请求,做数据转换呢?
JavaScript文件在HTML文件里的执行顺序[★]
有哪些方式可以判断是否是数组[★★]
什么是防抖和节流?有什么区别?如何实现?
深浅拷贝的方法及手写
用原生 JS 模拟一个 bind
跨域的方法有哪些?原理是什么?
介绍下观察者模式和订阅-发布模式的区别,各自适用于什么场景
说一下你对setTimeout(f, 0)的理解?
setTimeout倒计时为什么会出现误差?
手动实现一个EventEmitter类
手写new创建对象
function myNew(constructorFn,...args){
//创建一个新对象继承传进来的构造函数
let newObj = {}
newObj.__proto__ = constructorFn.prototype
let result = constructorFn.apply(newObj,args)
return result instanceof Object?result:newObj
}
function Animal(name){
this.name = name
}
let animal = myNew(Animal,'dog')
console.log(animal.name)
封装jsonp方法
function jsonp(url, params, callback){
//创建一个供后端返回数据调用的函数名
let funcname = 'jsonp_'+Date.now()+Math.random().toString().substr(2,5)
//将参数拼接成字符串
if(typeof params === 'object'){
let temp = []
for(let key in params){
temp.push(`${key}=${params[key]}`)
}
params = temp.join('&')
}
//在html中插入<script>资源请求标签
let script = document.createElement('script')
script.src=`${url}?${params}&callback=${funcname}`
//在本地设置提供后端返回数据时调用的函数
window[funcname]=data=>{
callback(data)
delete window[funcname]
document.body.removeChild(script)
}
}
//使用
jsonp('http://xxxxx',{id:123},data=>{
//获取数据后的操作
})
函数式编程
什么是函数柯里化?实现 sum(1)(2)(3) 返回结果是1,2,3之和
// 编写一个 add 函数,实现以下功能
add(1)(2)(3) // 6
add(1)(2, 3)(4) //10
add(1, 2)(3) (4, 5) // 15
function add() {
let args = Array.prototype.slice.call(arguments)
let adder = function() {
// 利用闭包的特性保存 args 并且收集参数
args = args.concat(Array.prototype.slice.call(arguments))
return adder
}
// 利用 toString 隐式转换的的特性返回最终计算的值
adder.toString = function() {
return args.reduce((a, b) => {
return a + b
})
}
return adder
}
// 当然,我们也可以借助ES6的方法简化这个函数
function add1(...args) {
let adder = (..._args) => {
args = [...args, ..._args]
return adder
}
adder.toString = () => args.reduce((a, b) => a + b)
return adder
}
ES6
es6的新特性
let const var的区别
var缺陷以及为什么要引入let和const?
let的特点
箭头函数和普通函数的区别
es6 的指向问题
JavaScript的基本数据类型+ES6新增
axios用途
es5 和 es6 继承的不同
ES6 代码转成 ES5 代码的实现思路是什么
数组去重
[...new Set(array)]
[...new Set("aabbcc")].join("") ——>abc
发布订阅模式
//发布订阅模式
class Observer {
constructor(){
this.events = {}
}
//订阅
subscribe(eventName,callback){
if(this.events[eventName]){
this.events[eventName].push(callback)
}else{
this.events[eventName]=[callback]
}
}
//发布
publish(eventName,...args){
if(this.events[eventName]){
this.events[eventName].forEach(cb=>cb.apply(this,args))
}
}
//取消订阅
unSubscribe(eventName,callback){
if(this.events[eventName]){
this.events[eventName] = this.events[eventName].filter(cb=>cb!==callback)
}
}
}
const ob = new Observer()
function showAlert(){
console.log(1111111111)
}
ob.subscribe('showAlert',showAlert)
ob.unSubscribe('showAlert',showAlert)
ob.publish('showAlert')
promise 的作用和使用方法
实现Promise的all方法
Promise.prototype.all=function(promiseList) {
return new Promise((resolve,reject)=>{
if (promiseList.length===0) return resolve([])
let result=[],count=0
promiseList.forEach((promise,index)=>{
Promise.resolve(promise).then(value=>{
result[index]=value
if (++count===promiseList.length) resolve(result)
},reason=>reject(reason))
})
})
}
promise 异步的判断题(判断执行顺序)
Promise的串行调用
手写一个符合Promises/A+规范的promise
简述异步加载的几种方式
es6 的继承用法
es module和commonjs的区别
CommonJS 是一种模块规范,最初被应用于 Nodejs,成为 Nodejs 的模块规范。运行在浏览器端的 JavaScript 由于也缺少类似的规范,在 ES6 出来之前,前端也实现了一套相同的模块规范 (例如: AMD),用来对前端模块进行管理。自 ES6 起,引入了一套新的 ES6 Module 规范,在语言标准的层面上实现了模块功能,而且实现得相当简单,有望成为浏览器和服务器通用的模块解决方案。但目前浏览器对 ES6 Module 兼容还不太好,我们平时在 Webpack 中使用的 export 和 import,会经过 Babel 转换为 CommonJS 规范。在使用上的差别主要有:
(1)CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
(2)CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
(3)CommonJs 是单个值导出,ES6 Module可以导出多个
(4)CommonJs 是动态语法可以写在判断里,ES6 Module 静态语法只能写在顶层
(5)CommonJs 的 this 是当前模块,ES6 Module的 this 是 undefined
介绍下 Set、Map、WeakSet 和 WeakMap 的区别?
Vue
简述 MVC 和 MVVM
vue 全家桶怎么用的
Vue中v-model的实现原理以及如何自定义v-model
vue 实现双向绑定的原理
Vue中事件绑定的原理?
Vue组件中的data为什么是个函数?
Vue中v-html会导致哪些问题?
Vue中什么是作用域插槽?
Vue中模板编译原理
babel 怎么把字符串解析成 AST,是怎么进行词法/语法分析的?
Vue的解析器原理? 用template生成AST语法树分析
Vue的响应式(双向绑定)原理[★★★★]
Vue中是如何检测数组变化的?
对virtual DOM的理解,其优势在哪里
「Virtual Dom 的优势」其实这道题目面试官更想听到的答案不是上来就说「直接操作/频繁操作 DOM 的性能差」,如果 DOM 操作的性能如此不堪,那么 jQuery 也不至于活到今天。所以面试官更想听到 VDOM 想解决的问题以及为什么频繁的 DOM 操作会性能差。
首先我们需要知道:
DOM 引擎、JS 引擎 相互独立,但又工作在同一线程(主线程)
JS 代码调用 DOM API 必须 挂起 JS 引擎、转换传入参数数据、激活 DOM 引擎,DOM 重绘后再转换可能有的返回值,最后激活 JS 引擎并继续执行若有频繁的 DOM API 调用,且浏览器厂商不做“批量处理”优化,引擎间切换的单位代价将迅速积累若其中有强制重绘的 DOM API 调用,重新计算布局、重新绘制图像会引起更大的性能消耗。
其次是 VDOM 和真实 DOM 的区别和优化:
虚拟 DOM 不会立马进行排版与重绘操作
虚拟 DOM 进行频繁修改,然后一次性比较并修改真实 DOM 中需要改的部分,最后在真实 DOM 中进行排版与重绘,减少过多DOM节点排版与重绘损耗
虚拟 DOM 有效降低大面积真实 DOM 的重绘与排版,因为最终与真实 DOM 比较差异,可以只渲染局部
Vue生命周期[★★★]
Vue父子组件生命周期的调用顺序?
Vue ajax请求放在哪个生命周期中?
在created的时候,视图中的dom并没有渲染出来,所以此时如果直接去操作dom节点,无法找到相关的元素
在mounted中,由于此时 dom 已经渲染出来了,所以可以直接操作 dom 节点
一般情况下都放到 mounted 中,保证逻辑的统一性,因为生命周期是同步执行的, ajax 是异步执行的。
服务端渲染不支持mounted方法,所以在服务端渲染的情况下统一放到created中
computed和watch[★★]
Vue中的computed是怎么实现的吗?
为什么Vue采用异步渲染?
讲一下nextTick的原理[★]
Vue的Watch中的deep: true是如何实现的?
谈谈你对keep-alive的理解
keep-alive是一个vue的内置的抽象组件,自身不会渲染一个DOM元素,也不会出现在父组件链中,使用keep-alive包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。
vuex 的有哪些参数,各有什么作用和区别,mutation 和 action 有什么区别,怎么用
路由守卫哪些参数,怎么实现
实现hash路由和history路由
你是如何理解Vue的响应式系统的?
Vue组件的更新和渲染过程
Vue中的key到底有什么用?
简述Vue中diff算法原理
vue3.0 有哪些改动和新特性(重点)
ssr有没有用过
Vue常见性能优化
Vue和React的区别是什么
Vue为什么没有类似于React中shouldComponentUpdate的生命周期?
vuex 模块化怎么做
React
对virtual DOM的理解[★]
React里key的作用[★]
react 的生命周期钩子,各个阶段发生了什么
React组件通信如何实现?
umi约定式路由怎么实现的
React组件重复渲染
你是如何理解fiber的?
如何用 Hooks 的方法去模拟 Class Components 的功能?
React Hooks 解决了什么问题?
redux 和 mobx 平常用过吗
react-redux中的connect原理解析
react-router 里的 Link 标签和 a 标签有什么区别
redux-saga了解吗?解决了什么问题?
redux在状态管理方面解决了react本身不能解决的哪些问题
react中的key的作用
你对 Time Slice的理解?
React dom绑定事件,与原生事件有什么区别
小程序
小程序里面开页面最多多少
小程序内部页面是通过栈的方式实现的,当前展示的页面即栈顶元素,栈内元素最多不能超过十个。
小程序和 H5 有什么区别?
(1)渲染方式与 H5 不同,小程序一般是通过 Native 原生渲染的,但是小程序同时也支持 web 渲染,如果使用 web 渲染的方式,我们需要初始化一个WebView 组件,然后在 WebView 中加载 H5 页面;
所以当我们开发一个小程序时,通常会使用 hybrid 的方式,即会根据具体情况选择部分功能用小程序原生的代码来开发,部分功能通过 WebView 加载 H5 页面来实现。Native 与 Web 渲染混合使用,以实现项目的最优解;
这里值得注意的是,小程序下,native 方式通常情况下性能要优于 web 方式。
(2)小程序特有的双线程设计。 H5 下我们所有资源通常都会打到一个 bundle.js 文件里(不考虑分包加载),而小程序编译后的结果会有两个bundle,index.js封装的是小程序项目的 view 层,以及 index.worker.js 封装的是项目的业务逻辑,在运行时,会有两条线程来分别处理这两个bundle,一个是主渲染线程,它负责加载并渲染 index.js 里的内容,另外一个是 Service Worker线 程,它负责执行 index.worker.js 里封装的业务逻辑,这里面会有很多对底层api调用。
Node
什么是event loop?浏览器和node上实现有什么不同?
什么是 JWT(JSON WEB TOKEN)
测试
浏览器
前端路由的实现
浏览器的主要组成部分是什么?
浏览器如何解析css选择器?
浏览器是如何渲染UI的?
介绍AST(Abstract Syntax Tree)抽象语法树
浏览器的进程[★]
Chrome浏览器,仅仅打开了1个页面,为什么有4个进程?
深入理解浏览器的缓存机制
CSS和JS文件阻塞浏览器页面加载吗[★★]
宏任务和微任务的区别[★]
cookie/session/SessionStorage和LocalStorage区别[★★★]
JS相较于C++等语言为什么慢,V8做了哪些优化
浏览器事件代理机制的原理是什么?
什么是event loop?浏览器和node上实现有什么不同?
了解v8引擎吗,一段js代码如何执行的
在执行一段代码时,JS 引擎会首先创建一个执行栈
然后JS引擎会创建一个全局执行上下文,并push到执行栈中, 这个过程JS引擎会为这段代码中所有变量分配内存并赋一个初始值(undefined),在创建完成后,JS引擎会进入执行阶段,这个过程JS引擎会逐行的执行代码,即为之前分配好内存的变量逐个赋值(真实值)。
如果这段代码中存在function的声明和调用,那么JS引擎会创建一个函数执行上下文,并push到执行栈中,其创建和执行过程跟全局执行上下文一样。但有特殊情况,即当函数中存在对其它函数的调用时,JS引擎会在父函数执行的过程中,将子函数的全局执行上下文push到执行栈,这也是为什么子函数能够访问到父函数内所声明的变量。
还有一种特殊情况是,在子函数执行的过程中,父函数已经return了,这种情况下,JS引擎会将父函数的上下文从执行栈中移除,与此同时,JS引擎会为还在执行的子函数上下文创建一个闭包,这个闭包里保存了父函数内声明的变量及其赋值,子函数仍然能够在其上下文中访问并使用这边变量/常量。当子函数执行完毕,JS引擎才会将子函数的上下文及闭包一并从执行栈中移除。
最后,JS引擎是单线程的,那么它是如何处理高并发的呢?即当代码中存在异步调用时JS是如何执行的。比如setTimeout或fetch请求都是non-blocking的,当异步调用代码触发时,JS引擎会将需要异步执行的代码移出调用栈,直到等待到返回结果,JS引擎会立即将与之对应的回调函数push进任务队列中等待被调用,当调用(执行)栈中已经没有需要被执行的代码时,JS引擎会立刻将任务队列中的回调函数逐个push进调用栈并执行。这个过程我们也称之为事件循环。
附言:需要更深入的了解JS引擎,必须理解几个概念,执行上下文,闭包,作用域,作用域链,以及事件循环。建议去网上多看看相关文章,这里推荐一篇非常精彩的博客,对于JS引擎的执行做了图形化的说明,更加便于理解。
https://tylermcginnis.com/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/?spm=ata.13261165.0.0.2d8e16798YR8lw
解释下从输入URL到页面渲染整个过程
从输入URL到渲染出整个页面的过程主要包括三个部分:
1、DNS解析URL的过程(缓存、查找IP)
2、浏览器发送请求与服务器交互的过程(三次握手、请求数据、http缓存、返回数据、四次挥手)
3、浏览器对接收到的html页面渲染的过程(DOM树生成、CSS DOM树生成、合并生成Render树、页面节点定位布局、渲染)
计算机网络
HTTP2相对于HTTP1.x有什么优势和特点?
http2多路复用
从输入URL到页面展示,这中间发生了什么?
TCP/UDP区别[★★]
一个 TCP 连接可以发多少个 HTTP 请求?
如果是 HTTP 1.0 版本协议,一般情况下,不支持长连接,因此在每次请求发送完毕之后,TCP 连接即会断开,因此一个 TCP 发送一个 HTTP 请求,但是有一种情况可以将一条 TCP 连接保持在活跃状态,那就是通过 Connection 和 Keep-Alive 首部,在请求头带上 Connection: Keep-Alive,并且可以通过 Keep-Alive 通用首部中指定的,用逗号分隔的选项调节 keep-alive 的行为,如果客户端和服务端都支持,那么其实也可以发送多条,不过此方式也有限制,可以关注《HTTP 权威指南》4.5.5 节对于 Keep-Alive 连接的限制和规则。
而如果是 HTTP 1.1 版本协议,支持了长连接,因此只要 TCP 连接不断开,便可以一直发送 HTTP 请求,持续不断,没有上限;
同样,如果是 HTTP 2.0 版本协议,支持多用复用,一个 TCP 连接是可以并发多个 HTTP 请求的,同样也是支持长连接,因此只要不断开 TCP 的连接,HTTP 请求数也是可以没有上限地持续发送
讲一下TCP三次握手、四次挥手过程及原理
当登录过一个网站之后,下次再访问该站点,就已经处于登录状态了,这是怎么做到的呢?
为什么很多站点第二次打开速度会很快?
怎么实现跨域[★★]
讲一下HTTP的缓存[★]
HTTP状态码301和302[★★]
HTTP状态码304[★★]
TCP的慢启动算法[★]
工程模块+webpack
介绍模块化发展历程
webpack 模块机制
介绍下 npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块?
webpack中,有哪些常见的Loader?他们是解决什么问题的?
webpack中,有哪些常见的Plugin?他们分别是解决什么问题的?
babel-runtime和babel-polyfill的作用介绍和使用
webpack HMR 原理解析
简单说下webpack中的文件指纹策略
文件指纹对应的其实就是hash:
Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的 hash 值就会更改
Chunkhash:和 webpack 打包的 chunk 有关,不同的 entry 会生成不同的 chunkhash 值
Contenthash:根据文件内容来定义 hash,文件内容不变,则 contenthash 不变
来看下这三种 hash 在 webpack 里面怎么配置:
module.exports = {
entry: {
app: "./src/app.js",
info: "./src/info.js",
},
output: {
filename: "[name][chunkhash:8].js",
path: __dirname + "/dist",
},
plugins: [
new MiniCssExtractPlugin({
filename: `[name][contenthash:8].css`,
}),
],
module: {
rules: [
{
test: /\.(png|svg|jpg|gif)$/,
use: [
{
loader: "file-loader",
options: {
name: "img/[name][hash:8].[ext]",
},
},
],
},
],
},
};
JS 文件指纹设置:设置 output 的 filename,使用[chunkhash]
CSS 文件指纹设置:设置 MiniCssExtractPlugin 的 filename,使用[contenthash]
图片文件指纹设置:设置 file-loader 的 name,使用[hash]
占位符名称 | 含义 |
---|---|
[ext] | 资源后缀名 |
[name] | 文件名称 |
[path] | 文件的相对路径 |
[folder] | 文件所在的文件夹 |
[contenthash] | 文件的内容 hash,默认是 md5 生成 |
[hash] | 文件内容的 Hash,默认是 md5 生成 |
[emoji] | 一个随机的指代文件内容的 emoj |
模块化规范[★] | |
webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全 | |
webpack中,loader和plugin的区别? |
loader直译为"加载器"。webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。
所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力。
plugin直译为"插件"。plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 webpack
运行的生命周期中会广播出许多事件,plugin 可以监听这些事件,在合适的时机通过 webpack 提供的 API 改变输出结果。
平常自己配过 webpack(前端面试必问,本属于附加题,如果能当面手写一个给面试官看,肯定加分)
与webpack类似的工具还有哪些?谈谈你为什么最终选择(或放弃)使用webpack?
同样是基于入口的打包工具还有以下几个主流的:
rollup、parcel
从真实项目使用场景上来看:
rollup适用于基础库的打包,如vue、react
parcel适用于简单的实验性项目,他可以满足低门槛的快速看到效果
webpack适用于大型复杂的前端站点构建
webpack与grunt、gulp的不同?
三者都是前端构建工具,grunt和gulp在早期比较流行,现在webpack相对来说比较主流,不过一些轻量化的任务还是会用gulp来处理,比如单独打包CSS文件等。
grunt和gulp是基于任务和流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,更新流上的数据, 整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。
webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
设计模式
算法
版本号排序[★]
复原IP地址[★]
两个二维矩阵相乘[★]
数组去重[★]
写快排[★]
合并有序数组[★★]
实现数组的扁平化[★]
找出字符串中第一个不重复的字符[★]
合并两个有序链表[★]
买卖股票的最佳时机[★]
二叉树后序遍历[★★]
合并区间[★]
字符串数字相加[★]
随机数(洗牌算法)[★]
实现trim功能[★]
类似逆波兰表达式的题[★★]
说一下几种常见算法的时间复杂度
二叉树遍历:前序、中序、后序的时间复杂度分别是多少?
图的遍历:时间复杂度是多少?
搜索算法:DFS、BFS时间复杂度分别是多少?
二分查找:时间复杂度是多少?
实现一个异步队列Queue,要求按时间依次执行callback
比较两数组差异 (Diff Two Arrays)
实现一个 sleep 函数
async function sleep(time = 0) {
return await new Promise(function(resolve) {
setTimeout(resolve, time)
})
}
如何快速从一个巨大的数组中随机获取部分元素(需考虑性能)
介绍下前端加密的常见场景和方法
找出数组中两数之和为指定值的所有整数对,要求时间复杂度为O(N)
数组随机打乱排序
多维数组转为一维数组
斐波那契数列如何优化
性能优化
如何避免重绘或者重排?
介绍下重绘和回流(Repaint & Reflow),以及如何进行优化
在你的前端项目中,你是如何找出性能瓶颈的?
接口如何防刷
一个思路,以 客户端 session + API 生成 redis key,并通过 redis set expire 进行保存,在进入对应接口前读取 redis 判断即可
如何在 H5 和小程序项目中计算白屏时间和首屏时间,说一下你的思路
首屏时间的计算,可以由 Native WebView 提供的类似 onload 的方法实现,在 ios 下对应的是 webViewDidFinishLoad,在 android 下对应的是onPageFinished事件。
白屏的定义有多种。可以认为“没有任何内容”是白屏,可以认为“网络或服务异常”是白屏,可以认为“数据加载中”是白屏,可以认为“图片加载不出来”是白屏。场景不同,白屏的计算方式就不相同。
方法1:当页面的元素数小于x时,则认为页面白屏。比如“没有任何内容”,可以获取页面的DOM节点数,判断DOM节点数少于某个阈值X,则认为白屏。
方法2:当页面出现业务定义的错误码时,则认为是白屏。比如“网络或服务异常”。
方法3:当页面出现业务定义的特征值时,则认为是白屏。比如“数据加载中”。
vue 如何优化首页的加载速度?首页白屏是什么问题引起的?如何解决?
文件上传如何做到断点续传
100万个成员的数组取第一个和最后一个有性能差距吗?
页面加载海量数据
webpack分包
国际化站点,cdn, 在页面什么阶段加载国际化文件,如果有20多个语言该怎么做
AST作用 or babel实现原理
不同域名共享cookie
网络安全
介绍下 HTTPS 中间人攻击
cookie 和 token 都存放在 header 中,为什么不会劫持 token?
有哪些可能引起前端安全的的问题?
其他
介绍下 BFC、IFC、GFC 和 FFC
触发bfc的方式
其他资料
https://www.yuque.com/yanghui-xazj3/uu7edw/gqsnu5