东一榔头西一棒槌的前端面试准备 - 基础篇 (持续整理中...)

HTTP

GET和POST的区别

  • 报文格式不一样,get把参数放在Url里,post把参数放在body里;
  • get请求因为把全部参数都暴露在url里,因此相对post安全性差一些;
  • url有长度限制,因此会限制get传参(这条其实会根据浏览器的实现不一样而不一样);
  • get能够被缓存能够被收藏为书签,post不能;
  • get会被保存在浏览器历史里,post不会;
  • 回退或者前进的时候get是无害的,post会从新提交;

IP和TCP

IP: 互联网的数据是经过数据包传递的,若是要将主机A的数据传递到主机B,就须要知道主机B的IP地址,才能正确寻址;额外的,数据包上还会添加上A的IP地址,这样B才知道怎么回复A;可是,B拿到数据包以后,并不知道要交给哪一个程序进行处理,就须要UDP(用户数据包协议)和TCP协议的帮助;
TCP(传输控制协议):上层把数据包传递给传输层 --> 传输层给数据包加上UDP头交给网络层 --> 网络层把IP头附加在数据包上,交给底层 --> 数据包被传输给了B的网络层,这时候主机B把IP头拆开,把数据包交给传输层 --> 传输层把UDP头拆开,根据端口号交给相应的应用程序进行处理;
TCP的三次握手:主要是为了确认通讯能力,也就是双方都有发信和收信的能力,若是不确认的话任何数据传送都是不稳定的~因此须要三次握手:
客户端A向服务端B发送报文(B已确认了A的发信能力和B的收信能力) --> 服务端收到报文后,向客户端发送报文(A已确认了双方的收发能力) --> A返回ACK并创建链接(B确认了A的收信能力和B的发信能力)。TCP链接创建后,浏览器就能够利用HTTP/HTTPS协议向服务器发送请求了。
TCP的四次挥手:因为TCP协议有半关闭的状态(就是只能够接收信息不能够发生信息),关闭能够由客户端或者服务端提出:
二者在established状态,客户端A向服务端B提出关闭请求 --> B收到以后,给A发送收到信息的响应,同时通知应用程序关闭相关资源 --> B准备好了以后,给A发送关闭通知消息 --> A回复B,断开链接。javascript

缓存

DNS缓存

主要就是在浏览器本地把对应的 IP 和域名关联起来,这样在进行DNS解析的时候就很快。html

MemoryCache

存在内存里的缓存。不会请求服务器。从优先级上来讲,它是浏览器最早尝试去命中的一种缓存。从效率上来讲,它是响应速度最快的一种缓存。主要用来缓存图片、字体、通常脚本等;和渲染进程“生死相依”,tab关掉就没有了;前端

http缓存

  • 强缓存:不会请求服务器。expires和cache-control字段控制。expires依赖本地时间,因此并非最好的策略。cache-control: max-age=31536000比较合适。cache-control比expires优先度更高;
  • 协商缓存:依赖于服务端与浏览器之间的通讯。协商缓存机制下,浏览器须要向服务器去询问缓存的相关信息,进而判断是从新发起请求、下载完整的响应,仍是从本地获取缓存的资源。若是服务端提示缓存资源未改动(Not Modified),资源会被重定向到浏览器缓存,这种状况下网络请求对应的状态码是 304。

协商缓存的实现,从Last-ModifiedEtag。Last-Modified 是一个时间戳,第一次请求的时候,服务器会返回Last-Modified,随后咱们每次请求时,会带上一个叫 If-Modified-Since 的时间戳字段, 服务器会进行比较;可是存在last-modified不许确的现象(好比咱们编辑了文件可是内容没有发生改变,服务器只认修改的时间,所以会去修改last-modified的值,这样的话就么有正确使用协商缓存~),所以有了EtagEtag是由服务器为每一个资源生成的惟一的标识字符串。vue

Service worker cache

Service Worker 是一种独立于主线程以外的 Javascript 线程。它脱离于浏览器窗体,所以没法直接访问 DOM。这样独立的个性使得 Service Worker 的“我的行为”没法干扰页面的性能,这个“幕后工做者”能够帮咱们实现离线缓存、消息推送和网络代理等功能。咱们借助 Service worker 实现的离线缓存就称为 Service Worker Cache。java

Service worker

Service Worker
GoogleChrome关于service worker的sample.jsgit

service worker的由来和做用:

service worker是基于web worker发展而来的(web worker主要是由于js是单线程的,用ww能够开辟一个新的线程,是脱离在主线程以外的,咱们能够将复杂耗费时间的事情交给web worker来作)。sw是在ww的基础上增长了离线缓存的能力。github

sw是由事件驱动的,具备生命周期,能够拦截处理页面的全部网络请求(fetch),能够访问cache和indexDB,支持推送,而且可让开发者本身控制管理缓存的内容以及版本,为离线弱网环境下的 web 的运行提供了可能,让 web 在体验上更加贴近 native。换句话说他能够把你应用里的全部静态动态资源根据不一样策略缓存起来,在你下次打开时再也不须要去服务器请求,这样一来就减小了网络耗时,使得web应用能够秒开,而且在离线环境下也变得可用。作到这一切你只须要增长一个sw文件,不会对原有的代码产生任何侵入。web

// 页面注册service worker
if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/sw.js');
  });
}

service worker的生命周期:

最常绑定的事件:面试

  • install 事件中, 抓取资源进行缓存
  • activate 事件中, 遍历缓存, 清除过时的资源
  • fetch 事件中, 拦截请求, 查询缓存或者网络, 返回请求的资源

ES6

let和const

class

函数(箭头函数、参数解构)

Promise

async / await

Map和Set

Vue

为何vue的列表渲染要加key?

React

Promise

跨域

js遵循同源策略,即同协议,同域名,同端口号,不然都算跨域。
下图帮助理解:

能够进行跨域的主要有iframe / JSONP / CORS算法

iframe

<iframe src="demo.html" height="300" width="500" name="demo" scrolling="auto" sandbox="allow-same-origin"></iframe>
  • window.self: 本身; window.parent: 父级窗口; window.top: 顶级窗口;
  • 在前端领域,咱们能够经过window.top来防止咱们页面被嵌套。
if(window != window.top){
    window.top.location.href = myURL;
}
  • iframe经过iframe.postMessage进行跨域通讯;经过window.addEventListener('message', fn)来监听通讯事件;

闭包

原型链和class

浏览器相关

浏览器相关原理(面试题)详细总结一

EventLoop

  • js是单线程的,会出现阻塞问题,所以有了异步队列的出现
  • 主进程同步执行任务,异步操做将添加到异步队列中
  • 等候主进程执行完毕后再执行异步队列中的操做

什么是宏任务和微任务?
异步队列有宏任务和微任务之分。

  • 宏任务

    • setTimeout
    • setImmediate
    • setIntarval
    • requestAnimationFrame
    • I/O
    • UI rendering
  • 微任务

    • process.nextTick
    • Promise.then
    • Object.observe
    • MutationObserver
  • 一次事件循环:先运行宏任务队列中的一个,而后运行微任务队列中的全部任务。接着开始下一次循环

浏览器渲染过程

  • 解析HTML,构建DOM树;
  • 解析CSS,生成CSS规则树;
  • 合成HTML和CSS,生成render树;
  • 布局render树,计算每个节点的位置和尺寸;
  • 绘制render树(paint),绘制图像信息;
  • 浏览器会把各层信息发给GPU,由GPU显示在屏幕上;
从新布局叫回流,就是改变布局,每次的回流都会触发重绘(repaint), 又要去消耗gpu; 但并非每次repaint都会触发reflow,好比改个背景色啥的,就不须要从新布局;
onLoad: 在页面全部文件加载完成后执行;DomContentLoaded: DOM加载后执行,没必要等待样式脚本和图片下载;

webSocket

web Socket 协议

WebSocket 协议实现了浏览器与服务器全双工通讯,能更好的节省服务器资源和带宽并达到实时通信的目的。它与HTTP同样经过已创建的TCP链接来传输数据,可是它和HTTP最大不一样是:

  • WebSocket是一种双向通讯协议。在创建链接后,WebSocket服务器端和客户端都能主动向对方发送或接收数据,就像Socket同样;
  • WebSocket须要像TCP同样,先创建链接,链接成功后才能相互通讯。

WebSocket 链接必须由浏览器发起,请求协议是一个标准的HTTP请求(也就是说,WebSocket的创建是依赖HTTP的)。请求报文格式以下:
GET ws://localhost:3000/ws/chat HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Origin: http://localhost:3000
Sec-WebSocket-Key: client-random-string // 用于标识这个链接
Sec-WebSocket-Version: 13 //指定了websocket的协议版本

web Socket API

建立web socket, 指定open、message等事件的回调便可(和web worker和service worker还挺像);
WebSocket 构造函数
const ws = new WebSocket('ws://localhost:8080/ws')
webSocket.readyState

CONNECTING: 值为  0,表示正在链接。
OPEN: 值为  1,表示链接成功,能够通讯了。
CLOSING: 值为  2,表示链接正在关闭。
CLOSED: 值为  3,表示链接已经关闭,或者打开链接失败。

webSocket.onopen : 指定链接成功以后的回调函数:

ws.onopen = function() {
    console.log('hello websocket')
}

webSocket.onclose: 指定链接关闭以后的回调函数
webSocket.onmessage: 指定收到服务器数据后的回调函数

webSocket.onmessage = function (event) {
    // 数据多是文本或者二进制数据
    if (typeof event.data === 'string') {
        //...
    } else if (event.data.instanceof ArrayBuffer) {
        //...
    }
    console.log(event.data)
}

webSocket.send: : 实例对象的send()方法用于向服务器发送数据
webSocket.send(message)

SPA和PWA

SPA的优缺点

从 SPA 到 PWA:Web App的下一站在哪?

微信小程序和PWA的异同点:

来自 微信小程序和PWA对比分析

二者和native app最大的区别都是“无需安装、用完即走”

  • 小程序:主要依托微信自有生态,好处是几乎不须要运营成本,且方便分享和传播;同时,微信小程序相似于hybrid app的开发方式,用H5完成主要的渲染工做,原生层面上有WebView预加载,原生模块覆盖(camera/map/storage)等。坏处是微信出于稳定考虑没有暴露DOM api, 且只能基于微信系统作个性化封装,开发有必定的局限性,小程序的生态也不是很好;
  • PWA:主要利用了service worker作缓存策略以及推送通知。优化了用户的体验,最大的限制就是看浏览器是否是支持service worker。

MVC和MVVM

MVC:

咱们全部的App都是界面和数据的交互,因此须要类来进行界面的绘制,因而出现了View,须要类来管理数据因而出现了Model。咱们设计的View应该能显示任意的内容好比页面中显示的文字应该是任意的而不仅是某个特定Model的内容,因此咱们不该该在View的实现中去写和Model相关的任何代码,若是这样作了,那么View的可扩展性就至关低了。而Model只是负责处理数据的,它根本不知道数据到时候会拿去干啥,可能拿去做为算法噼里啪啦去了,可能拿去显示给用户了,它既然没法接收用户的交互,它就不该该去管和视图相关的任何信息,因此Model中不该该写任何View相关代码。然而咱们的数据和界面应该同步,也就是必定要有个地方要把Model的数据赋值给View,而Model内部和View的内部都不可能去写这样的代码,因此只能新创造一个类出来了,取名为Controller

这张图把MVC分为三个独立的区域,而且中间用了一些线来隔开。颇有意思的设计,由于这些线彷佛出如今了驾校科目一的内容中,你瞧C和V以及C和M之间的白线,一部分是虚线一部分是实线对吧,这就代表了引用关系:C能够直接引用V和M,而V和M不能直接引用C,至少你不能显式的在V和M的代码中去写和C相关的任何代码,而V和M之间则是双黄线,没错,它们俩谁也不能引用谁,你既不能在M里面写V,也不能在V里面写M。哦,上面的描述有点小小的问题,你不是“不能”这样写,而是“不该该”这样写,没人能阻止你在写代码的时候在一个M里面去写V,可是一旦你这样作了,那么你就违背了MVC的规范,你就不是在使用MVC了,因此这算是MVC的一个必要条件:使用MVC –> M里面没有V的代码。因此M里面没有V的代码就是使用MVC的必要条件。

MVVM:

MVVM的诞生:

就像咱们以前分析MVC是如何合理分配工做的同样,咱们须要数据因此有了M,咱们须要界面因此有了V,而咱们须要找一个地方把M赋值给V来显示,因此有了C,然而咱们忽略了一个很重要的操做:数据解析。在MVC出生的年代,手机APP的数据每每都比较简单,没有如今那么复杂,因此那时的数据解析极可能一步就解决了,因此既然有这样一个问题要处理,而面向对象的思想就是用类和对象来解决问题,显然V和M早就被定义死了,它们都不该该处理“解析数据”的问题,理所应当的,“解析数据”这个问题就交给C来完成了。而如今的手机App功能愈来愈复杂,数据结构也愈来愈复杂,因此数据解析也就没那么简单了。若是咱们继续按照MVC的设计思路,将数据解析的部分放到了Controller里面,那么Controller就将变得至关臃肿。还有至关重要的一点:Controller被设计出来并非处理数据解析的。一、管理本身的生命周期;二、处理Controller之间的跳转;三、实现Controller容器。这里面根本没有“数据解析”这一项,因此显然,数据解析也不该该由Controller来完成。那么咱们的MVC中,M、V、C都不该该处理数据解析,那么由谁来呢?这个问题实际上在面向对象的时候至关好回答:既然目前没有类可以处理这个问题,那么就建立一个新的类出来解决不就行了?因此咱们聪明的开发者们就专门为数据解析建立出了一个新的类: ViewModel。这就是MVVM的诞生。
相关文章
相关标签/搜索