前端面试题收集

153 阅读14分钟

计算机网络与计算机原理等

进程和线程

  • 1、进程:程序的一次执行,它占有一片独有的内存空间,是操作系统执行的基本单元
  • 2、线程:是进程内的一个独立执行单元,是CPU调度的最小单元,程序运行基本单元
  • 3、一个进程中至少有一个运行的线程:主线程。它在进程启动后自动创建
  • 4、一个进程可以同时运行多个线程,我们常说程序是多线程运行的,比如你使用听歌软件,这个软件就是一个进程,而你在这个软件里听歌收藏歌点赞评论,这就是一个进程里的多个线程操作
  • 5、一个进程中的数据可以供其中的多个线程直接共享,但是进程与进程之间的数据时不能共享
  • 6、JS引擎是单线程运行

HTTP2

  • 二进制分帧层=> 使用二进制进行传输二不是文本
  • 多路复用 => 一次TCP可以发送多个HTTP,避免线头阻塞(TCP连接上只能发送一个请求,前面的请求未完成前,后续的请求都在排队等待。)
  • 头部压缩 => 使用HPACK压缩格式进行压缩、避免头部相同部分多次请求
  • 服务端推送 => 服务器端推送使得服务器可以预测客户端需要的资源,主动推送到客户端。

HTTPS

  • HTTPS 中,使用传输层安全性(TLS)安全套接字层(SSL)对通信协议进行加密。
  • HTTPS结合了对称加密和非对称加密的特点,在客户端和服务端第一次通信时候,采用非对称加密的形式完成随机密钥的传输,在后面的请求中,采用首次生成的密钥进行对称加密。

TCP与UDP区别

原文TCP和UDP面试总结

基于连接vs无连接

  • TCP是面向连接的协议。
  • UDP是无连接的协议。UDP更加适合消息的多播发布,从单个点向多个点传输消息。 可靠性
  • TCP提供交付保证,传输过程中丢失,将会重发。
  • UDP是不可靠的,不提供任何交付保证。(网游和视频的丢包情况) 有序性
  • TCP保证了消息的有序性,即使到达客户端顺序不同,TCP也会排序。
  • UDP不提供有序性保证。 数据边界
  • TCP不保存数据边界。
    • 虽然TCP也将在收集所有字节之后生成一个完整的消息,但是这些信息在传给传输给接受端之前将储存在TCP缓冲区,以确保更好的使用网络带宽。 UDP保证
    • 在UDP中,数据包单独发送的,只有当他们到达时,才会再次集成。包有明确的界限来哪些包已经收到,这意味着在消息发送后,在接收器接口将会有一个读操作,来生成一个完整的消息。 速度
  • TCP速度慢
  • UDP速度快。应用在在线视频媒体,电视广播和多人在线游戏。 发送消耗
  • TCP是重量级。
  • UDP是轻量级。
    • 因为UDP传输的信息中不承担任何间接创造连接,保证交货或秩序的的信息。
    • 这也反映在用于报头大小。 7. 报头大小
  • TCP头大。
    • 一个TCP数据包报头的大小是20字节。
    • TCP报头中包含序列号,ACK号,数据偏移量,保留,控制位,窗口,紧急指针,可选项,填充项,校验位,源端口和目的端口。
  • UDP头小。
    • UDP数据报报头是8个字节。
    • 而UDP报头只包含长度,源端口号,目的端口,和校验和。 拥塞或流控制
  • TCP有流量控制。
    • 在任何用户数据可以被发送之前,TCP需要三数据包来设置一个套接字连接。TCP处理的可靠性和拥塞控制。
  • UDP不能进行流量控制。

应用

  • 由于TCP提供可靠交付和有序性的保证,它是最适合需要高可靠并且对传输时间要求不高的应用。
  • UDP是更适合的应用程序需要快速,高效的传输的应用,如游戏。
  • UDP是无状态的性质,在服务器端需要对大量客户端产生的少量请求进行应答的应用中是非常有用的。
  • 在实践中,TCP被用于金融领域,如FIX协议是一种基于TCP的协议,而UDP是大量使用在游戏和娱乐场所。 上层使用的协议
  • 基于TCP协议的:Telnet,FTP以及SMTP协议。
  • 基于UDP协议的:DHCP、DNS、SNMP、TFTP、BOOTP。

TCP 三次握手 四次挥手

原文TCP和UDP面试总结
三次握手具体过程

  • 主机A向主机B发送含有同步序列号SYN的标志位的数据,
  • 主机B收到后,发送ACK和SYN给 主机A
  • 主机A收到后,发送应答ACK确认给 主机B 。 `第一次握手**:客户端发送包含SYN和seq的网络包,然后服务端收到了。
  • 服务端视角得出结论:客户端的发送能力、服务端的接收能力是正常的。 第二次握手**:服务端发送包含SYN、ACK和seq`的网络包,然后客户端收到了。
  • 客户端视角得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。 第三次握手:客户端发送包含ACK和seq的网络包,然后服务端收到了。
  • 服务端视角得出结论:客户端的接收、发送能力,服务端的发送、接收能力是正常的。

四次挥手
四次挥手可以分为两个部分,每个部分包含两次挥手,表示一个方向的连接断开。 客户端断开连接

  • 客户端发送包含FIN的网络包,服务端收到。
  • 服务端发送包含ACK的网络包(这里出现close-wait),客户端收到,此时这个方向上的连接关闭。 服务端断开连接
  • 服务端发送包含FIN的网络包,客户端收到。
  • 客户端发送包含ACK的网络包(time-wait开始计时),服务端收到,此时这个方向上的连接关闭。

用户访问CDN资源过程

  • 用户向浏览器输入www.web.com这个域名,浏览器第一次发现本地没有DNS缓存,则向网站的DNS服务器请求;
  • 网站的DNS域名解析器设置了CNAME,指向了www.web.51cdn.com,请求指向了CDN网络中的智能DNS负载均衡系统;
  • 智能DNS负载均衡系统解析域名,把对用户响应速度最快的IP节点(CDN服务器)返回给用户;
  • 用户向该IP节点(CDN服务器)发出请求;
  • 由于是第一次访问,CDN服务器会向原web站点请求,并缓存内容;
  • 请求结果发给用户。

浏览器机制


输入url发生了什么

  • 1、浏览器的地址栏输入URL并按下回车。
  • 2、浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
  • 3、DNS解析URL对应的IP。
  • 4、根据IP建立TCP连接(三次握手)。
  • 5、HTTP发起请求。
  • 6、服务器处理请求,浏览器接收HTTP响应。
  • 7、渲染页面,构建DOM树。
  • 8、关闭TCP连接(四次挥手)

浏览器渲染

  • 1、HTML解析器:解释HTML文档的解析器,主要作用是将HTML文本解释为DOM树

  • 2、CSS解析器:它的作用是为DOM中的各个元素对象计算出样式信息,为布局提供基础设施

  • 3、JavaScript引擎:JavaScript引擎能够解释JavaScript代码,并通过DOM接口和CSS接口来修改网页内容 和样式信息,从而改变渲染的结果

  • 4、布局(layout):在DOM创建之后,WebKit需要将其中的元素对象同样式信息结合起来,计算他们的大小位置等布局信息,形成一个能表达着所有信息的内部表示模型

  • 5、绘图模块(paint):使用图形库将布局计算后的各个网页的节点绘制成图像结果 渲染过程

  • 1、浏览器会从上到下解析文档

  • 2、遇见HTML标记,调用HTML解析器解析为对应的token(一个token就是一个标签文本的序列化)并构建DOM树(就是一块内存,保存着tokens,建立他们之间的关系)

  • 3、遇见style/link标记调用相应解析器处理CSS标记,并构建出CSS样式树

  • 4、遇见script标记,调用JavaScript引擎处理script标记,绑定事件,修改DOM树/CSS树等

  • 5、将DOM树与CSS合并成一个渲染树

  • 6、根据渲染树来渲染,以计算每个节点的几何信息(这一过程需要依赖GPU)

  • 7、最终将各个节点绘制在屏幕上


script的async和defer

  • <script async></script> 加上async属性,JS代码会异步加载并执行(多script标签情况下,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行)
  • <script defer></script> 加上defer属性,JS代码会异步加载(如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script,会在DOMCotentLoaded前执行)

跨域的方式

跨域的条件 当协议、子域名、主域名、端口号中任意一个不相同时,都算作不同域

  1. JSONP => 利用 <script src="资源地址"> 标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。
  2. CORS => 通过后端设置请求头"Access-Control-Allow-Origin"来实现,浏览器会事先发送一个method为option的预请求来检查是否可以跨域
  3. websocket => 实现了浏览器与服务器的全双工通信,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。
  4. 代理服务器
  5. window.name + iframe
  6. location.hash + iframe
  7. document.domain + iframe

Vue


vue基本使用


如果子组件改变props里的数据会发生什么


如果是基本类型会报错,引用类型会改变父元素

props自定义验证

props: { 
    num: { 
        default: 1,
        validator: function (value) {
        // 返回值为true则验证不通过,报错
            return [ 1, 2, 3, 4, 5 ].indexOf(value) !== -1
        }
   } 
}

vue原理


nextTick原理

  1. vue用异步队列的方式来控制DOM更新和nextTick回调先后执行
  2. 微任务因为其高优先级特性,能确保队列中的微任务在一次事件循环前被执行完毕
  3. 因为兼容性问题,vue不得不做了微任务向任务的降级方案

vue响应式原理

参考文章林三心画了8张图,最通俗易懂的Vue3响应式核心原理解析

  • Vue2的响应式是基于Object.defineProperty实现的
  • Vue3的响应式是基于ES6的Proxy来实现的 Vue2缺点:响应式不能监听object属性的增加和删除 响应式需要当改变一个变量时,另一个依赖他的变量会自动更新 比如 let a = 1,let b = "哈哈"+1,a变化时,b也会更新,这就需要连个函数,track函数:收集依赖,trigger函数:通知更新

实现reactive reactive => 通过proxy进行代理可以监听对象的get,set。 effect => 收集接收函数并将函数赋值给用来标记的全局变量activeEffect,并执行函数,触发proxy的get方法 track => get方法调用track方法进行依赖收集 将当前activeEffect放入dep中 trigger => set方法调用trigger,对依赖的函数进行更新

//全局变量
let activeEffect: (() => void) | null = null;
let targetMap = new WeakMap();

//手写reactive
function reactive(target: any) {
  const handler: ProxyHandler<any> = {
    get(target: any, key: any, receiver: any) {
      track(receiver, key); // 访问时收集依赖
      return Reflect.get(target, key, receiver);
    },
    set(target: any, key: string | symbol, value: any, receiver: any): boolean {
      Reflect.set(target, key, value, receiver);
      trigger(receiver, key); // 设值时自动通知更新
      return true;
    },
  };
  return new Proxy(target, handler);
}
effect(effectNameStr1);
function effect(fn: () => void) {
  activeEffect = fn;
  activeEffect();
  activeEffect = null; // 执行后立马变成null
}
function track(target: any, key: any) {
  // 如果此时activeEffect为null则不执行下面
  // 这里判断是为了避免例如console.log(person.name)而触发track
  if (!activeEffect) return;
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }

  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect); // 把此时的activeEffect添加进去
}
function trigger(target: any, key: any) {
  let depsMap = targetMap.get(target);
  if (depsMap) {
    const dep = depsMap.get(key);
    if (dep) {
      dep.forEach((effect: any) => effect());
    }
  }
}
//实验
const person = reactive({ name: "林三心", age: 22 }); // 传入reactive
let nameStr1 = "";
const effectNameStr1 = () => {
  nameStr1 = `${person.name}是个大菜鸟`;
};

实现ref与computed

function ref (initValue) { 
    return reactive({ 
        value: initValue 
    }) 
}
function computed(fn) { 
    const result = ref()
    effect(() => result.value = fn()) // 执行computed传入函数
    return result
}

vue-router


vuex


JavaScript & TypeScript


JS基础


call,apply,bind的区别

  1. 三者第一个参数都是需要绑定this的对象
  2. call,apply会立即执行,bind会返回一个绑定好的函数
  3. call,bind后面的参数为函数的参数,apply第二个参数为一个数组,数组里是函数的参数

new操作符执行过程(手写new)

#创建一个Object
var obj = {}
#将obj原型指向func的原型
obj._proto_ = func.prototype
#执行构造函数
var result = func.apply(obj,arg)
#判断构造函数返回值是否是一个对象如果是返回函数返回的对象不是返回创建的对象
return result instanceof Object ? result : obj;

数组常用方法


绑定事件方法

  • 元素标签onClick属性
  • dom对象onclick方法
  • dom对象addEventListener

碎片文档用法

需要大量操作的时候,通过碎片文档避免多次重绘和回流,列子:在ul中插入10000个li

var parent = document.getElementById("parent"); 
var frag = document.createDocumentFragment(); 
for (var i = 0; i < 10000; i++) { 
    var child = document.createElement("li"); 
    var text = document.createTextNode("" + i); 
    child.appendChild(text); 
    frag.appendChild(child); 
} 
parent.appendChild(frag);


ES6


map和Object区别


  • 当所要存储的是简单数据类型,并且 key 都为字符串或者整数或者 Symbol 的时候,优先使用 Object ,因为Object可以使用 字符变量 的方式创建,更加高效。
  • 当需要在单独的逻辑中访问属性或者元素的时候,应该使用 Object;
  • JSON 直接支持 Object,但不支持 Map
  • Map 是纯粹的 hash, 而 Object 还存在一些其他内在逻辑,所以在执行 delete 的时候 会有性能问题。所以写入删除密集的情况应该使用 Map。
  • Map 会按照插入顺序保持元素的顺序,而Object做不到。
  • Map 在存储大量元素的时候性能表现更好,特别是在代码执行时不能确定 key 的类型的情况。

WeakMap与WeakSet

  • WeakSet只能存储对象,不能存储基础数据类型
  • WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。案列:
let obj = { name: '诺克萨斯'};
let ws = new WeakSet(); 
ws.add(obj);
obj = null
console.log(ws)  //垃圾回收之后ws会为空
  • 应用场景,储存 DOM 节点,而不用担心这些节点从文档移除时,会引发内存泄漏。

有哪些ES6语法

  1. let,const
  2. 解构赋值
  3. 模板字符串
  4. 同名属性简写
  5. 扩展运算符
  6. 函数参数默认值
  7. 箭头函数
  8. promise,async,await

箭头函数

  1. 箭头函数没有 prototype (原型),所以箭头函数本身没有this,且不能当做构造函数
  2. 箭头函数中this的指向在它被定义的时候就已经确定了,之后永远不会改变,通过call()、apply()、bind()方法调用时,第一个参数会被忽略。
  3. 箭头函数中若用了this,这个this指向包裹箭头函数的第一个普通函数的 this
  4. 箭头函数不能用作Generator函数,不能使用yield关键字
  5. 箭头函数不绑定arguments,取而代之用rest参数...代替
  6. 普通函数可以定义后相当于会在最顶,只要定义了在运行到定义那一行之前也可以调用,箭头函数不能 必须等运行到函数的变量才行。

CSS


other