1. css选择器有哪些和权重级别?可继承的属性有哪些?
选择器类型:
行内样式:style
ID: #id
类: .class
属性:[type=“text”] [ 属性=值 ] 或者[属性]
伪类: :hover
标签: div、p
伪元素:::first-line
通用: *
子选择器、相邻选择器:如>、+
优先级由高到低为:!important > 行内样式 > ID选择器 > 类/属性/伪类选择器 > 标签/伪元素选择器 > 通配符、子选择器、相邻选择器 > 继承
可以继承的属性包括:font-family、font-size、font-weight、line-height、color、text-align、margin、padding、border、background、visibility等
2. 冒泡机制,冒泡和捕获的区别
冒泡机制:事件从子级向父级传递
捕获事件:事件从父级向子级传递
事件委托:将事件加到父级上,利用冒泡的原理,触发子级执行效果。
document.addEventListener(‘event’,function(){},true),默认为false冒泡事件,true是捕获事件
e.stopPropagation() 阻止冒泡
e.preventDefault()阻止默认
3. http1.1、http2的区别
http1.1:
1. 长连接
2. 管道,同一个tcp连接可以同时发多个请求,但响应是串行的
3. 支持断点续传,新增了range字段
4. host头处理
5. 缓存处理,新增了协商缓存的一些缓存策略
6. 新增了24个错误状态码
http2
1. 头部压缩
2. 多工(多路复用):客户端和浏览器都可以同时发送多个请求和响应,不用按顺序串行返回,避免了对头堵塞。
3. 头信息和数据体都是二进制格式
4. 数据流
4. 强缓存和协商缓存
强缓存:不会向服务器发送请求,直接从缓存中读取资源,通过两种请求头实现:Expires、Cache-control过期时间和过期时长。Cache-control优先级大于Expires。相对稳定和不常更新的静态资源使用强缓存。
协商缓存:强制缓存失效后,浏览器携带缓存向服务器发送请求,由服务器根据缓存标识确定是否使用缓存,缓存生效返回304,失效返回200;通过设置两种HTTP Header实现:Last-Modified Etag;
Last-Modified缺点:根据资源最后修改时间判断,如果对文件有编辑操作即使内容没有更新,这个时间也会更新不准。资源修改时间单位是秒,如果1秒内修改文件,根据时间也无法识别资源更新。
Etag缺点:服务器对于生成etag需要付出额外的计算开销,如果资源尺寸较大数量多且修改比较频繁,生成etag就会影响服务器的性能。
综合考虑:html文件使用协商缓存;
图片采用强缓存且过期时间不宜过长;
样式表文件style.css可以考虑在样式文件命名中增加文件的版本号,当文件修改后,文件的url不同了 重新请求;
涉及用户隐私的js文件避免代理服务的缓存。
5. cookie和session区别
第一次登陆后服务器返回cookie给浏览器,然后浏览器保存在本地,当该用户发送第二次请求时,就会自动把上次请求存储的cookie自动给服务器,服务器根据cookie判断是哪个用户。
cookie:存储在浏览器端,数量有限,不同的浏览器有不同的存储大小,单条cookie限制一般不超过4kb
session:存储在服务器,更加安全不容易窃取。
6. cookie、localStorage和sessionStorage区别
都是同源的保存在浏览器端
cookie:默认不设置时间是关闭浏览器失效,设置时间后,在时间内关闭窗口或cookie都不会失效。
sessionStorage:不在不同浏览器窗口共享,即使是同一页面;localstorage和cookie在所有的同源窗口共享
localStorage:生命周期是永久,sessionStorage在当前会话下有效,关闭窗口失效。
localStorage在不同窗口是同步改变的,sessionstorage不同步改变。
跨域方案:
cookie:jsonp、nginx反向代理
localStorage:使用postmessage和iframe
7. webpack优化
一、babel-loader的处理文件排除node-modules
二、cache-loader缓存性能开销比较大的loader,将处理结果缓存到磁盘里
三、使用多线程处理打包:
HappyPack打包任务分解成多个子线程并行的执行,子线程执行完再发给主线程
thread-loader在worker池中运行加载器loader
DllPlugin&DllReferencePlugin可以把特定的类库提前打包成动态链接库,减少打包类库的次数
四、noParse 配置那些模块文件的内容不需要进行解析的第三方大型类库(如jquery、lodash)
五、ignorePlugin 忽略某些某些特定的模块,让webpack不把这些指定的模块打包进去
六、webpack-bundle-analyzer 使用打包文件分析工具,生成代码分析报告,提高代码质量和网站性能
七、speed-measure-webpack-pugin费时分析插件
八、删除无用的css样式,可以使用mini-css-extract-plugin插件
九、tree-shaking 删除无用代码(webpack5已内置)
十、以cdn方式加载资源
webpack一些配置操作:https://editor.csdn.net/md/?articleId=130930659
8. js怎么判断数据类型
一、typeof:可以判断的类型有Number,String,Boolean,Undefined,Object,Function,Symbol。 能准确判断基本类型,对象类型不能做出准确判断。typeof null是object。
二、instanceof:A instanceof B判断A是否为B的实例,instanceof检测的是原型,判断对象A的原型链中是否有B的原型。基本类型不能用instanceof判断类型,由于undefined和null没有原型,所以用instanceof会报错。
三、constructor:能判断基本数据类型string、number、boolean和对象类型(array、function等等),undefined和null会报错。
四、Object.prototype.toString.call()
9. js原型和原型链
原型:每个函数都有prototype属性,称之为原型,因为原型的值是个对象,也称为原型对象。作用:存放一些属性和方法;在js中实现继承。
原型链:每个对象都有__proto__属性,指向它的构造函数的原型对象(arr.proto === Array.prototype)。原型对象也是对象,也有__proto__属性,指向原型对象的原型对象,这样一层一层形成的链式结构称为原型链,最顶层找不到则返回null。
原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己构造函数的显式原型。
原型链:所有对象的__proto__指向他们构造函数的prototype原型对象,当调用这个对象不存在的属性或者方法时,它会一层一层往上找,直到null为止。
10. 如何理解JS的异步?
JS是一门单线程的语言,这是因为它运行在浏览器的渲染主线程中,而渲染主线程只有一个。
而渲染主线程承担着诸多的工作,渲染页面、执行JS都在其中运行。如果采用同步的任务,就有可能导致主线程产生阻塞,从而导致消息队列中的很多任务无法得到执行,这样一来,一方面会导致繁忙的主线程白白的消耗时间,另一方面导致页面无法及时更新,给用户造成卡死现象。
所以浏览器采用异步的方式来避免,当某些任务发生时,比如计时器、网络、事件监听,主线程将任务交给其他线程去处理,自身立即结束任务的执行,转而执行后续代码。当其他线程完成时,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。
在这种异步模式下,浏览器永不阻塞,从而最大限度的保证了单线程的流畅运行。
11. js是单核的,异步是怎么实现的?
js是单线程的,有evenloop事件循环机制,是指任务在主线程不断进栈出栈的一个循环过程,过程是:
1.1执行全局script同步代码,形成一个执行栈;
1.2在执行代码时遇到异步任务时把宏任务加入宏任务队列,微任务加入微任务队列;
1.3等执行栈中的同步任务全部执行完后,先去检查微任务队列是否有任务,逐步将任务加入执行栈中;
1.4微任务队列和执行栈都清空后,再去检查宏任务中是否有任务,也放入执行栈中执行。
1.5循环这个过程
宏任务有:setTimeout、setInterval、setImmediate(node)、ajax 、postMessage、DOM事件
微任务有:Promise.then/catch/finally、Proceess.nextTick(node)
微任务在dom渲染之前执行,宏任务在dom渲染之后执行
12. 作用域
全局作用域:window拥有的变量,用var定义的变量会自动存储在全局对象window里;最外层定义的变量;未声明直接赋值的变量。
局部作用域:在函数中声明的变量。
13. 继承
原型继承:继承子类中的私有属性会变成原型中的共有属性;创建子类型的时候不能向父类型的构造函数中传递参数。
构造函数继承:解决了私有属性变公有的问题,可以传递参数。构造函数里的function等属性被声明了多次。
组合继承
派生继承
14. js深拷贝实现方式?
手写递归方式,注意循环引用问题
通过JSON对象实现:JSON.parse(JSON.stringify())
通过jQuery的extend方法实现
lodash函数库的cloneDeep方法
15. JSON.parse(JSON.stringfy(obj))深拷贝的问题
如果obj里存在时间对象,得到的是字符串
存在RegExp、Error对象,得到的是空对象
存在函数、undefined,会把函数和undefined丢失
存在NaN、Infinity和-Infinity,会变成null
存在构造函数生成的,构造函数会被丢弃;
对象中存在循环引用(环形变量)会报错
16. require和import区别?
(1)require是AMD规范引入方式;import是ES6的一个语法标准。
(2)require是运行时调用,import是编译时调用,必须写在文件开头。
17. 首屏优化
取决于网速和资源大小
压缩,图片压缩、代码压缩
异步加载和按需加载,按需引入第三方库
写代码精简
18. 兼容性问题
样式初始化:margin、padding设置为0,一些标签的处理
使用不同类型的浏览器内核前缀
js兼容性,使用babel转换
19. 高并发问题
(1) 通过增加软件技术或者升级硬件来提高单机性能。
(2) 通过单机架构性能,使用缓存来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间。增加单机硬件性能,增加cpu核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G
(3) 通过增加服务器数量节点个数来扩展系统性能。
20. 浏览器渲染过程
(1)浏览器输入url,dns查询,解析成ip地址,等待响应获取内容
(2)浏览器渲染,解析html建立dom树
(3)解析css构建css树,合并render树
(4)布局render树,回流重绘,绘制页面信息。
(5)浏览器将隔层信息发送给gpu,gpu将各层合成,显示在屏幕上
dns域名服务器查询过程:
(1)客户机提出域名解析请求,并将该请求发送给本地的域名服务器。
(2)当本地的域名服务器收到请求后,先查询本地的缓存,如果有记录,则把域名查询结果返回。
(3)。。。
头信息可以设置预解析url
21. 闭包的概念、用途、应用场景、优缺点?
概念:闭包是指有权访问另一个函数作用域变量的函数(内部函数使用了外部函数的变量)。
作用:保护函数的私有变量不受外部的干扰,形成不销毁的内存。
把一些函数内的值保存起来,实现方法和属性的私有化。
应用:设计模式中的单例模式。
防抖和节流。
函数珂里化:有接受多个参数的函数变成接受单一参数的函数。
缺点:过度使用会导致内存占用过多,谨慎使用闭包合理释放。
形成原因:内部函数存在外部作用域的引用就会导致闭包
闭包存储为止:堆内存,如果在栈中会自动回收。
22. 手写new操作符步骤
(1) 创建一个对象
(2) 实例对象的__proto__关联到原型prototype上
(3) 把this的指向这个构造函数
(4) 返回这个新对象
23. promise
更加优雅的书写复杂的异步函数,解决回调地狱的问题,promise构造函数返回一个promise对象,promise对象有几个方法:
then:处理promise成功状态的回调函数
catch:处理promise失败状态的回调函数
finally:无论promise是成功还是失败,都会执行的回调函数
return不能中断promise的执行,通过throw跳转至catch中断
24. web worder
Web Worker是html5标准中提供的一种javascript多线程解决方案,它可以让我们在浏览器中创建多个js线程,并行处理复杂任务,从而提高页面的性能和用户体验。
Web Worker可以把一些耗时的js代码放到后台线程中运行,以免堵塞主线程,与主线程是独立的,没有共享的数据,只能通过消息传递来通信,保证了多线程的安全性。
Web Worker不能访问dom,也不能访问主线程中的全局变量和函数。
使用过程:1. 创建Worker对象:在主线程中使用new Worker()方法传入要执行的js文件的url
-
发送消息:使用woker.postMessage()方法向worker线程发送消息
-
接收消息:在主线程中,使用worker.onmessage方法监听worker线程 发送的消息
-
终止worker线程:在主线程中,使用worker.terminate()来终止worker线程。
使用场景:1. 计算密集型任务:图像处理、数据计算等,可以使用Web Worder来将计算任务放到后台线程中执行,避免阻塞主线程。
- 长时间运行的任务:如音视频解码,文件读取等。
25. webpack中loader和plugin区别
loader:处理非js模块,把其他语言转为js,运行在项目打包之前
plugin:处理loader无法解决的问题,在整个周期
26. ajax、fetch和axios区别
fetch:原生js,没有使用xhr,基于promise
只对网络请求报错,对400/500都当作成功
默认不带cookie,需要添加配置项
不支持中止,不支持超时控制
不能原生检测请求的进度,xhr可以
ajax:针对MVC编程,基于原生xhr开发,文档架构不够清晰
可以使页面在不重新加载的情况下请求数据并进行局部更新
axios:基于promise的http请求库,对原生xhr的封装
支持promise API
客户端支持防止CSRF
提供了一些并发请求的接口
从nodejs创建http请求
请求和响应拦截
可以取消请求
自动转换json数据
27. 性能优化
(1)性能优化的指标
页面要打开的够快,操作时响应的也要够快,能长时间运行不卡顿。
1. 首次内容绘制(First Contentful Paint):浏览器首次将任意内容绘制到屏幕上的时间点
2. 最大内容绘制(Largest Contentful Paint):可见的最大图像或文本块的呈现时间
3. 速度指标(Speed Index):首评可见内容绘制在屏幕上的速度。
4. 可交互事件(Time to Interactive):指搜有页面内容都已经成功加载,且能够快速对用户的操作做出反应的时间点。
5. 总阻塞事件(Total Blocking Time):首次内容绘制和可交互事件的总时间
6. 累计布局偏移(Cumulative Layout Shift):衡量的是页面整个生命周期中每次元素发生的非预期布局偏移得分的总和。每次可视元素在两次渲染帧中的起始位置不同时,就说是发生了LS(Layout Shift)。
Web Vitals
1. 加载性能 LCP:显示最大内容元素所需时间
2. 交互性 FID:首次输入延迟时间
3. 视觉稳定性 CLS:累积布局配置偏移
(2)性能分析工具
Lighthouse(灯塔)
WebPageTest(在线免费性能测评网站)
(3)首屏优化方案:
减少http请求(合并图片雪碧图;缓存;压缩css和js,代码压缩;异步加载第三方资源)
图片优化(使用png格式,压缩图片,懒加载图片,避免使用dataurl)
使用cdn节省带宽
28. 内存泄漏场景
(1)意外的全局变量:未声明变量;使用window创建的变量;避免创建全局变量或者使用严格模式在js头部文件或函数顶部加上user strict
(2)闭包引起的内存泄漏:将内部函数定义在外部,解除闭包
(3)没有清理的dom元素引用:虽然删除了元素但是还是保留着对dom的引用;将dom置为null
(4)被遗忘的定时器或者回调:手动删除定时器;removeEventListener移除事件监听。
可以使用performace录制
29. 关键渲染路径优化
避免使用@import加载css
script尽量放在页面底部(放前面会阻塞dom的解析和渲染)或者加上defer/async延迟加载或异步加载
30. for…in和for…of
for…in可以对普通对象遍历可枚举属性或键名。可枚举属性:属性描述符的enumerable的值为true
for…of可以对可迭代对象(array、map、set、string)进行循环迭代获取键值,不可以对对象进行遍历。一个可迭代对象必须实现了inerator方法,还需要next方法,在迭代器内部不断的调用next方法,直到返回结果是{done:true,value:’’}为止
31. ts中interface和type区别
interface只能定义对象类型;type可以定义任何类型,基础类型、联合类型、交叉类型
interface可以使用extends和implements扩展,type使用交叉类型合并
32. 盒模型及区别
标准盒模型:元素宽度不包含padding和border
怪异(IE)盒模型:width+margin width已经包含了padding+border
box-sizing:content-box;//标准盒模型
box-sizing:border-box;//怪异盒模型
33. 去除浮动
清除浮动主要是为了解决,父元素因为子级元素浮动引起的内部高度为0的问题
(1)额外标签法
(2)父元素添加overflow属性(触发BFC方式,清除浮动)
(3)使用after伪元素清除浮动
(4)使用before和after双伪元素清除浮动
(5)或者给父元素定义好高度
34. css定位方式
fixed:固定定位,脱离文档流,不占位置,参照整个浏览器的窗口,固定在当前window不动
absolute:绝对定位,脱离文档流,不占位置,参照父元素,会随参照对象元素的宽高变化而变化
relative: 相对定位,不脱离文档流,占位置,给绝对定位的父元素设置较多
sticky: 粘性定位,做一些吸顶效果,不占位置,参照整个浏览器窗口
没有滚动条的情况下没差异,有滚动条的情况,fixed定位不会随滚动体移动而移动,absolute会随滚动体移动
35. rem、em区别
rem:根据网页的根元素来设置字体大小。通过设置html(根元素)的font-size,内部元素的1rem = 1 * font-size
em:根据其父元素的字体大小设置
36. less、scss、css区别
css可以被浏览器直接识别;scss和less都是css预处理器
(1)编译环境不一样,less是基于js在客户端处理,scss是基于ruby在服务端处理。
(2)变量符不一样,less是@,scss是$
(3)输出设置,less没有输出设置,scss提供了四种输出设置
(4)scss支持条件语句,可以使用if else for循环等,less不支持
37. link和@import区别
都是外部引入css的方式,推荐使用link
加载顺序,link跟页面同时加载,@import在页面加载完被加载
兼容性:@import是css2引入的在es5以上使用;而link是html元素,不存在兼容性问题。
link权重大于@import
38. 数组排序
(1)js中的sort()方法
(2)选择排序:每次找到最小的元素,记录索引,与头部索引交换
(3)冒泡排序,比较相邻元素,大的放后面,第一次循环最后的元素是最大的
39. bind、call、apply的区别
相同点:都是改变this指向的,第一个参数都是this要指向的对象,可以利用后续参数传参
不同点:call和bind的参数是依次传参,一一对应的;apply的第二个参数为数组。call和apply都是对函数直接调用,而bind返回的是一个函数。
40. 跨域三要素,怎么处理跨域?
协议、域名、端口
webpack proxy正向代理,打包之后就没有这个proxy,适用于开发阶段
jsonp
nginx反向代理中间件
cors 后端配置
41. flex布局的详细属性有哪些?
flex-direction:主轴的方向 row/row-reverse/column/column-reverse
flex-wrap:如果一个轴线排不下,换行方式 nowrap/wrap
flex-flow:flex-direction和flex-wrap简写,默认row nowrap
justify-content:主轴的字元素排列方式:flex-start/flex-end/center/space-around/space-between/space-evenly
align-items:设置测轴上的子元素排列方式:flext-start/flex-end/center/stretch
flex-grow:还有剩余空间时,为此元素安排多少的空间
flex-shrink:此元素宽度超出父级时,压缩多少
flex-basic:制定元素宽度,优先级高于width
flex:缩写flex-grow、flex-shrink、flex-basic
42. html开头!DOCTYPE作用
声明在文档的最前面,告诉浏览器以何种方式来渲染页面,触发浏览器的标准模式
43.圣杯布局、双飞翼布局
中间内容优先渲染,左右宽度固定,中间内容宽度自适应
body
<div class=”container”>
<div class=”center”></div>
<div class=”left”></div>
<div class=”right”></div>
</div>
css
.container{
padding-left:150px;
padding-right:200px;
box-sizing:border-box;
}
.center{
float:left;
width:100%;
}
.left{
width:150px;
position:relactive;
left:-150px;
float:left:
margin-left:-100%;
}
.right{
width:200px;
float:right;
margin-right:-200px;
}
双飞翼布局
body
<div class=”container”>
<div class=”center”>
<div class=”inner”></div>
</div>
<div class=”left”></div>
<div class=”right”></div>
</div>
css
.container{
padding-left:150px;
padding-right:200px;
box-sizing:border-box;
}
.center{
float:left:
width:100%;
}
.inner{
margin-left:150px;
margin-right:200px;
}
.left{
width:150px;
float:left;
margin-left:-100%;
}
.right{
width:200px;
float:left;
margin-left:-200px;
}
44. 隐藏元素的方式
display:none; 彻底消失
visibility:hidden; 占位消失;
opacity:0; 过渡动画,一般会结合transition;
宽度高度设为0;
position:absolute;left:-9999px;top:-9999px;
45. 图片3像素问题
排列图片时图片之间会出现三个像素的缝隙。
(1)给图片添加display:block
(2)给父元素添加font-size:0;解决li之间的间距;解决行内元素(图片等)之间的间距;
(3)vertical-align设置非baseline默认值即可
46. 开启bfc方法
页面上一个隔离的独立容器,容器内不会受外部样式的影响
(1)float:left/right
(2)position:absolute/fixed 除了static
(3)display:inline-block/flex
(4)overflow:hidden/auto/scroll/inherit 除了visible
特性:1. 内部元素会在垂直方向上一个接一个的放置;
2. 垂直方向元素距离靠上下文margin最大值来设置
3. bfc内区域不会和float区域重叠
4. 计算bfc区域高度时会将float的高度也算进去
5. 容器内部的子元素不会影响外部元素
margin重叠:借助bfc的概念,是原本两个受影响的元素,将其中一个增加bfc父级,因为bfc的独立容器属性,不会影响外部元素。
清除浮动:1. 使用伪类或空白块元素占位,必须是display:block且增加clear:both。clear:both是使元素左右 两侧都不允许浮动元素存在。
2. 将父级设置为bfc,因为bfc区域高度会将float的高度也算入,所以不会使父级无高度。
47. webpack打包过程
(1)初始化参数阶段:从配置文件中读取参数和shell命令传入的参数合并得到最终打包参数
(2)编译阶段:从入口模块分析,调用匹配文件的loaders对文件进行处理。分析模块依赖关系,递归进行模块
编译工作
(3)输出阶段:整理模块依赖关系,将处理后的文件输出到output中
48. 去重代码
(1)利用Set和转换数组方法
[...new Set(arr)]
(2)for循环或者for…of
let res = []
for(const value of arr){
if(!res.includes(value)){
res.push(value)
}
}
(3)数组filter方法和indexOf方法
arr.filter((value,index)=>{
return arr.indexOf(value)===index
})
49. 防抖节流代码
防抖和节流是js中常见的两种函数优化方式,为了解决高频率触发某个函数而导致的性能问题,都可以通过闭包实现。
防抖:在短时间内连续触发同一个函数时,只执行最后一次。
let timer = null
function throlle(fn,timeout){
if(timer){
clearTimeout(timer)
timer = null
}
timer = setTimeout(()=>{
fn.call(this)
},timeout)
节流:将函数的执行频率限制在一定时间范围内
let timer = null
function dedounce(fn,timeout){
if(timer)return
timer = setTimeout(()=>{
clearTimeout(timer)
fn.call(this)
},timeout)
}
50. 写代码,一个字符串里出现最多的字符,出现了几次?
let str = '134983999902'
let arr = str.split('')
let count = 1
arr.reduce((pre,value,index)=>{
if(pre[value]){
pre[value]++
if(pre[value]>count){
count = pre[value]
}
}else{
pre[value] = 1
}
return pre
},{})
console.log(count)
51. css设置垂直居中方式
(1)单行文本,line-height等于height;
(2)display:inline-block;行内块元素设置vertical-align:middle;
(3)绝对定位加transform:translateY(-50%);
(4)使用flex布局设置alight-item:center。
52. 堆和栈的区别
栈:存放基本数据类型;基本数据类型有固定的大小和值;基本类型在当前环境执行结束时销毁;
基本数据类型:string、number、boolean、null、undefined、 symbol、bigint
堆:存放引用数据类型;引用类型不确定大小,引用地址是固定的存在栈中;引用类型在引用它的变量不在时,会被垃圾回收。
引用数据类型:Object、Array、Function、Date、RegExp、Map、Set
53. 深拷贝和浅拷贝
浅拷贝:浅拷贝复制了对象的引用指针而不是复用对象本身,复制后的对象和原对象共享一个内存地址,其中一个对象的变化会影响另一个对象。浅拷贝只能拷贝第一层的基本数据类型。浅拷贝比赋值多了一层。
深拷贝:对拷贝后的数据修改不影响原数据,两个对象不共用一块内存地址。
浅拷贝的实现方式:
1. Object.assign():可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。
2. lodash的clone方法
3. 展开运算符…
4. Array.prototype.concat,数组的拼接方法
5. Array.prototype.slice,数组的截取方法
6. 手写浅拷贝
深拷贝的实现方式:
1. JSON.parse(JSON.stringify()),对于有些数据类型不能正确转换,比如如果obj里存在时间对象,得到的是字符串;存在RegExp、Error对象,得到的是空对象;存在函数、undefined,会把函数和undefined丢失;存在NaN、Infinity和-Infinity,会变成null;存在构造函数生成的,构造函数会被丢弃;
2. lodash的cloneDeep函数
3. jQuery.extend函数
4. 手写递归实现,注意循环引用的问题
54. Map、WeakMap和Object的区别
(1)键的类型:Map的键可以是任何类型,WeakMap的键必须是对象类型,而Object的类型必须是字符串或者symbol类型;
(2)垃圾回收:Map和Object的键是强引用,即使键对象没有其他引用,也不会被垃圾回收;WeakMap的键是弱引用,当键对象没有其他引用时,会被垃圾回收;
(3)可枚举性:Object的属性是可枚举的,可以用for…in或者Object.keys()等遍历,而Map和WeakMap是不可枚举的;
(4)方法和操作:Object和WeakMap没有size属性,无法获取大小。Object的大小需要手动计算;
(5)原型链:Object具有原型链,而Map和WeakMap不具有原型继承,是独立的数据结构。
55. 浏览器重绘和回流
回流reflow:浏览器需要重新布局时(例如改变元素的宽高、位置等),就会触发回流。回流会重新计算元素的几何属性(位置和大小),并重新构造渲染树,很消耗性能。
重绘repaint:当浏览器需要更新元素的外观时(例如改变元素的背景颜色、字体颜色等),但不会影响它在文档流中的位置时,就会触发重绘。重绘不会影响文档流的几何属性,只是重新绘制元素的外观。
回流的产生:
(1)dom树的机构变化:例如节点的增减、移动。
(2)元素尺寸变化(边距、填充、边框、宽高)。
(3)获取某些属性,比如offsetTop/offsetLeft/offsetWidth/offsetHeight,scrollTop/scrollLeft/scrollWidth/scrollHeight,clientTop/clientLeft/clientWidth/clientHeight,getComputedStyle(),多次使用这些值时应进行缓存。
(4)内容改变,比如文本改变或图片大小改变引起计算值宽高变化。
(5)页面渲染初始化。
(6)浏览器窗口尺寸改变,如resize事件发生时。
重绘的产生:
当render tree的一些元素需要更新属性,而这些属性只是影响元素的外观,不影响布局,比如background- color、visibility、outline等。
减少回流和重绘的方法:
(1)尽量不用内联样式style属性,操作元素样式用添加去掉class类的方式。
(2)给元素添加动画的时候,可以把该元素的定位设置成absolute或者fixed(脱离文档流),不会影响其他元素,减少回流。
(3)在需要获取那些引起浏览器回流的属性值时,缓存变值。
(4)尽量在dom的最末端改变class。
(5)避免使用table布局。
(6)避免使用css的js表达式。
(7)使用css3动画代替js动画。
(8)使用transform代替top/left属性。
(9)避免循环操作dom。
(10)减少dom深度和dom数量,可以减少浏览器解析dom的时间。
(11)批量操作dom。
(12)在内存中操作dom,使用文档碎片DocumentFragment。
(13) 使用防抖和节流,限制频繁触发。
(14)及时清理环境,及时清除定时器、事件监听器等,回收内存。
56. es6新属性
(1)解构
(2)字符串的扩展方法
(3)剩余参数
(4)展开数组参数
(5)箭头函数
(6)proxy代理器
(7)class类
(8)extends类的继承
(9)set/map/symbol数据类型
(10)for…of
(11)迭代器生成器
57. 输入url并回车发生了什么?
(1)URL解析
(2)域名解析:DNS查询解析
(3)tcp连接:三次握手
(4)http请求
(5)响应请求
(6)页面渲染
58. dispatch更改state是异步,为什么?如何处理?
vuex是一个状态集中管理器,解决多组件之间的数据通信。
state:存储公共数据。
mutations:修改数据方法的集合,必须是同步。
getters:蕾丝与computed计算属性(利用现有的状态进行计算得到新的数据)。
actions:异步操作。
modules:模块化拆分。
actions和mutation包含的是一些方法,但是actions不能直接修改数据,它的作用是提交mutations,mutation里面包含的是具体操作数据的方法。
59. 作用域
js作用域:js中的变量若在当前作用域中没有,会向父级寻找,直到最顶层
块级作用域:js ES5中没有块级作用域,如果要形成,可以通过()()自执行函数实现函数中的作用域为块级作用域;ES6中每个{}都是一个块级作用域。
60. null和undefined的区别
null:一个对象被人为的置为空对象,而非一个变量最原始的状态。
undefined:一个变量最原始的状态,而非人为操作的结果,比如
(1)声明了一个变量,没有赋值;
(2)访问对象上不存在的属性;
(3)函数定义了行参,但是没有传递实参;
(4)使用void对表达式求值。
61. 闭包
讲讲闭包理解:指的是一个函数可以访问另一个函数作用域中的变量,外层变量不会被垃圾回收机制回收。优点是:避免全局变量污染。缺点是:容易造成内存泄漏。
为什么闭包会引起内存泄漏:闭包内部的匿名函数在调用后把外层的变量也包含在自己的作用域内了。此变量属于一直在引用中,所以垃圾回收机制不会将他回收。导致会比其他function占用更多内存。
如何解决闭包引起的内存泄漏:1.调用时先用变量保存闭包函数,在执行完成后为此变量赋值为null,清除指针即可使垃圾回收机制正常回收。2.可以借助()()自执行函数,在闭包内部不使用return function而是自执行函数取代,因为自执行函数是私有块级作用域,即可在执行结束后将引用对象销毁。
其他场景的内存泄漏及解决方案:setTimeout及setInterval未在使用后清理,或循环多个定时任务,clear时有缺漏。解决方案:每个定时器应使用变量保存,且在使用后clearTimeOut/clearInterval。
addEventerListener、jquery的on、vue的$on等引用dom后需要做解绑处理
addEventerListener使用removeEventerlistener解绑
62. http和https区别
http为明文传输,不安全;https多了ssl加密协议,为加密传输。
用的端口不一样,http是80,https是443。
https协议的主要作用分为两种:一种是建立一个信息安全通道来保证数据传输的安全,另一种是确认网站的真实性。https协议需要用到ca申请证书,ssl依靠证书来验证服务器的身份,为浏览器和服务器之间的通信加密。
63. async和defer的区别
async是异步下载并立即执行,然后文档继续解析;
defer是异步加载后解析文档,然后再执行脚本。比较稳定。
如果脚本代码依赖于页面中的dom元素(文档是否解析完毕),或者被其他脚本文件依赖,用defer。
64. css引入的几种方式
(1)行内样式:写在style属性里
(2)内嵌式:把css样式写入style标签内
(3)外链式:通过link标签链接
(4)导入式:在style标签内通过@import导入
外链式link的css是跟页面一起加载,而导入式@import是先显示html再加载css
65. ES6模块和CommonJS规范区别
(1)CommonJS支持动态导入,运行时加载;ES6不支持,是静态编译,编译时输出;
(2)CommonJS同步加载,用于服务端,文件放在本地磁盘,读取速度快,同步导入卡住主线程也不受影响;
ES6是异步加载,用于浏览器端,不能同步加载。
(3)CommonJS模块输出的是值拷贝,内部变化影响不到值的变化;ES6模块输出的是值引用,原始值变化,加载的值也会跟着变化。
(4)关于模块顶层的this指向问题,在CommonJS顶层this指向当前模块;而在ES6模块this指向undefined
66. 路由守卫
(1)全局守卫:所有路由配置的组件都会触发
beforeEach(to, from,next) 在路由跳转之前触发,可以做权限校验
beforeResolve(to, from,next) 全局解析守卫,在所有组件内守卫和异步组件路由被解析之后触发
afterEach(to,from) 路由跳转之后触发,可以让对应的页面标题改变
(2)路由守卫:单个路由配置的时候也可以设置的钩子函数
beforeEach(to, from,next) 在进入组件时被调用
(3)组件内守卫:在组件内执行的钩子函数
beforeRouteEnter(to,from,next) 进入该组件时调用
beforeRouteUpdate(to,from,next) 路由更新但是内容不会改变
beforeRouteLeave(to,from,next) 离开组件时调用
参数:to:即将要进入的目标路由对象
from:即将要离开的路由对象
next:涉及到next参数的钩子函数,必须调用next方法来resolve这个钩子,否则路由会中断在这,不会 继续往下执行。
67. 小程序冷热启动
冷启动时小程序已经被销毁,热启动时未被销毁再次打开。
冷启动会重新走app中的onLaunch,热启动不会触发,只会触发onshow周期
小程序占用内存过高或小程序置入后台超过五分钟。
68. 小程序运行环境
小程序的运行环境分为渲染层和逻辑层,由两个线程管理。其中WXML模版和WXSS样式工作在渲染层,js脚本工作在逻辑层。渲染层的页面使用webview进行渲染,逻辑层运行在JSCore中,并没有一个完整的浏览器对象,因而缺少相关的DOM API和BOM API,没有window、document、navigator、localstorage等浏览器专用的js API。这一区别导致了前端开发非常熟悉的一些库,例如 jQuery、 Zepto 等,在小程序中是无法运行的。同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
好处:一个小程序存在多个界面,所以渲染层存在多个WebView线程,这两个线程的通信会经由微信客户端做中转,逻辑层发送网络请求,也经由微信客户端转发。逻辑层和视图层分离,好处是js运算不卡渲染,最简单直接的感受就是:窗体动画稳。
坏处:这两个线程的通信会经由微信客户端做中转,这两层互相通信,是有损耗的。
69. uni-app的生命周期
一、应用声明周期,只在App.vue里执行
1. onLaunch:应用初始化完成触发一次,全局只触发一次(登陆全局变量)
2. onShow:应用启动的时候,从后台进入前台触发
3. onHide:应用从前台进入后台会触发
4. onError:报错时触发
二、页面生命周期
1. onload :监听页面加载,其参数为上个页面传递的数据,参数类型为object,只执行一次或者页面刷新会执行。
2. onShow :监听页面显示
3. onReady:监听页面初次渲染完成,在onShow之后执行
4. onHide 监听页面隐藏
5. onUnload 监听页面卸载
6. onResize:监听窗口尺寸变化
7. onPullDownRefresh:监听用户下拉动作,一般用于下拉刷新
8. onReachBottom:页面滚动到底部的事件
9. onTabItemTap:点击tabbar触发
10. onShareAppMessage:点击右上角分享
11. onPageScroll:监听页面滚动
12. onNavigationBarButtonTap:监听原生标题栏按钮点击事件
13. onBackPress:监听页面返回
14. onNavigationBarSearchInputChanged:监听原生标题栏搜索输入框输入内容变化
15. onNavigationBarSearchInputConfirmed:监听原生标题栏搜索输入框搜索时间,用户点击键盘上的搜索按钮
16. onNavigationBarSearchInputClicked:监听原生标题栏搜索输入框点击事件
三、组件生命周期,跟vue一致
1. beforeCreate
2. created
3. beforeMount
4. mounted
5. beforeUpdate
6. updated
7. beforeDestroy
8. destroyed