记录最近一次前端面试中被提问到的基础问题
css部分
盒模型
本质是一个盒子,包括盒子实际大小、内边距、边框、外边距
css优先级计算
元素选择符:1,
class选择符:10,
id选择符:100
元素标签:1000
!important 优先级最高,如果优先级相同,则靠近生效。
css常用伪元素
:link, :sivited, :hover, :active, :focus, ::before, ::after, :first-child, :last-child, :nth-child(n), :checked
居中对齐:
水平居中:
行内元素:text-align:center,块级元素:margin: 0 auto, absolute + transform, flex + justify-content:center
垂直居中:
line-height: height,absolute + transform,flex + align-items:center, table
水平垂直居中:
absolute + transform, flex+justify-content + align-items
去除浮动影响:
父级div定义Height
父元素添加overflow:hidden或auto
子元素最后添加空的div,添加样式clear:both
父元素添加伪类和zoom:1
外边距塌陷问题:
外层使用padding代替marrgin
内层元素添加透明边框、内层元素添加定位、外层元素添加overflow:hidden,内层元素添加浮动或display:inline-block,内层元素添加padding:1
css预处理器 sass lass
特点:嵌套,变量,单位转换,循环语句,条件语句,复用
Javascript部分
数据类型:
基本数据类型:string、number、boolean、null、undefined
引用数据类型:Object、Array、Function
检测数据类型
通过typeof可以返回string、number、undefined、boolean、Object、function,可以判断基本数据类型,不能正常的检测null、object、array。可以通过Object.prototype.toString.call()来检测;
闭包
闭包就是能够读取其他函数内部变量的函数
闭包可以读取函数内部的变量,可以让这些变量始终保存在内存中
优点:减少全局变量,减少传递函数的参数
缺点:占用内存资源 (可以将不需要的变量赋值为null,系统会自动回收)
原型链
原型:每个对象都会在内部初始化一个属性就是prototype(原型),通俗的说原型就是一个模板
原型链:如果一个对象内部不存在这个属性就会去这个对象的原型对象上去找,一层一层知道原型对象为null。修改原型实例时所有继承与该对象的实例属性发生改变。
继承
原型链继承 缺点:属性被所有实例共享,不能传参
借用构造函数继承 优点:可以传参,避免属性共享 缺点:每次创建实例都会创建一遍方法
组合继承:使用原型链实现原型方法的继承,通过构造函数实现实例属性的继承。优点:融合原型链继承和构造函数继承的优点比较常用。缺点:调用两次父类构造函数。
使用ES6的class/extends实现继承。
拷贝
浅拷贝
利用Object.assign(对象的合并)实现
利用结构赋值实现
深拷贝
利用JSON的stringify和parse实现,但是值为undefined和function不会拷贝回来
通过递归实现深拷贝
this.指向:谁调用指向谁;箭头函数中的this指向执行上下文。
防抖与节流
防抖:将高频操作优化为只在最后一次执行
节流:每隔一段时间后执行一次
ES6、ES7都有哪些新增语法
let/const 块级作用域不存在变量提升
解构赋值
class/extend 类声明与继承
set/map 新的数据结构
箭头函数
promise
promise主要用于异步请求,可以将异步操作队列化。解决了地域回调问题,便于维护。
promise的三种状态: pending/reslove/reject 。pending就是未决,resolve成功,reject拒绝
链式调用:使用.this方法之后会再次返回一个promise对象可以继续使用.then调用,参数是上个.then的返回值。
await\async 是以同步代码的形式处理异步。
async用于生命一个异步函数(返回promise),await等待一个异步方法执行完成。
数组的常用方法
forEach、push/pop、unshift/shift、content、join、slice、indexof...
任务队列和事件循环
js是单线程的,为了避免阻塞,会将异步任务放在任务队列中,当主线程执行完毕,会读取任务队列,将可执行的异步任务添加到执行栈中执行,遵循先微后宏。
跨域问题
由于浏览器同源策略,不能请求不用域名的接口和消息。
跨域的解决方案:
cors:服务端响应头设置Access-Control-Allow-Origin允许跨域
jsonp:借助script标签可跨域的原理 只能发送git请求。
浏览器部分
Web优化
浏览器访问优化:
减少http请求:脚本合并,图片合并,文件压缩,使用浏览器缓存,减少cookie传输
图片懒加载
css引入放在顶部,javascript引入放在底部(可能会造成阻塞)
代码优化
减少dom操作,减少重排和回流,减少作用域链查找,代码压缩,提取公共代码
css不要使用*,减少选择器的重叠,提取项目公共样式,使用预处理工具
CDN加速
localStorage和seccionStorage和cookie
都是在客户端储存数据的
cookie始终在http请求中携带,localStorage和seccionStorage只用于本地保存
大小不同,cookie大小4k左右,localStorage和seccionStorage5M
生命周期不同:cookie可以自己设置过去时间(默认浏览器关闭),seccionStorage浏览器窗口关闭之前有效,localStorage永久有效,除非手动清除
作用域不同: sessionStorage只能在当前窗口适应,cookie和localStorage可以在所有同源窗口中使用。
重绘和重排
当元素样式发生变化后,浏览器需要触发更新,有两种类型即重绘和重排
重绘:当元素改变不影响布局,触发局部重绘,损耗较小
重排:元素的尺寸结构发生变化,页面重新渲染,损耗较大
尽量避免频繁的重排
从输入url到页面展示的过程
DNS解析
在浏览器输入网址,浏览器会首先解析这个域名,先查看本地hosts文件,如果有就直接使用hosts文件里的ip地址。如果没有浏览器会发起一个请求到本地DNS服务器查询,如果没有再向DNS根服务器查询,再向域服务器上查询直到查到域名解析服务器的地址,本地DNS服务器向解析服务器发送请求,获取域名和ip的对应关系,并将对应关系保存到本地,方便下次查询
建立TCP链接
当拿到域名对应的ip地址后,会向web服务器程序发起TCP链接请求(三次握手)
1.客户端发送一个带有SYN数据包给服务器
2.服务器收到后返回一个SYN/ACK的数据包,传达确认信息
3.客户端再回传一个ACK数据包,链接成功
向服务器发送http请求
建立TCP连接之后,发起http请求(请求行、请求头、请求正文)
服务器端处理请求,并返回处理结果
浏览器解析渲染页面
首先浏览器解析html生成dom树,然后解析css文件构建渲染树,浏览器根据渲染树将绘制到页面上。
常见的http状态码
-
1xx:指示信息–表示请求已接收,继续处理。
-
2xx:成功–表示请求已被成功接收、理解、接受。
-
3xx:重定向–要完成请求必须进行更进一步的操作。
-
4xx:客户端错误–请求有语法错误或请求无法实现。
-
5xx:服务器端错误–服务器未能实现合法的请求。
100:表示处理中
200:表示请求成功
201:请求成功并且服务器创建了新的资源
202:服务器接收请求,尚未处理
301:请求网页已永久移动到新的位置
302:临时重定向
304:上次请求后网页未修改
400:请求格式错误
401:请求未授权
403:禁止访问
404:找不到资源
500:服务器段错误
503:服务器暂时无法处理
vue部分
说一下vue的设计原理
vue是一套用于构建用户界面的渐进式框架(渐进式的理解就是根据开发的需要可以不用深度的使用vue,既可以把它当成js库也可以把它当做一整套解决方案,比较灵活和便于扩展),其核心原理是的双向数据绑定,vue用数据劫持结合发布者-订阅者模式实现双向数据绑定,通过Object.defineProperty()来劫持各个属性的setrer,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
vue组件之间的通信
-
父子组件的通信---props/emit
父组件通过peops给子组件传值,子组件通过emit触发父组件定义的自定义事件来传值。
通过ref和parent/children直接访问组件实例实现通讯
-
兄弟组件的通信---emit/on
兄弟组件之间引入同一个用于通讯的中间组件,通过触发中间组件的emit和on来实现通信
3.使用全局状态管理vuex。
vuex的使用
vuex就是用于存放多个组件共用参数的一个仓库,存放的数据发生改变各个组件都会更新。
使用步骤
1.安装、引入、定义数据。
2.通过this.$store.state.名称使用属性,通过this,$store.commit.方法修改属性(不常用),或者使用mapState,mapMutations使用(常用)
3.vuex实例文件中的state用于定义数据,mutations用于修改state的值,getters用于监听state的最新状态,类似于计算属性。
vue动态组件
动态组件就是将几个组件放在同一个挂载点上,通过变量来决定显示那个组件(<component is="one"></component>)
vue插槽
插槽其实就是子组件提供父组件使用的一个占位符,父组件可以向插槽中填充内容。
插槽分为匿名插槽、具名插槽、默认插槽、作用域插槽(可以传递参数)。
vue生命周期
beforeCreate、created、beforeMounte、mounted、(beforeUpdata、updata)、boforeDestory、destored.
created:实例创建、属性绑定完成,可以在此进行一些请求数据操作。
mounted:实例挂载完成,可以在此进行dom操作
vue路由 vue-router
安装,引入路由、定义规则,{path:'',name:'',component:'',children:[]}
声明式导航:<router-link :to="..."> 对应的显示放在router-view 中
编程式导航:this.$router.push({path:'',name:'',params:''}) 。
使用watch监听路由的变化
vue路由传参
1.使用router-link进行路由导航传递参数,在子组件中使用this.$route.params.属性名 接收参数
2.$store.push中通过hash的方式传递参数,使用this.$route.params.属性名 接收参数
3.通过路由属性中的name匹配的路由,通过params传参,使用this.$route.params.属性名 接收参数 url后不显示,
4.通过路由属性中path匹配的路由,通过query传参,使用this.$route.query.属性名 接收参数 url显示
vue中的watch和computed
watch和computed都可以监听到数据发生变化,不同的是computed有缓存机制,只有依赖数据发生改变才会重新计算,computed不支持异步,更适应于一个数据受多个影响的情况,而watch没有缓存,支持异步,更适用于一个数据影响多个数据的情况。
vue组件中的data为什么要返回一个函数
因为组件可能会有多个实例,如果data是对象的形式会导致多个实例共用一个data数据,那么一个实例数据改变会影响其他实例。data返回函数则每个实例都会返回全新的data对象,互不影响
vue中的v-if和v-show的区别
v-if是增加和删除dom元素,v-show是控制元素的现实和隐藏
vue中的v-if和v-for的优先级
v-for的优先级会优于v-if,如果同时出现每次渲染都会先执行循环再执行判断,浪费性能。
可以再循环外层加template,在这一层进行判断,也可以提前处理好需要循环的变量
vue中v-for中的key有什么用
高效的更新DOM元素,减少Dom操作,提高性能
不设置key会有一些隐藏bug 比如复选框组件
nextTick
下次dom更新循环结束之后执行延时回调,可用于获取更新后dom。因为dom更新是异步的,使用nextTick会将代码添加到异步任务队列中
vue混入 - mixins
可将一段代码重复使用的一种方式,可以将代码直接合并带需要合并的地方
vue组件化的理解
将程序拆分为不同的组件可以提高代码的复用性,降低代码的耦合,提高开发效率,便于后期维护。
vue的性能优化
路由懒加载
适应v-show复用DOM
v-for与v-if避免同时使用
纯粹的数据展示不需要做响应式,节省性能(object.freeze)
vue组件销毁时手动清除定时器。
图片懒加载
第三方插件按需引入
合理的分割组件,将一些耗时的操作切割为单独的组件。
vue3.0新特性 --谦虚点,就说不会
虚拟dom的重写,基于proxy的数据响应式。
webpack
webpack是一个JavaScript静态模块打包工具,可以根据依赖将需要用到的模块打包成一个或多个bundel,
核心概念:入口(entry)输出(output)预处理器(loader) 插件(plugins)
loader:
webpack通过配置loader规则,调用外部脚本或工具,可以处理更多格式的的文件,比如处理sass、lass、es6/7转化为es5等。
一些常用的loader:file-loader, url-loader, image-loader, babel-loader, css-loader, style-loader
plugins:
plugins可以扩展wabpack的功能,比如打包优化和压缩代码。
webpack构建流程
初始化参数=>开始编译=>确定入口=>编译模块=>完成编译模块=>输出资源=>输出完成
利用wabpack优化前端性能:压缩代码,删除多余代码和注释,提取公共代码,利用CND加速
小程序部分
生命周期函数
onLoad:页面加载时触发,只调用一次,可以获取当前页面路径中的参数
onShow:页面显示/切入前台触发
onReady:页面初次渲染完成触发,只调用一次
onHide: 页面隐藏或切入后台时触发
onUnload:页面卸载时触发
小程序路由
wx.navigateTo(), 保留当前页面跳转到应用内的某个页面,不能跳转到tabbar页面
wx.navigateBack(),关闭当前页面返回上一个页面
wx.redirectTo(), 关闭当前页面跳转到应用内的某个页面,不能跳转到tabbar页面
wx.switchTab(), 跳转到tabbar页面,并关闭所有的非tabbar页面
wx.reLaunch(), 关闭所有页面,打开到应用内的某个页面
微信小程序的优劣势
即用即走,不用安装省流量,依托微信流量,便于推广传播,开发成本低
入口深,用户留存问题,限制比较多