基础概念

JavaScript为什么是单线程?

设计初衷:响应事件、操作dom、发送网络请求。处理I/O密集型任务,而非处理计算密集型任务。

单线程原因:简化开发、避免dom操作冲突、适应浏览器环境。

浏览器环境:渲染引擎是单线程

虽然js本身是单线程、但是运行环境可以支持多线程能力

通过js的事件循环异步机制和web workers解决单线程的高并发性能问题。

什么是事件循环?

目的:事件循环是解决js单线程既能异步又不阻塞的调度器。

机制:主线程、微任务、宏任务、微任务、宏任务……

什么是高并发?

单位时间内涌入大量的请求/链接/任务,程序依旧保持低延迟、高吞吐、不崩溃运行。

Web Workers

什么是Web Workers?

就是浏览器给javascript开的"后台线程",用于计算密集型任务,解决js单线程阻塞问题。从而提升js的单线程性能和高并发能力。

缺点:不可操作dom,window,document

什么是Service Workers?

特点:网络代理、缓存、离线推送

缺点:不可操作dom,window,document

什么是Web Components?

为原生js封装公共组件的方式

存储与数据

Web Storage API有哪些?分别有什么特点?

特性 localStorage sessionStorage IndexedDB(小型数据库)

容量 5MB 5MB 大量数据(通常50%磁盘空间)

持久性 永久存储 会话期间 永久存储

数据结构 键值对 键值对 结构化数据

如何理解数据结构?

数据结构通过"重新组织数据之间的结构",降低对数据增删改查的操作成本。从而使得算法性能提升。

常见操作:数组转对象,对象转数组。树转数组,数组转树。

原型与继承

原型链是什么?

构造函数/类通过prototype为实例化对象添加属性

所有对象(包括函数)可通过__proto__查找链上的属性方法。

原型对象继承:call()继承this.xxx Object.create(Animal.prototype)继承构造函数.prototype.xxx

Call、apply、bind的区别?

call:立即执行函数、参数逐个传递

apply:立即执行函数、参数数组传递

bind:不会立即执行,返回新函数。

this指向规则?

普通指向window,考虑严格模式下

隐式绑定:立即调用的对象.方法()

隐式绑定丢失:赋值对象.函数。后续再调用

显式绑定:call、apply、bind

new Promise()

箭头函数没有this指向

异步编程

Promise的理解?

错误机制处理:冒泡式处理,错误会一直向后传递,直到被catch捕获。这种机制避免了重复的错误代码检测。

解决回调地狱:

promise通过then()可实现链式调用,把纵向嵌套改为横向扩展的方式。

微任务机制:Promise属于微任务

Promise和async/await的区别?

promise:es6语法,链条式调用,通过catch捕获异常,写法更底层。

async/await:es7语法,看起来像同步的异步代码。写法更简洁易懂,可读性更高,通过try/catch捕获异常。

二者可结合使用,根据需求来选

内存管理

Map和WeakMap的区别?

区别:前者为强引用,后者为弱引用

什么是内存泄漏?

程序中已分配的内存在未使用时继续占有内存,导致内存占用不断增加。从而影响性能。

常见内存泄漏:

意外的全局变量、未清理的定时器、闭包的滥用、dom的引用

判断是否存在内存泄漏:

需要 → 有引用 → 正常

不需要 → 有引用 → 泄漏

不需要 → 无引用 → 正常

WeakMap解决内存泄漏原理?

1. user变量强引入了user对象

2. weakmap以键的形式弱引入user对象

3. weakmap以值的形式强引入额外数据

4. user = null,不再指向对象,强引用断开,剩下唯一的weakmap弱引用

5. 垃圾回收器回收weakmap弱引入的user对象

6. weakmap映射删除,额外数据失去引用,同时被垃圾回收

性能优化

隐藏类优化、JIT、ESM优化?

隐藏类优化:函数传参顺序结构保持统一

JIT优化:函数传参类型保持统一

ESM(提升tree-shaking):模块化导入,尽量不使用通配符,通配符会把未使用到的全部导入进来

什么是防抖、什么是节流?

防抖:事件发生后,延迟多少时间再触发。只执行最后一次。

案例:输入框输入500毫秒后再请求搜索,防止hello搜索五次。

节流:一定时间内,只执行第一次。

案例:表单提交,防重复提交。

事件机制

事件委托、捕获、冒泡理解?

事件委托:把目标事件委托给父级去触发事件,通过event.target判断是否为目标对象再进行事件触发,提升性能。

事件捕获:添加capture:true后才算监听捕获,从外向内捕获,判断是否需要拦截事件并阻止向下捕获,常用于权限判断、是否执行接下来的事件流


冒泡:子元素点击 → 事件冒泡到父级 → 父级判断:"刚才是不是子元素被点击了?" → 是则处理


捕获:父级捕获事件 → 父级判断:"是否允许事件传递到子元素?" → 不允许就拦截,允许就放行


浏览器事件流:事件捕获 → 目标元素 → 事件冒泡

onclick和addEventListener区别?

onclick:简单直接,无法控制完整的事件流

addEventListener:能控制完整的事件流

浏览器相关

浏览器改为多进程的好处?

每个标签进程独立,不至于一个标签卡死整个浏览器卡死。

安全考虑,权限最小化。

并行:多核CPU同时跑多个标签

浏览器渲染页面步骤?

解析HTML生成DOM树 → 解析CSS生成CSSOM树 → 合并生成渲染树 → 结构布局 → 绘制 → 合成

css选择器匹配:从右往左

解析流程:从上而下,谁先到谁先下载/解析。js下载会阻塞html解析。css的下载会阻塞js的执行,css解析与html解析并行。

网络与服务器

对网络协议的理解?

应用层DNS解析域名为ip,生成http报文 → 传输层3次握手,添加tcp头 → 网络层添加ip头 → 链路层添加MAC头 → 服务器拆包(1.校验MAC 2.校验IP 3.校验TCP 4.http报文交给端口80 nginx处理) → 业务逻辑处理 → 回包http,4次挥手 → 反向逐层加头(MAC,IP,TCP)→ 浏览器逐层拆包(MAC → IP → TCP → HTTP)→ 渲染页面

如何理解nginx?它的作用是什么?

可实现静态部署、反向代理、缓存、限流、负载均衡等作用。

其他概念

什么是哈希值?哈希值的特点?

哈希值是一种十六进制字符组成,常用于信息加密

特点:不可逆、唯一性、相同哈希算法加密结果长度相同

SSR服务端渲染?

SSR工作流程:1.用户请求、2.服务器执行vue、3.生成HTML、4.发送完整页面、5.客户端激活(js下载,vue接管页面使其可以交互)

SSR特点:SEO友好、首屏加载快、服务器渲染、服务器压力大、开发复杂

CSR特点:客户端/浏览器渲染,其他跟SSR相反