一些前端面试题总结

1.浏览器缓存

浏览器的缓存机制【即HTTP缓存机制】是根据HTTP报文的缓存标识进行的,而HTTP报文分为:

HTTP请求报文(request)

报文格式:请求行 - HTTP头(通用信息头,请求头,实体头) - 请求报文主体(POST请求时)

HTTP响应报文(reponse)

报文格式:状态行 - HTTP头(通用信息头,响应头,实体头) - 响应报文主体

缓存过程

浏览器发起HTTP请求 - 服务器响应请求

一些前端面试题总结_第1张图片

浏览器第一次HTTP发起请求后,浏览器缓存中并没有保存该请求的缓存结果和缓存标识,则浏览器会根据响应报文中HTTP头中的缓存标识决定是否缓存结果,如果“是”,将请求结果和缓存标识存入浏览器缓存中。

缓存规则

当浏览器向服务器发起请求时,服务器会将缓存规则放入HTTP响应报文中的HTTP头中和请求结果一起返回。

一、强缓存:

强缓存有三种情况:

1.不存在该缓存结果和缓存标识,强缓存失效,浏览器直接向服务器发起请求

一些前端面试题总结_第2张图片 2.存在该缓存结果和缓存标识,但该结果已失效,强缓存失效,使用协商缓存

一些前端面试题总结_第3张图片

 3.存在该缓存结果和缓存标识,且该结果未失效,强缓存生效,直接返回结果

一些前端面试题总结_第4张图片

控制强缓存的字段:

Expires 的值为服务器返回请求结果缓存的到期时间,当再次发起请求时,如果客户端的时间小于Expires的值,直接使用缓存结果。

缺点:因为Expires是将客户端时间与服务器时间进行比较,当客户端与服务端的时间因某些原因出现误差,会使强缓存失效。

Cache-Control(优先级更高)主要取值为 public【所有内容都将被缓存,即客户端和代理服务器都可缓存】、 private【只有客户端可以缓存所有内容,是Cache-Control的默认值】、 no-cache【客户端缓存内容,但是否使用缓存需要经过协商缓存来验证决定】、 no-store【所有内容都不会被缓存,即不使用强缓存和协商缓存】、 max-age=xxx【缓存内容的失效时间】。

缺点:在缓存过期后,服务器不管资源有无发生变化,都会再次将资源文件进行读取和返回。

二、协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,服务器根据缓存标识决定是否使用缓存的过程,有两种情况:

1.协商缓存生效,返回304

一些前端面试题总结_第5张图片

 2.协商缓存失效,返回200和请求结果

一些前端面试题总结_第6张图片

控制协商缓存的字段:

Etag / If-None-Match(优先级更高):Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成)。If-None-Match是客户端再次发起该请求时,携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。服务器收到该请求后,发现该请求头中含有If-None-Match,则会根据If-None-Match的字段值与该资源在服务器的Etag值做对比,一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

缺点:实际应用中由于Etag的计算是使用算法来得出的,而算法会占用服务端计算的资源。

Last-Modified / If-Modified-Since:Last-Modified是服务器响应请求时,返回该资源文件在服务器最后被修改的时间。If-Modified-Since是客户端再次发起该请求时,携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。服务器收到该请求,发现请求头含有If-Modified-Since字段,则会根据If-Modified-Since的字段值与该资源在服务器的最后被修改时间做对比,若服务器的资源最后被修改时间大于If-Modified-Since的字段值,则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件。

缺点:如果资源被修改,导致最后修改时间变化,但是内容没有变,会重新请求资源文件。

三、缓存存储

一些前端面试题总结_第7张图片

状态码Status为灰色的请求代表使用了强缓存,请求对应的Size代表该缓存存放的位置:

内存缓存(from memory cache)和硬盘缓存(from disk cache),

浏览器读取缓存的顺序:内存缓存 -> 硬盘缓存

内存缓存

快速读取:内存缓存会将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取。

时效性:一旦该进程关闭,则该进程的内存则会清空。

硬盘缓存:直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。

浏览器会在js和图片等文件解析执行后,直接存入内存缓存中,刷新页面时只需要从内存中读取;

CSS 文件会存入硬盘文件中,每次渲染页面都需要从硬盘读取缓存。

不同刷新的区别:

1.当ctrl+f5强制刷新网页时,直接从服务器加载,跳过强缓存和协商缓存(强制更新)

2.当f5刷新网页时,跳过强缓存,检查协商缓存(发请求带上If-Modify-since检查文件是否过期)

3.浏览器地址栏中写入URL+回车,发现缓存中有该请求结果,直接使用缓存(最快)

2.怎么优化H5让它可以在300ms以内打开

1. 减小页面体积:使用压缩工具来减小文件大小,加快加载速度。

2. 减少HTTP请求:合并多个CSS和JavaScript文件,以减少HTTP请求的数量。使用CSS Sprites来减少图像请求。

3. 使用CDN:将静态资源托管到内容分发网络(CDN)上,减少响应时间和提高加载速度。

4. 延迟加载:将不必要的资源延迟加载,在用户需要时才加载,加快初始页面加载速度。

5. 压缩图片:优化和压缩图像以减小文件大小。使用适当的图像格式来提高加载速度。

6. 使用浏览器缓存:通过设置合适的缓存策略,让浏览器在再次访问页面时能够加载缓存的资源,而不是重新下载。

7. 异步加载脚本:将不需要立即执行的JavaScript脚本标记为异步,以避免阻止页面加载。

8. 按需引用插件和库:删除不必要的插件和库,以减少加载时间。

9. 使用预加载和预渲染:通过预加载链接或使用``标签来预加载关键页面,以加快用户导航。

10. 减少重定向:页面中的重定向会增加加载时间。

11. 使用服务端渲染(SSR):使用SSR技术在服务器端生成HTML,减少客户端渲染时间。

3.浏览器渲染机制简要解析

1.解析html,构建DOM树

2.解析CSS,生成CSSOM树

3.合并dom树和css规则树,生成render渲染树

4.根据render渲染树进行布局

5.调用GPU对渲染树进行绘制,合成图层,显示在屏幕上

第四步和第五步就是浏览器渲染

输入网址到现显示页面的过程:

1)用户在浏览器地址栏中输入网址。

2)浏览器将URL发送到本地DNS解析器,并进行域名解析。本地DNS解析器会查询缓存或递归查询,向DNS服务器获取域名对应的IP地址。

3)如果本地缓存中有对应的地址记录会直接返回缓存结果,否则进行递归查询:本地DNS解析器通过根域名服务器、顶级域名服务器和权威域名服务器的查询,获取到目标域名的IP地址。

4)本地DNS解析器将得到的IP地址返回给浏览器。

5)浏览器通过获取到的IP地址与目标服务器建立TCP连接。这个过程涉及TCP三次握手。

6)TCP建立连接,浏览器发送HTTP请求到目标服务器,请求特定的资源(例如:GET请求获取网页内容)。

7)目标服务器接收到HTTP请求后,会解析请求,找到请求对应的资源(例如:HTML文件)。

8)目标服务器将请求的资源作为HTTP响应返回给浏览器。

9)浏览器接收到响应后,会根据响应中的内容进行渲染,将 HTML、CSS和 JavaScript 等资源解析并显示到用户界面上。

10)如果页面中有其他资源需要加载(例如图片、样式表、脚本等),浏览器会继续发送请求并加载这些资源。

11)所有资源加载完成,网页内容会完整地显示在用户的浏览器窗口中。

通过以上步骤,用户输入网址后,浏览器经过域名解析、建立连接、发送HTTP请求、接收响应、解析渲染等过程,最终将网页内容显示给用户。

4.HTTPS如何实现安全通信,建立通信过程

参考之前的文章,内容较为详细:http://t.csdn.cn/RPpPG

5.css中的几种定位方式

静态定位(static)静态定位(默认值),元素框正常生成的;

相对定位(relative)相对定位的偏移参考元素是元素本身,不会使元素脱离文档流;

绝对定位(absolute)绝对定位元素以父辈元素中最近的定位元素为参考坐标,如果绝对定位元素的父辈元素中没有采用定位的,那么此绝对定位元素的参考对象是html,元素会脱离文档流;

固定定位(fixed)固定定位位移的参考坐标是可视窗口,使用fixed的元素脱离文档流。

6.如何解决跨域

1. CORS(跨域资源共享):在服务器端配置CORS,允许特定域名的请求访问您的资源。通过设置适当的响应头,控制跨域请求的访问权限。

2. JSONP:使用JSONP允许从不同域名获取数据。但JSONP只适用于GET请求,可能存在安全风险。

3. 代理服务器:在服务器上设置一个代理,将跨域请求转发到目标服务器,然后将响应返回给客户端。

4. WebSocket:如果需要实时通信,WebSocket是一种可以跨域的双向通信协议。

5. 服务器配置:调整服务器配置,使请求绕过跨域限制(如在Nginx或Apache上设置反向代理)

6. 使用跨域库:使用JavaScript库(如axios)提供了简化处理跨域请求的方法。

7.对称加密和非对称加密的区别

对称加密是使用一个秘钥对明文加密,也用同样的秘钥把密文解密;

非对称加密需要两个秘钥,一个是公开的,另一个是私有的,用公钥加密的数据只能用私钥解密。

8.进程和线程的区别

一个进程可以包含多个线程,不同进程间数据很难共享,同一进程下不同线程间数据很易共享;

进程要比线程消耗更多的计算机资源;

进程间不会相互影响,一个线程挂掉将导致整个进程挂掉;

进程可以拓展到多机,进程最适合多核;

进程使用的内存地址可以上锁,即某一线程使用某些共享内存时,其他线程必须等它结束才能用。

9.同步和异步的区别

同步:按照代码书写顺序执行处理指令的一种模式,上一段代码执行完才能执行下一段代码。

异步:并行处理的方式,不必等待一个程序执行完,可以执行其它的任务。

JS需要异步的原因:JS是单线程运行的

常用的异步场景有:定时器、ajax请求、事件绑定。

10.深拷贝和浅拷贝

深拷贝会复制源对象的所有属性,包括对象的属性

浅拷贝只复制源对象的顶层属性,不会复制属性中的其他对象和数组。

手写深拷贝:

function deepCopy(obj, cache = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') return obj //原始值
  if (obj instanceof Date) return new Date(obj) //日期值
  if (obj instanceof RegExp) return new RegExp(obj) //正则

  if (cache.has(obj)) return cache.get(obj) //防止循环引用情况
  let copyObj = new obj.constructor() //创建一个和obj类型一样的对象
  cache.set(obj, copyObj) //放入缓存中
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      copyObj[key] = deepCopy(obj[key], cache)
    }
  }
  return copyObj
}
// 测试
const obj = {
  name: 'Jack',
  address: {
    x: 100,
    y: 200
  }
} 
obj.a = obj
let copyObj = deepCopy(obj)
console.log(copyObj)
console.log(copyObj.address === obj.address)  //false

11.Vue通信方式

参考之前的文章:http://t.csdn.cn/9n9Ar。

12.节流和防抖的区别

节流是指在一定时间内只能执行一次函数,防抖是指在一定时间内只能执行一次函数,但每次触发事件会重新计时。

13.cookie、localStorage、SessionStorage的区别

cookie是服务器下发到客户端的文本文件,本质是储存在浏览器端;localStorage和sessionStorage是HTML5标准中新增的技术,也是存储在浏览器端,但是使用方式和Cookie有所不同;localStorage存储的数据不过期,sessionStorage存储的数据会在页面会话结束之后自动删除。

14.TCP三次握手:

三次握手 和 四次挥手 是在网络通信中建立和终止TCP连接时发生的。

三次握手 发生在TCP连接建立阶段。当客户端想要与服务器建立连接时,它会发送一个带有SYN(同步)标志的数据包给服务器。服务器收到后会发送一个带有SYN/ACK(同步/确认)标志的数据包给客户端,表示接收到了客户端的请求并准备好建立连接。最后,客户端再发送一个带有ACK(确认)标志的数据包给服务器,表示连接已经建立。

四次挥手 发生在TCP连接终止阶段。当客户端或服务器想要断开连接时,它会发送一个带有FIN(结束)标志的数据包给对方。对方收到后会发送一个带有ACK标志的数据包作为确认。然后,对方也发送一个带有FIN标志的数据包给发起方,表示对方也准备好断开连接。最后,发起方再发送一个带有ACK标志的数据包作为确认,表示连接已经断开。

通过三次握手建立连接,可以确保双方都愿意进行通信。而通过四次挥手终止连接,可以确保双方都完成了数据的传输并且愿意断开连接。这样可以保证可靠的数据传输和释放网络资源。

详细过程及其他问题链接参考之前文章:http://t.csdn.cn/0ggQG

15.TCP和UDP

跳转之前文章:http://t.csdn.cn/LH9wX

16.手写Promise

class myPromise {
    // Promise 等待态(初始状态)
    static PENDING = 'pending';
    // Promise 失败态
    static REJECTED = 'rejected';
    // Promise 成功态
    static FULFILLED = 'fulfilled';
 
    constructor(executor){
        // 初始化 Promise 初始状态
        this.status = Promise.PENDING;
        // 定义 Promise 成功的值
        this.value = undefined
        // 定义 Promise 失败的原因
        this.reason = undefined;
 
        // 定义存储 then 方法中成功的回调
        this.onFulfilledCallbacks = [];
        // 定义存储 then 方法中失败的回调
        this.onRejectedCallbacks = [];
 
        // 定义 resolve 函数
        const resolve = (value) => {
            if(this.status === Promise.PENDING){
                this.status = Promise.FULFILLED;
                this.value = value
                this.onFulfilledCallbacks.forEach(fn => fn())
            }
        }
        // 定义 reject 函数
        const reject = (reason) => {
            if(this.status === Promise.PENDING){
                this.status = Promise.REJECTED;
                this.reason = reason
                this.onRejectedCallbacks.forEach(fn => fn())
            }
        };
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
        
    }
    then(onFulfilled,onRejected){
        if(this.status === Promise.FULFILLED){
            onFulfilled(this.value)
        }
        if(this.status === Promise.REJECTED){
            onRejected(this.reason)
        }
        if(this.status === Promise.PENDING){
            this.onFulfilledCallbacks.push(() => {
                onFulfilled(this.value)
            })
            this.onRejectedCallbacks.push(() => {
                onRejected(this.reason)
            })
        }
    }
}
// 测试
const promise = new myPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve('ok')
    },2000)
});
promise.then((value) => {
    console.log("promise success:", value);
}, (reason) => {
    console.log("promise fail:", reason);
})

17.异步Promise

 class myPromise {
    // Promise 等待态(初始状态)
    static PENDING = 'pending';
    // Promise 失败态
    static REJECTED = 'rejected';
    // Promise 成功态
    static FULFILLED = 'fulfilled';
 
    constructor(executor){
        // 初始化 Promise 初始状态
        this.status = Promise.PENDING;
        // 定义 Promise 成功的值
        this.value = undefined
        // 定义 Promise 失败的原因
        this.reason = undefined;
        // 定义 resolve 函数
        const resolve = (value) => {
            if(this.status === Promise.PENDING){
                this.status = Promise.FULFILLED;
                this.value = value
            }
        }
        // 定义 reject 函数
        const reject = (reason) => {
            if(this.status === Promise.PENDING){
                this.status = Promise.REJECTED;
                this.reason = reason
            }
        };
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
        
    }
    then(onFulfilled,onRejected){
        if(this.status === Promise.FULFILLED){
            onFulfilled(this.value)
        }
        if(this.status === Promise.REJECTED){
            onRejected(this.reason)
        }
    }
}
// 测试
const promise = new myPromise((resolve, reject) => {
    resolve('ok')
});
promise.then((value) => {
    console.log("promise success:", value);
}, (reason) => {
    console.log("promise fail:", reason);
})

18.http状态码

1xx:代表请求已被接受,需要继续处理

100 用来通知客户端它的部分请求已经被服务器接收,且未被拒绝。客户端需发送请求的剩余部分,如果请求已经完成,忽略这个响应,服务器必须在请求完成后向客户端发送一个最终响应

101 服务器根据客户端的请求切换协议

2xx:代表请求已成功被服务器接收

200 请求已成功【成功】

201 请求成功并且服务器创建了新的资源【已创建】

202 服务器已经接受请求,但尚未处理【已接受】

203 服务器已成功处理请求,但返回的信息可能来自另一来源【非授权信息】

204 服务器成功处理请求,但未返回任何实体内容【无内容】

205 服务器成功处理请求,但未返回任何实体内容,并且响应已经被重置了【重置内容】

206 服务器成功处理了部分请求【部分请求】

3xx:代表要完成请求,需要进一步操作,通常用来重定向

300 服务器针对请求可执行多种操作,服务器可根据请求者选择一项操作,或提供操作列表供其选择【多种操作】

301 请求的网页已永久移动到新位置【永久移动】

302 资源临时在另一个位置,该位置通过 Location 指定【临时移动】

303 请求的资源可以在另一个 URI 处找到,客户端必须使用单独的 GET 方法来获取新位置的资源【查看其他位置】

304 自从上次请求后,请求的网页未被修改过【未修改】

305 请求者只能使用代理访问请求的网页【使用代理】

307 服务器目前从不同位置的网页响应请求,但请求者应该继续使用原有位置进行之后的请求【临时重定向】

4xx:代表客户端可能发生了错误,妨碍了服务器的处理

400  服务器不理解请求的语法【错误请求】

401  请求要求身份验证,可能不希望将此网页纳入索引【身份验证错误】

403  服务器拒绝请求【禁止】

404  服务器找不到请求的网页【未找到】

405  禁用请求中指定的方法【方法禁用】

406  无法使用请求的内容特性响应请求的网页【不接受】

407  与 401 类似,但指定请求者必须授权使用代理。如果服务器返回此响应,还表示请求者应当使用代理【需要代理授权】

408  服务器等候请求时发生超时【请求超时】

409  服务器在完成请求时发生冲突。服务器必须在响应中包含有关冲突的信息。服务器在响应与前一个请求相冲突的 PUT 请求时可能会返回此代码,以及两个请求的差异列表【冲突】

410  请求的资源永久删除后,服务器返回此响应。在资源以前存在而现在不存在的情况下,有时会用来替代 404 代码。如果资源已永久删除,应当使用 301 指定资源的新位置【已删除】

411  服务器不接受不含有效内容长度标头字段的请求【需要有效长度】

412  服务器未满足请求者在请求中设置的其中一个前提条件【未满足前提条件】

413  服务器无法处理请求,因为请求实体过大,超出服务器的处理能力【请求实体过大】

414  请求的 URI 过长,服务器无法处理【请求的 URI 过长】

415  请求的格式不受请求页面的支持【不支持的媒体类型】

416  页面无法提供请求的范围【请求范围不符合要求】

417  服务器未满足"期望"请求标头字段的要求【未满足期望值】

5xx:代表服务器在处理请求的过程中有错误或异常状态发生

500  服务器内部错误,无法完成请求【服务器内部错误】

501  服务器不具备完成请求的功能(当服务器无法识别请求方法时)【尚未实施】

502  服务器作为网关或代理,从上游服务器收到无效响应【错误网关】

503  由于超载或停机维护,服务器目前无法使用【服务不可用】(暂时状态)

504  服务器作为网关或代理,但是没有及时从上游服务器收到请求【网关超时】

505  服务器不支持请求中所用的 HTTP 协议版本【HTTP 版本不受支持】

19.CSS设置元素水平垂直居中的方法

当父、子元素宽高未知

方法一:table-cell

.parent {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
.children {
  display: inline-block;
}

方法二:flex 布局

.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

方法三:absolute定位

写法一:

.parent {
  position: relative;
}
.children {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

写法二:

.parent {
  position: relative;
}
.children {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
}

方法四:Grid 布局

.parent {
  display: grid;
}
.children {
  align-self: center;
  justify-self: center;
}

当子元素宽高已知(假设子元素宽高为 200px)

absolute定位

写法一:calc计算

.parent {
  position: relative;
}
.children {
  position: absolute;
  top: calc(50% - 100px);
  left: calc(50% - 100px);
}

写法二:设置margin负值 

.parent {
  position: relative;
}
.children {
  position: absolute;
  top: 50%;
  left: 50%;
  margin-top: -100px;
  margin-left: -100px;
}

当父元素高度已知(假设为 400px)

text-align + vertical-align

.parent {
  text-align: center;
  line-height: 400px;
}
.children {
  display: inline-block;
  vertical-align: middle;
  line-height: initial;
}

20.flex和grid布局的区别

flex是单轴线布局,而grid是双轴线布局。

grid拥有更丰富的布局能力;flex使用较简单,可以将其子项目布局为列或行,但不能同时布局。

/* Flexbox */
.wrapper {
  display: flex;
}

/* Grid */
.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr;
  grid-gap: 16px;
}

一些前端面试题总结_第8张图片

21. CSS优先级

CSS 简单选择器可以分为以下几种类型:

  1. 通配符*,*选择器可以命中所有的 html 元素

  2. 标签选择器

  3. id 选择器

  4. 类选择器

  5. 属性选择器,使用“[]” 中括号包裹的内容,属性选择器一般与其他选择器一起使用作为补充,如 div[id],命中的是所有带有 id 属性的 div 元素,div[id=“abc”]命中 id 属性值为 abc 的 div 元素

  6. 伪类选择器,与其他的选择器组合使用,用来表示该元素的某种状态,如 div:hover,表示当 div 元素被鼠标悬浮时的样式,常见的伪类还有 :active、:link、:focus 等等

  7. 伪元素选择器,伪元素顾名思义即为不真实的元素,需要配合其他选择器一起使用,单独使用没有意义,如 div[class="abc"]::after,用来在命中属性 class 的 div 元素之后生成一个新的元素,主要的伪元素选择器有 ::before、::after、::first-letter、::first-line

!important > 内联样式 > id选择器 > 类选择器 > 标签选择器 > 外联样式表 > 通用选择器

22.原型和原型链

可以参考之前文章中第19点,有详细的说明:http://t.csdn.cn/ZD022

23.JS的事件循环

它是一个在 JavaScript 引擎等待任务,执行任务和进入休眠状态等待更多任务这几个状态之间转换的无限循环。

引擎的一般算法:

  1. 当有任务时:从最先进入的任务开始执行。
  2. 休眠直到出现任务,然后转到第 1 步。

任务示例:

  • 当外部脚本 

你可能感兴趣的:(前端,javascript,http,tcp/ip,vue.js)