主要分为2部分:
1、渲染引擎
a、渲染引擎负责获取网页的内容,html,xml,图像等等,然后加入css,计算网页的显示方式
2、JS引擎,例如V8
二、常见的内核
Trident(IE ,MaxThon,TT,360,搜狗)
Gecko(FF,mozillaSuite/SeaMonkey,Netscape6及以上版本)
Presto(opera7及以上,现在为Blink(webkit的分支))
Webkit内核(Safafi,Chorme)
三、cookie,sessionStorage,localStroage,indexDB
特性 | cookie | lcoalStorage | sessionStorage | indexDB |
---|---|---|---|---|
数据周期性 | 一般由服务器生成,可以设置过期时间 | 除非被清理,否则一直存在 | 页面关闭就清理,会话级 | 除非被清理,否则一直存在 |
数据存储大小 | 4K | 5M | 5M | 无限 |
与服务器通信 | 每次都会携带在head中,对性能有影响(如果过大) | 不参与 | 不参与 | 不参与 |
此外,cookie的安全性
value:如果用于保存用户登录状态,应该将值加密,不能使用明文的用户标识
http-only:不能通过JS访问Cookie,减少XSS攻击
什么是xss攻击?
secure:只能在协议为HTTPS的请求中携带
same-site:规定浏览器不能再跨域请求中携带Cookie,减少CSRF攻击
什么是CSRF攻击?
浏览器对象模型
常用API
1、window对象
alert() ……
open()
onerror : 监听全局报错(资源加载,js代码报错)
addEventListener(‘error,’)
setTimout() :轮训 ,模拟setTnterval
setTnterval():
窗口大小……
窗口位置……
location对象
hash
host
serach
……
navigation : isOnline 判断用户是否断网
history对象
go()
back()
forword()
length
pushState
onPopState
浏览器事件模型
事件捕获— 目标阶段 — 事件冒泡
true ,捕获阶段 ,默认是false ,代表冒泡
e.target 绑定事件的元素
e.currentTarget //当前点击的元素
Ie 不支持事件捕获
阻止事件传播
1、stopPropagation :阻止事件传播(不论是捕获还是冒泡)。
阻止到哪里事件就在哪里 停止
IE : e.cancelBubble = true 阻止事件冒泡
面试题:场景设计题
阻止默认行为:
e.preventDefault ,比如说 a标签
ie : e.returnValue = true
封装一个没有兼容问题的addEvent
class BomEvent{
constructor(el){
this.el = el
}
addEvent(type,handler){
if(this.el.addEventListener){
this.el.addEventListener(type,handler,false) //false表示冒泡,默认也是false
}else if(this.el.attachEvent){
this.el.attachEvent('on'+type,handler) //IE 不支持事件捕获
//handler.call(this.el)
}else{ //兜底
this.el['on'+type] = handler
}
}
removeEvent(type,handler){
if(this.el.removeEventListener){
this.el.removeEventListener(type,handler)
}else if(this.el.attachEvent){
this.el.detachEvent('on'+type,handler) //IE 不支持事件捕获
}else{ //兜底
this.el['on'+type] = null
}
}
}
function stopPropagation(event){
if(event.stopPropagation){
event.stopPropagation
}else{
event.cancelBubble = true
}
}
function preventDefault(event){
if(event.preventDefault){
event.preventDefault
}else{
event.returnValue = true
}
}
事件委托\事件代理
//事件委托+ 伪数组(获取的node节点数组)
ul.addEventListener('click',function(e){
let target = e.target //点击的目标元素
if(target.tagName.toLowerCase() === 'li'){
let liList = Array.from(document.querySelectorAll('li'))
let index = liList.indexOf(target) //拿索引
alert(`内容为${target.innerHTML} ,索引为${index}`)
}
})
浏览器请求相关内容
3、浏览器原生请求 xhr
const xhr = new XMLHttpRequest()
xhr.upload.onprogress //原生的上传的进度
xhr.timeout = 3000 //超时
xhr.ontimeout = ()=>{ //超时处理函数
}
xhr.upload.onprogress = p =>{
const percent = Math.round((p.loaded / p.total)*100) + '%'
}
4、fetch
- fetch:默认不带cookie
- 错误不会reject出去
- 不支持设置超时
- 可以中止fetch, signal, new Abort ```javascript const controller = new AbortController() //中止请求 fetch(‘http://domin/service',{ method:’GET’, credentials :’same-origin’ , //同源携带 cookie ,localStroge传值 signal:controller.signal //中止请求 }).then((response)=>{ if(response.ok){ return response.json() } throw new Error(‘http error’) }).then(json=>{ console.log(json) }).catch(error=>{ console.error(error) }) controller.abort() //中止请求 //手动设置超时
function ontimeout(url,options,time = 3000){ return new Promise((resolve,reject)=>{ fetch(url,options).then(resolve).catch(reject) setTimeout(reject,time) }) }
5、封装一个ajax工具函数,处理对于异步函数的超时处理
```javascript
//一个通用的异步函数的超时逻辑
interface IOptions {
url:string;
type?:'GET' | 'POST';
data:any;
timeout?:number;
}
export function asyncAjax(options:IOptions ={
url:'',
type:'GET',
data:{},
timeout:3000
}){
if(!options.url) return
return new Promise((resolve,reject)=>{
let xhr,timer
const onStateChange = ()=>{
xhr.onreadystatechange = ()=>{
if ( xhr.readyState == 4 ) {
clearTimeout(timer);
if(xhr.status>=200 && xhr.status<300 || xhr.status==304){
resolve(xhr.responseText)
}
} else {
reject(xhr.status);
}
}
}
const formatUrl = (obj)=>{
let resArr = []
for(let k in obj ){
resArr.push(`${k}=${obj[k]}`)
}
return resArr.join('&')
}
if((window as any).XMLHttpRequest){
xhr = new XMLHttpRequest() //chrome
}else{
xhr = new ActiveXObject('Microsoft.XMLHTTP') //IE
}
if(options.type.toUpperCase()==="GET"){
xhr.open('GET',options.url + formatUrl(options.data) )
onStateChange() //这个要放在前面,避免
xhr.send()
}else if(options.type.toUpperCase()==="POST"){
xhr.open('POST',options.url)
xhr.setRequestHeader(
"ContentType",
"application/x-www-form-urlencoded" //浏览器编码好的名称/值对格式,ajax默认提交格式
//而axios默认的请求头就是application/json,
)
/****
* 0(UNSENT):未初始化。尚未调用open()方法
1(OPENED):启动。已经调用open()方法,但尚未调用send()方法
2(HEADERS_RECEIVED):发送。己经调用send()方法,且接收到头信息
3(LOADING):接收。已经接收到部分响应主体信息
4(DONE):完成。已经接收到全部响应数据,而且已经可以在客户端使用了
*/
// 必须在调用open()之前指定onreadystatechange事件处理程序,才能确保跨浏览器兼容性.否则将无法接收readyState属性为0和1的情况
onStateChange() //告诉xmlhttp当它的state发生改变的时候执行 ,这个要放在前面,避免
xhr.send(options.data)
}
if (options.timeout) { //超时后就取消掉请求,并reject
timer = setTimeout(() => {
xhr.abort();
reject("timeout");
},options.timeout);
}
})
}
6、请求头
为什么cnd域名和 业务域名不一样?
- 安全,用户信息不包括给第三方cdn厂商。
- request header携带了不必要的资源,增加带宽消耗
referer ?
- 判断当前浏览器来自哪个页面,从哪里来,标志访问路径
user-agent
7、返回头
access-control-allow-origin:*
conrent-encoding:gzip
set-cookie:
8、status
304 :协商缓存,服务器资源未修改
强缓存
max-age
expired:服务器时间不准
协商缓存
- last-modified : 打开后不做修改就保存,这个时间也会变化
- etag :整体文件内容hash,耗时间耗性能
9、单页应用的index.html如果一定要做缓存,适合做哪种缓存
- 协商缓存
- 因为里面的js和css文件本身都是有hash的,都是js.hash,css.hash,需要及时更新,协商缓存检测到变化了就必须要更新,因为迭代很快,
- 真实情况下:一般不做缓存,原因有1.本身文件比较小2、需要快速迭代实时更新