前端知识点一

141 阅读5分钟

1、从输入url到浏览器呈现页面中间经历了什么?

  • 在输入url的时候,会进行本地历史记录和标签页的查询,提供模糊查询效果

  • 浏览器查找当前URL是否存在缓存,并比较缓存是否过期 HTTP缓存有多种规则,根据是否需要向服务器重新发起请求来分类,将其分为强制缓存,对比缓存。 强制缓存:判断HTTP首部字段:Expires 和 cache-control。 Expires是一个绝对时间,即服务器时间。浏览器检查当前时间,如果还没到失效时间就直接使用缓存文件。但是该方法存在一个问题:服务器时间与客户端时间可能不一致 cache-control中的max-age保存了一个相对时间。例如Cache-Control: max-age = 484200,表示浏览器收到文件后,缓存在484200s内有效。 如果同时存在cache-control和Expires,浏览器总是优先使用cache-control。 对比缓存:通过HTTP的 last-modified(最新-改进),Etag字段进行判断。 last-modified 表示请求的URL(资源)最后一次更新的时间。下一次浏览器请求资源时就发送if-modified-since字段。服务器用本地Last-modified时间与if-modified-since时间比较,如果不一致则认为缓存已过期并返回新资源给浏览器;如果时间一致则发送304状态码,让浏览器继续使用缓存。 Etag:资源的实体标识(哈希字符串),当资源内容更新时,Etag会改变。服务器会判断Etag是否发生变化,如果变化则返回新资源,否则返回304。

  • DNS解析URL对应的IP 首先查询本地host文件是否有对应地址的一个映射关系,如果没有找到,会查找本地DNS解析器缓存,如果还是没有找到则会查找本地DNS服务器,最后迭代查询,按根域服务器库(.com,.cn,.vip,.top...)->顶级域(com)->->第二层域子域(baidu.com),最后根据baidu.com的域名找到相应的IP,返回给浏览器。

  • 根据IP建立TCP连接(三次握手) 浏览器用这个IP地址与服务器建立TCP连接,如果用的是HTTPS,还有完成TLS / SSL的握手。 第一次握手: 建立连接时,客户端发送syn包(syn=j)到服务器,并进入等待服务器确认的状态; 第二次握手: 服务器收到syn包,必须确认客户端的syn(ack=j+1),同时自己根据syn生成一个ACK包,此时服务器进入等待状态; 第三次握手: 客户端收到服务器的ACK包,向服务器发送确认,此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。

  • 发送HTTP请求 在建立好连接以后呢,构造HTTP请求,在构造请求的过程中,要填充少量至HTTP头部

  • 服务器解析请求返回结果 然后通过这个TCP连接发起HTTP请求,当服务器收到这个HTTP请求以后,返回给浏览器以HTTP页面作为包体的HTTP响应。

  • 浏览器解析结果并渲染页面 根据html代码生成DOM树 ,在解析到外部的css和js文件时,向服务器发起请求下载资源,如果是CSS代码会在下载的同时进行解析,如果是JS代码会阻塞页面加载,根据CSS代码生成OM树,然后生成layout树(重排),生成painting树(重绘),然后生成渲染树。

  • 关闭TCP连接(四次挥手) 第一次握手是浏览器发完数据,然后发送FIN请求断开连接。 第二次握手是服务器向客户端发送ACK,表示同意。 第三次握手是服务器可能还有数据向浏览器发送,所以向浏览器发送ACK同时也发送FIN请求,是第三次握手。 第四次握手是浏览器接受返回的ACK,表示数据传输完成。

相关链接: 输入url至呈现页面过程 三次握手 四次挥手

2、js基本数据类型

Number、String、Boolean、undefined、object、symbol、bigInt、Null js基本数据类型

3、typeof返回类型

number、 string、boolean、 undefined、object、symbol、bigint、function typeof NaN == 'number'

4、最大安全值和最大值

Number.MAX_SAFE_INTEGER 进行运算不会丢失精度 Numebr.MAX_VALUE js能表示的最大值

5、this的绑定规则

显示绑定 call、apply、bind 隐式绑定 obj对象的属性为函数时,内部指向obj 默认绑定 函数内部的this默认指向window new绑定 this的绑定规则

6、call、bind、apply

改变this指向的方法 call参数为列表、apply为数组、立即执行 bind为等待状态

Math.max.call(null, 1,3,5,2,4)  
Math.max.apply(null, [1,3,5,2,4])

call、apply、bind

7、promise

创建对象

let p1 = function(){
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      resolve('成功1!')
    },1000)
  })
}
let p2 = function(){
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      resolve('成功2!')
    },1000)
  })
}
let p3 = function(){
  return new Promise((resolve, reject)=>{
    setTimeout(()=>{
      resolve('成功3!')
    },1000)
  })
}

链式操作

p1().then((data)=>{
  console.log(data)
  return p2()
}).then((data)=>{
  console.log(data)
  return p3()
}).then((data)=>{
  console.log(data)
})

race函数

Promise.race([p1(),p2(),p3()]).then((data)=>{
  console.log(data)  //[p1,p2,p3]
}).catch((err)=>{
  console.log(err)
})

all函数

Promise.all([p1(),p2(),p3()]).then((data)=>{
  console.log(data)    //p1
})

promise原理

8、观察者模式

class Event{
  constructor(){
    this.list = []
  }
  subscrible(type, handler){
    if(this.list[type]){
      this.list[type].push(handler)
    }else{
      this.list[type] = [handler]
    } 
  }
  unSubscrible(type, handler){
    if(this.list[type]){
      let index = this.list[type].indexOf(handler)
      this.list[type].splice(index, 1)
    }
  }
  publish(type){
    if(this.list[type]){
      this.list[type].forEach((item)=>{
        item()
      })
    }
  } 
}
let event = new Event()
function load(index){
  console.log('load')
}
function click1(index){
  console.log('click')
}
function click2(index){
  console.log('click')
}
event.subscrible('load', load)
event.subscrible('click', click1)
event.subscrible('click', click2)
event.publish('load')
event.publish('click')

9、发布订阅模式

class Dog{
  call(){
    console.log('汪汪')
  }  
}
class  Pubsub{
  constructor(){
    this.list = []
  }
  subscrible(call){
    this.list.push(call)
  }
  publish(){
    this.list.forEach((item)=>{
      item()
    })
  }
}
let pubsub = new Pubsub()
class  Thief{
  constructor(){
    this.list = []
  } 
  action(){
    pubsub .publish()
  }
}
let thief = new Thief()
let dog1 = new Dog()
let dog2 = new Dog()
pubsub .subscrible(dog1.call)
pubsub .subscrible(dog2.call)
thief.action()

链接

10、eventLoop (堆、栈、队列)

1、先执行主线程(包含执行栈和堆) 2、遇到宏队列(macrotask)放到宏队列(macrotask) 3、遇到微队列(microtask)放到微队列(microtask) 4、主线程执行完毕(执行栈Stack被清空) (栈内存出栈后自动销毁) 5、执行微队列(microtask),微队列(microtask)执行完毕 6、执行一次宏队列(macrotask)中的一个任务,执行完毕 (宏任务有可能产生微任务) 7、执行微队列(microtask),执行完毕 8、依次循环...