setTimeout能否实现精确定时?为什么
不能,它的第二个参数只能保证何时将代码添加到浏览器的任务队列中,不能保证添加到任务队列就会立即执行
scss和css区别?
可以使用变量、嵌套,scss为带有缩进的sass
webpack打包优化方案
1、多进程打包
2、Tree shaking
3、开启缓存
多叉树深度优先遍历和广度优先遍历
let arr=[]
const dfs=(node)=>{
if(!node)return
arr.push(node.id)
if(node.children&&node.children.length>0){
node.children.forEach(item=>dfs(item))
}
}
dfs(node)
const bfs=(node)=>{
if(!node)return
let arr=[]
let stack=[]
let tmpNode
stack.push(node)
while(stack.length){
tmpNode=stack.shift()
arr.push(tmpNode)
if(tmpNode.children&&tmpNode.children.length){
tmpNode.forEach(item=>stack.push(tmpNode.children))
}
}
return arr
}
浏览器缓存原理
当发起http请求之前,会现在本地缓存中查找是否有对应的缓存,根据缓存标识判断缓存是否有效,如果有效则从本地缓存中读取数据,否则进入协商缓存。根据是否要向服务器发送http请求,缓存可分为强缓存和协商缓存
(1)强缓存
浏览器第一次请求时,服务器返回资源,浏览器将资源缓存在本地,并且服务器会通知浏览器一个缓存事件,下次请求如果在缓存时间内,直接使用缓存,否则进入协商缓存
HTTP1.0中使用expires关键字,HTTP1.1中使用Cache-control关键字
expires是一个绝对时间,表示资源在这个时间之前均有效;cache-control是一个相对时间,表示自上次请求多少秒时间内资源有效。cache-control的优先级高于expires,解决了expires因为浏览器时间被手动修改导致缓存判断错误的问题
cache-control常用字段:
- max-age:最大有效时间
- no-cache:必须向服务器发送请求查询缓存是否有效
- no-store:不能使用缓存
(2)协商缓存
用于判断缓存是否有用,主要包括两个字段:Last-Modified和Etag
Last-Modified表示资源最后的修改时间,下一次请求相同资源时,浏览器将Last-Modified的值写入到If-Modified-Since字段中,浏览器将If-Modified-Since的值和Last-Modified的值对比,如果一致则说明资源未被修改,返回304状态码,从本地缓存中读取数据;否则返回200状态码和新的数据
Last-Modified的缺陷在于无论资源是否发生实质性修改,都会将该资源返回客户端,并且无法识别1s内修改多次的情况。Etag优先级高于Last-Modified,它主要配合If-None-Match使用,Etag的值实际上是文件的hash值
position有哪些属性值
(1)static:正常布局,top等属性失效
(2)relative:相对于原有位置偏移,原有位置会被空白占位
(3)absolute:元素会脱离文档流
(4)fixed:相对于屏幕视口的位置,当元素祖先的transform、perspective或filter非none时,容器由视口改为该祖先
(5)sticky:元素在跨越特定阈值之前为相对定位,之后为固定定位
水平垂直居中
.div{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
.div{
display:flex;
justify-content:center;
align-items:center;
}
.div{
position:absolute;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;
}
.div{
display:grid;
justify-content:center;
align-items:center;
}
基础数据类型和引用数据类型的区别
基础数据类型将值存放在栈中,引用数据类型将引用变量名称存储在栈中,但实际对象存储在堆中,栈中内存地址指向堆中实际对象,当把引用类型复制给另一个变量时,实际上复制的是引用变量的地址
判断类型的方法
(1)typeof
需要注意的几个:
typeof NaN //number
typeof null //object
不区分对象、数组、正则,它们的结果都是object
(2)instanceof
判断构造函数的原型是否出现在实例对象的原型链上
const s='1111'
s instanceof String //false
const obj = Object.create(null)
obj instanceof Object //obj原型为null
手写instanceof:
function myinstanceof(obj,type){
let proto=Object.getPrototypeof(obj)
let prototype=type.prototype
while(true){
if(proto===null)return false
if(proto===prototype)return true
proto=Object.getPrototypeof(proto)
}
}
注意:基本类型和null直接返回false
new的原理
(1)创建一个新对象
(2)将构造函数原型指向新对象原型
(3)改变构造函数this指向新对象
(4)判断返回值类型,如果为引用类型,直接返回;否则返回新对象
function myNew(){
let obj={}
let fn=[].shift.call(arguments)
obj.__proto__=fn.prototype
let res=fn.call(obj,arguments)
return res instanceof Object?res:obj
}
http和https的区别
- http端口号为80看,而https端口号为443
- https需要证书验证,而http不需要
- http是无状态的,https是有状态的,需要身份认证
- http采用明文传输,https采用加密传输,更加安全
https加密过程?什么时候是对称加密,什么时候是非对称加密
https采用非对称加密交换对称加密的密钥,使用对称加密传输数据
(1)对称加密
同一个密钥可以同时用于加密和解密
(2)非对称加密
使用公钥进行加密,使用私钥进行解密
https加密过程分为两个阶段:证书认证阶段、数据传输阶段
- 客户端第一次向服务器发起https请求,连接到服务器443端口
- 服务端向第三方申请一个证书,返回一个包含公钥和身份标识的数字证书。服务端将包含公钥的数字证书发送给客户端
- 客户端对证书进行验证,如果证书合法,客户端随机生成随机数,然后用证书中的公钥进行加密。https第一次请求就结束了
- 客户端第二次向服务端发起http请求,将加密后的随机数发送给服务端,服务端使用服务端私钥对加密后的随机数进行解密得到对称加密的密钥。然后对需要返回给客户端的数据使用对称加密密钥家吗,发送给客户端
- 客户端收到后,使用对称加密密钥进行解密,得到数据
async和defer的区别
都用于异步加载脚本
区别:async加载完就会立即执行,不能保证脚本按次序加载,defer是按次序加载