1. 数组扁平化的方法
Ex. var arr=[1,[2,[3,[4,5]]]]; => arr=[1,2,3,4,5]
- 传统方法
递归- 使用
reduce函数递归遍历- 数组强制类型转换
对于数组对象,toString方法连接数组并返回一个字符串,其中包含用逗号分隔的每个数组元素。返回的字符串使用split分割成子字符串数组,最后将数组中每个元素的类型转换为Number型- 使用ES6的
flat方法 flat(depth)- 使用JSON的
函数和正则表达式使用JSON的序列化函数stringify()先对数组进行序列化,再用正则去掉[],得到的结果在最外层加上[]后使用JSON.parse()恢复成数组对象。- 扩展运算符与some函数结合
先用some方法把数组中仍然是数组的项过滤出来,再执行concat操作,利用ES6的扩展运算符‘ ... '将其拼接到原数组中,最后返回。
2. CSS两列布局的实现方式
float+calc(): 左列开启浮动+右列开启浮动+右列宽度为父级100%减去左列宽float+margin-left:左列开启浮动+右列增加外边距absolute+margin-left:开启定位脱离文档流+(同上)float+overflow: {overflow:hidden}flex布局:.container {display:flex} .right {flex:1}grid布局
3. BFC
一、什么是BFC?
一个块格式化上下文(block formating context)是Web页面得可视化CSS渲染出得一部分,它是块级盒布局出现的区域,也是浮动元素进行交互的区域
二、触发条件
- 浮动元素,float不是none
- 绝对定位元素元素具有position为absolute或fixed
- 内联块,元素具有display:inline-block
- 表格单元格,元素具有display:table-cell
- 表格标题,元素具有display:table-caption
- 具有overflow且值不是visible的块元素
- display:flow-root
- column-span:all 应当总是会创建一个格式化上下文,即便具有column-span:all 的元素并不被包裹在一个多列容器中
三、BFC特性
- 内部的Box会在垂直方向上一个接一个的放置
- 垂直方向上的距离由margin决定
- BFC的区域不会与float的元素区域重叠
- 计算BFC的高度时,浮动元素也参与计算
- BFC就是页面上的一个独立容器,容器里面的子元素不会影响外面元素
四、为什么要使用BFC
- BFC可以解决子元素浮动导致父元素高度塌陷的问题
- BFC可以解决两个兄弟盒子之间的垂直距离是由他们的外边距所决定的,以较大为准
- 不被浮动元素覆盖
- 防止文字环绕
4. 水平居中方式
margin:auto; 元素有宽度有高度时
position:absolute;元素有宽度有高度时,设置position和margin为负的宽高的一半
position:absolute;元素有宽度有高度时,利用calc计算top和left
position:absolute;元素宽度、高度未知时,设置position和transform:translate(-50%, -50%)
弹性盒子:为其父元素设置display:flex利用水平对齐和行高:设置
text-align和line-height,实现单行文本水平垂直居中
grid:在网格项目中设置justify-self,align-self或者margin:auto
grid:在网格容器上设置justify,align-items或者jsutify-content,align-content
5. Vue-Router的原理,两种模式
一、
hash模式——即地址栏URL中的#符号
- hash不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重载页面
- 404错误:仅hash符号之前的内容会被包含在请求中,即使没有做到对路由的全覆盖也不会返回404错误
- hash的原理是采用hashchange事件,可以在window监听hash的变化,我们在url后面随便添加一个 #xx 触发这个事件
二、
history模式
- 需要特定浏览器支持,有back,forward,go,pushState等方法,提供了对历史记录修改的功能,当它们执行时,虽然改变了当前url,但浏览器不会立即向后端发送请求
- 404错误:前后端发起请求的url需一致,返回404错误
- histor的原理是H5的几个新API
6. 全局路由守卫和组件路由守卫
一、全局守卫
- 全局前置守卫 beforeEach
router.beforeEach((to, from, next) => {
})
在路由跳转之前被触发- 全局解析守卫 beforeResolve
参数: to, from, next
在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用- 全局后置钩子 afterEach
参数:to, from, failure二、组件内路由守卫
- beforeRouteEnter: 不能访问this,因为守卫在导航确认之前被使用,因此即将登场的新组件还没被创建
- beforeRouteUpdate: 主要是路由复用时被调用,即在当前页面跳转页面,会走该路由,而不会重头
- beforeRouteLeave: 这个离开路由守卫通常用来禁止客户在未保存修改前突然离开,该导航可以通过next(false)来取消
注意:beforeRouteEnter是支持给next传递回调的唯一守卫,对于beforeRouteUpdate和beforeRouteLeave来说,this已经可用了,所以不支持传递回调,因为没有必要了。
7. some和every方法的区别
相同点:
- 都可以遍历数组每一项数据
- 都不会对空数组进行检测
- 都不会改变原始数组
不同点:
some() 方法会依次执行数组的每个元素
如果有一个元素满足条件,则表达式返回true,剩余的元素不会再执行检测
如果没有符合条件的元素,则返回falseevery() 方法使用指定函数检测数组中的所有元素
如果数组中检测到有一个元素不满足,则整个表达式返回false,且剩余的元素不会再进行检测;如果所有元素都满足条件,则返回true
8. forEach 和 map 的区别
相同点:
- 都是循环遍历数组中的每一项
- 每次执行匿名函数都支持三个参数,参数分别为item(当前每一项), index(索引值), arr(原数组)
- 匿名函数的this都指向window
- 只能遍历数组
不同点:
- map() 方法会得到一个新数组并返回;forEach() 会修改原来的数组
- forEach() 允许callback 更改原始数组的元素;map() 返回新的数组
使用场景:
- forEach() 适合你并不打算改变数据的时候,而只是想用数据做一些事情——比如,存入数据库或打印
- map() 适合你要改变数据值的时候,不仅在于它更快,而是返回一个新数组,可以搭配filter(), reduce() 等
9. 浅拷贝 和 深拷贝
一、浅拷贝——
拷贝深度不够会改变原数组push、pop、unshift、shift、reverse、sort、forEach、Object.assign(第一个参数是拷贝的目标对象,后面的参数是开呗的来源对象)、扩展运算符
二、深拷贝——
不会改变原数组,增加了一个新指针并申请了一个新元素地址slice、concat、map、filter、reduce、for...in...、使用JSON.parse和JSON.stringify
注意:基本类型(string, number, boolean, null, undefined, symbol)不存在深浅拷贝问题,因为赋值的是数据;引用类型(Object, Array, Date, RegExp, Function)存在这个问题
10. reduce 方法
定义:reduce() 方法接收一个函数作为累加器,数组中的每个值
(从左至右)开始缩减,最终计算为一个值
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)reduce的常用方法:
- 数组求和
- 累加数组中对象的值
- 计算数组中每个元素出现的次数
- 数组去重
- 二维数组变一维
- 将多维数组变一维
- 根据属性把对象分类
11. 事件循环机制
浏览器时间循环和node.js事件循环Event Loop:
同步任务+异步任务所有同步任务都在主线程上执行,形成一个函数调用栈(执行栈),而异步任务则先放到任务队列里,任务队列又分为宏任务和微任务。
宏任务:script(整块代码)、setTimeout、setInterval、I/O,UI交互事件、setImmediate(node环境)
微任务:new promise().then 回调、MutationObserver(h5新特性)、process.nextTick(node环境)
12. 闭包
定义:有权访问其他函数作用域中变量得函数
JS中,变量得作用域属于函数作用域,在函数执行完毕后,它得作用域会被销毁,内传也会被回收,但由于闭包在函数内部创建一个子函数,且子函数可以访问父级函数中得作用域,即父函数执行完作用域也不会被回收,这就是闭包。
缺点:比普通函数更见占用内存,可能会造成内存泄漏
13. 箭头函数
语法比函数表达式更加简洁,并且
没有this, arguments, super 或 new.target;更加适用于本来需要隐匿函数的地方,并且它不能用作构造函数。
14. this指向
- 在
普通函数中,this指向window- 在
构造函数中,this指向创建对象- 在
方法声明中,this指向调用者- 在
定时器中,this指向window- 在
事件中,this指向事件源
15. 作用域有哪些
全局作用域 函数(局部)作用域 块级作用域 静态作用域 动态作用域
16. JS获取DOM节点的方式
getElementById getElementByClassName getElementByTagName
querySelector & querySelectorAll getElementByName
document.title & document.body
17. CSS布局
静态布局 自适应布局 流式布局 响应式布局 弹性布局
18. 双向绑定的原理
通过
数据劫持结合发布订阅模式的方法来实现
19. Vue2 和 Vue3 的区别
一、Composition API
Vue2是选择式API;Vue3是组合式API
二、双向数据绑定原理的变化
Vue2利用数据劫持结合订阅发布 Object.defineProperty();Vue3使用ES6的Proxy API对数据代理
三、Vue3支持碎片
四、建立数据
Vue2放入data;Vue3需使用setup(),在组件初始化构造的时候触发
五、生命周期钩子不同
六、父子传参不同
七、Vue3新增Teleport瞬移组件
20. HTTP 和 HTTPS 的区别
https需要到CA申请证书,一般免费证书较少,需要一定费用http是超文本文本传输协议,信息是明文,https是具有安全性的ssl加密传输协议- 连接方式不同,用的端口不一样,前者是
80,后者是443- http的链接是
无状态的;https协议是有ssl+http协议构建的可进行加密传输,身份认证的网络协议
21. 用elementUI的时候,如果需要el-button,打包的时候怎么按需打包
按需引入,借助babel-plugin-component打包
22. tree shaking(摇树优化)
ES6推出tree shaking,当我们在项目中引入其他模块时,它会自动将我们用不到的代码,或者永远不会执行的代码摇掉,在Uglify阶段查出,不打包到bundle中。
23. 为什么组件库按需加载时使用babel插件实现而不是依赖tree-shaking
tree-shaking依赖ES module语法,webpack不支持导出ES module。
组件库都是用webpack开发,不支持ES module导出
24. 浏览器渲染页面的过程
- 渲染引擎首先通过网络获得请求文档的内容
- 解析
HTML文件,构建DOM Tree- 解析
CSS,构建CSSOM Tree(CSS规则树)- 将
DOM Tree和CSSOM Tree合并,构建Render Tree(渲染树)reflow(重排):根据Render Tree进行节点信息计算(Layout)repaint(重绘):根据计算好的信息绘制整个页面(Painting)
25. JS 和 CSS 会不会阻塞页面渲染
- 通过
style标签引入的样式和同步加载的link标签会阻塞页面渲染,但异步加载的link标签则不会- js脚本通过添加
async或defer的方法来开启异步下载,开启异步下载则不会阻塞页面渲染,但下载完成后,加async的脚本会立即执行,执行时会阻塞页面渲染;
而加defer的脚本会等样式dom结构加载完成后才会执行,此时页面已经渲染完了,所以只有同步脚本和个别情况下加了async的脚本会阻塞渲染
26. 手写防抖和节流
防抖
function debounce(fn,wait){
let timer = null;
return function(){
if (timer) {
clearTimeout(timer)
timer = null
}
timer = setTimeout(()=>{
fn.call(this, arguments)
}, wait)
}
}
节流
function throttle(fn, wait){
let timer = null
return function(){
if(!timer){
timer = setTimeout(()=>{
fn.call(this,arguments)
tiemr = null
}, wait)
}
}
}
27. 三次握手,四次挥手
三次握手: 指建立一个TCP连接时,需要客户端和服务端总共发送3个包,以确认双方的接受能力和发送能力是否正常,为后面的可靠性传送做准备
四次挥手: 终止TCP链接只需要发送4个包,客户端或服务端均可主动发起挥手动作
28. 状态码
- 1XX (信息性状态码) 表示接受的请求正在处理
- 2XX (成功性状态码) 表示请求正常处理完毕
- 3XX (重定向状态码) 表示需要附加操作以完成请求
- 4XX (客户端错误状态码) 表示服务器无法处理请求
- 5XX (服务端错误状态码) 表示服务器处理请求出错
29. 手写对象扁平化
const flatten = (arr) => {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur)? flatten(cur) : (cur)
}, [])
}
30. setTimeout 实现 setInterval
setTimeout(function f() {
setTimeout(f,interval);
}, interval)
31. 水平垂直居中方法
flex布局,父元素:display:flex; justify-content: center; align-items: center;子绝父相,子元素:left:50%; top:50%; transform: translate(-50%, -50%)子绝父相,子元素:left:0; top:0; botton:0; right:0; margin: auto- 文字的话,text-align:center; line-height 和 height 相等
32. Promise.allSettled()
用来确认一组异步操作是否全都结束了,包含了“
fulfilled” 和 “rejected” 两种情况
Promise.allSettled()方法接受一个数组作为参数,数组每个成员都是一个Promise对象,并返回一个新Promise对象,只有等到参数数组的所有Promise对象都发生状态变更(不管是fulfilled还是rejected),返回的Promise对象才会发生状态变更
33. 盒子模型分哪两种
W3C标准的盒子模型(标准盒模型)IE标准的盒子模型(怪异盒模型)
34. 输入url后会发生什么
- 浏览器向
DNS服务器请求解析该URL中的域名所对应的IP地址- 解析出IP地址后,根据该IP地址和默认端口80,和服务器
建立TCP连接- 浏览器发出读取文件(URL域名后面部分对应的文件)的HTTP请求,该请求报文作为TCP
三次握手的第三个报文的数据发送给服务器- 服务器请求作出
回应,并把对应的html文本发送给浏览器释放TCP连接- 浏览器将该html文本
显示内容
35. 手写ajax(使用promise封装)
function getJSON(url) {
let promise = new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (this.readyState !== 4) return;
if (this.status === 200) {
resolve(new Error(this.statusText));
} else {
reject(new Error(this.statusTzext));
}
};
xhr.onerror = function () {
reject(new Error(this.statusText));
};
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
xhr.send(null);
});
return promise;
}
36. 前端有什么安全性问题
- XXS攻击(跨站脚本攻击)
- CSRF安全漏洞(跨站请求伪造)
- 文件上传漏洞
- 限制URL访问,越权访问
- 不安全的加密存储
- SQL注入攻击
- OS命令注入攻击
37. 面向对象的继承方法
- 原型对象
- 原型链继承
- 空函数作为中介继承
- 绑定继承
- 组合继承
- 拷贝继承
- ES6的class继承
38. 手写一个组合继承
function superType() {}
function subType() {
//构造函数继承
superType.call(this, ...arguments);
}
//原型链继承
subType.prototype = new superType();
//对象增强
subType.prototype.constructor = subType();
39. defer 和 async 的区别
一、
有async,加载和渲染后续文档元素的过程将和script.js的加载与执行异步
二、
有defer,加载后续文档元素的过程将和script.js的加载异步,但是script.js的执行要在所有元素解析完成之后,DOMContentLoaded事件触发之前完成
40. 工厂模式的理解
工厂模式:主要是用来实例化有共同接口的类,它可以动态的决定应该实例化哪一类
主要分为三种形态:简单工厂模式、工厂方法模式、抽象工厂模式一、简单工厂模式
主要有一个静态方法,用来接收参数,并根据参数进行switch或if判断来决定返回实现同一接口的不同类的实现
二、工厂方法模式
把工厂类定义为接口,以多态的形式来削弱工厂类的职能,对简单工厂进一步的解耦,降低简单工厂模式的风险,提高可维护性,可扩展性
三、抽象工厂模式
工厂模式下一个工厂只能生产同类同品 的产品,而抽象工厂模式下一个工厂可以生产多类同品 的产品
41. $nextTick 的使用场景
- 在vue生命周期的
created()里进行DOM的操作一定要使用nextTick(),因为created执行的时候DOM还未渲染- 在方法里操作DOM,由于dom元素还没有更新,因此打印出来的还是为改变之前的值,而通过
this.$nextTick()获取到的值为dom更新之后的值
42. Vue2 数据发生变化到页面变化的基本流程
- 先将数据进行
Obj.defineProperty()进行绑定,判断数据为数组或者对象进行绑定- 当页面开始渲染会定义
updateComponent方法,这个方法主要就是为了调用render方法- 进入
render的时候会执行页面使用的值,这时候会触发该数据的get属性- 开始进行
绑定依赖- 之后通过
patch方法将节点进行更新替换或者新增- 如果数据发生变化,会执行数据的
set方法,这时数据的Dep.notify会调用Dep.notify会去调用绑定的Watcher,促使它更新,并收集所有改变,一次性进行改变- 调用
Watcher的run()方法,run方法会调用updateComponent方法进行render更新
43. vue中v-for如何实现对数组、对象、数字的遍历
数组:v-for="(item, index) in/of arr"
对象:v-for="(value, index) in obj“
数字:v-for="(item,index) in 数字" index从1开始
44. 哪些因素会影响重排重绘
- 页面首次进入渲染
- 浏览器resize
- 元素位置和尺寸发生改变
- 可见元素的增删
- 内容发生改变
- 字体font改变
- CSS伪类激活
45. GET 和 POST 的区别
| GET | POST |
|---|---|
| get参数在请求地址 | post参数在请求体 |
| get有长度限制 | post没有长度限制 |
| get有缓存 | / |
| get返回的结果不会变 | post结果可能不一样 |
46. HTTP请求的几种类型
GET、POST、OPTIONS、PUT、DELETE、HEAD
47. HTTP缓存的方式
一、强制缓存
指只要浏览器缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边
二、协商缓存
与服务端协商之后,通过协商结果来判断是否使用本地缓存
48. 浏览器的存储方式
1)属于文档对象模型:
documentcookie
2)属于浏览器对象模型:localStroage、sessionStorage,indexDB区别:
cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据传给服务器,仅在本地缓存- 存储大小限制不同,
cookie数据不能超过4K,同时每次http请求都会携带cookie,所以cookie只适合保存很小的数据。
sessionStorage和localStorage虽然也有存储大小限制,但比cookie大很多,可以达到5MB或更大- 数据有效期不同:
类型 数据有效期 sessionStorage 仅在当前浏览器窗口关闭前有效 localStorage 始终有效,窗口或浏览器关闭也一直保保存,因此用作持久数据 cookie 只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
- 作用域不同:
类型 作用域 sessionStorage 不在不同的浏览器页面中共享,即使同一个页面 localStorage 在所有同源页面窗口中都是共享的 cookie 在所有同源页面窗口中都是共享的
49. transform、transition、translate、animation的区别
transition、transform、animation这三个是CSS属性,而translate是2D转换的一种方法,是transform的一个属性值transform是2D、3D变换的属性,只是动画可用的一种属性,因为使用transform不会引起页面的重排transition、animation才是动画中必备的两个属性
50. CSS画三角形
div {
border-left:50px solid transparent;
border-right:50px solid transparent;
border-bottom:50px solid #333;
width:0;
height:0;
}