前端基础
yatbfm

浏览器

url 的组成部分

  1. 协议(Protocol):表示访问网页时使用的通信协议,常见的有 HTTP、HTTPS、FTP 等。
  2. 域名(Domain Name):表示网站的名称,是网站在互联网上的唯一标识。域名由多个部分组成,包括主域名和子域名,例如www.example.com中的"www"是子域名,"example"是主域名,".com"是顶级域名。顶级域名:也就是后缀,例如.com、.cn等。(备注:域名可以说是一个IP地址的代称,目的是为了便于记忆后者。
  3. 端口号(Port):表示用于访问网站的端口号,默认为 80。例如,http://www.example.com:8080中的"8080"就是端口号。端口号的范围是:0~65535
  4. 路径(Path):表示网站上具体的文件或目录路径。例如,http://www.example.com/path/to/file中的"/path/to/file"就是路径(网址可以没有端口号)。
  5. 查询参数(Query Parameters):表示向服务器传递的参数,用于定制请求的内容。查询参数以"?"开头,多个参数之间使用"&"分隔。例如,http://www.example.com/path/to/file?param1=value1&param2=value2中的param1=value1&param2=value2就是查询参数,这种常见于项目中路由跳转的传参、get请求等。
  6. 锚点(Anchor):表示网页内部的定位点。锚点以"#"开头,用于跳转到网页的特定位置。例如,http://www.example.com/path/to/file#section1中的"#section1"就是锚点,常见于a标签的超链接。

输入 url 敲回车后发生了什么

大厂常问:输入 URL 到显示页面的全过程

  1. 在浏览器地址栏输⼊URL

  2. 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到解码步骤

    • 如果资源未缓存,发起新请求

    • 如果已缓存,检验是否⾜够新鲜,⾜够新鲜直接提供给客户端,否则与服务器进⾏验证。

    • 检验新鲜通常有两个 HTTP 头进⾏控制 Expires 和 Cache-Control:

      HTTP1.0 提供 Expires,值为⼀个绝对时间表示缓存新鲜⽇期 HTTP1.1 增加了 Cache-Control: max-age=time,值为以秒为单位的最⼤新鲜时间

  3. 浏览器解析 URL获取协议,主机,端⼝,路径等信息

  4. 浏览器组装⼀个 HTTP(GET)请求报⽂

  5. 浏览器获取主机 ip 地址,过程如下:

    • 浏览器缓存
    • 本机缓存
    • hosts⽂件
    • 路由器缓存
    • ISP DNS缓存
    • DNS递归查询(可能存在负载均衡导致每次IP不⼀样)
  6. 开启一个socket与目标 IP 地址端口建立 TCP 连接

    • 三次握手
  7. 建立 TCP 后发送 HTTP请求

  8. 服务器接受请求并解析,将请求转发到服务程序

  9. 服务器检查HTTP请求头是否包含缓存验证信息,如果验证缓存新鲜,返回 304 等对应状态码

  10. 处理程序读取完整请求并准备HTTP响应

  11. 服务器将响应报⽂通过TCP连接发送回浏览器

  12. 浏览器接收HTTP响应,然后根据情况选择关闭TCP连接或者保留重⽤

    • 四次挥手
  13. 浏览器检查响应状态码

  14. 如果资源可缓存,缓存资源

  15. 对响应进行解码

  16. 根据资源类型确定如何处理

  17. 解析 HTML构建 DOM 树,下载 CSS、JS 资源等,构造 CSS 规则树,执行 JS 脚本

面试官:Javascript 本地存储的方式有哪些?区别及应用场景? | web 前端面试 - 面试官系列

面试官: 既然有了 cookie 为什么还要 localStorage?😕😕😕Cookie 适合用于在客户端和服务器 - 掘金

Cookie、LocalStorage 和 SessionStorage:一次非常详细的对比!_cookie localstorage sessionstorage-CSDN 博客

什么是跨域

什么是跨域?跨域解决方法-CSDN 博客

跨域(Cross-Origin Resource Sharing,简称 CORS)是一种安全策略,用于限制一个域的网页如何与另一个域的资源进行交互。这是浏览器实现的同源策略(Same-Origin Policy)的一部分,旨在防止恶意网站通过一个域的网页访问另一个域的敏感数据。

所谓同源,指的是两个页面必须具有相同的协议(protocol)、域名(host)和端口号(port)

  1. 设置 document.domain 解决无法读取非同源网页的 Cookie 问题

    要求主域名相同

  2. 跨文档通信 API:window.postMessage()

  3. JSONP

    • JSONP 是服务器与客户端跨源通信的常用方法
    • 核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
  4. CORS

    • 普通跨域请求:只需服务器端设置 Access-Control-Allow-Origin
    • 带 cookie 跨域请求:前后端都需要进行设置
      • Access-Control-Allow-Credentials 设置为true
  5. Webpack 本地代理(本地调试)

线上环境跨域如何解决

面试官:聊聊你知道的跨域解决方案跨域是开发中经常会遇到的一个场景,也是面试中经常会讨论的一个问题。掌握常见的跨域解决方案 - 掘金

  1. 通过设置 CORS
  2. JSONP
  3. nginx 反向代理

重排(回流)、重绘、如何避免

面试官:怎么理解回流跟重绘?什么场景下会触发? | web 前端面试 - 面试官系列

事件循环、宏微任务都有哪些

面试官:说说你对事件循环的理解 | web 前端面试 - 面试官系列

JS 是单线程的,如果需要处理异步任务,不能在异步任务那里阻塞住,因此有了事件循环。

首先将任务分为同步任务异步任务,如果是同步任务则直接推入主线程去执行,异步任务则会加入到异步任务队列。当主线程执行结束后,会从任务队列中读取对应的任务,推入到主线程执行。这个过程重复执行就构成了事件循环。

而任务队列又分为宏任务队列微任务队列,执行时会优先执行微任务队列的任务直至清空,然后取一个宏任务执行,宏任务结束后再次清空微任务队列的任务,循环往复。

浏览器的事件循环和 NodeJS 的事件循环的区别

面试官:说说对 Nodejs 中的事件循环机制理解? | web 前端面试 - 面试官系列

在浏览器事件循环中,是根据HTML5定义的规范来实现。而NodeJS的事件循环是基于libuv实现的,libuv是一个多平台的异步 IO 库。

Nodejs 事件循环分为六个阶段

img

  • 定时器检测阶段(timers):本阶段执行 timer 的回调,即 setTimeout、setInterval 里面的回调函数
  • I/O 事件回调阶段(I/O callbacks):执行延迟到下一个循环迭代的 I/O 回调,即上一轮循环中未被执行的一些 I/O 回调
  • 闲置阶段(idle, prepare):仅系统内部使用
  • 轮询阶段(poll):检索新的 I/O 事件;执行与 I/O 相关的回调(几乎所有情况下,除了关闭的回调函数,那些由计时器和 setImmediate() 调度的之外),其余情况 node 将在适当的时候在此阻塞
  • 检查阶段(check):setImmediate() 回调函数在这里执行
  • 关闭事件回调阶段(close callback):一些关闭的回调函数,如:socket.on('close', ...)

每个阶段对应一个队列,当事件循环进入某个阶段时, 将会在该阶段内执行回调,直到队列耗尽或者回调的最大数量已执行, 那么将进入下一个处理阶段,直观表现是,宏任务队列全部执行完才会执行微任务队列,而浏览器是宏任务执行一个就去执行微任务队列。

除了上述 6 个阶段,还存在process.nextTick,其不属于事件循环的任何一个阶段,它属于该阶段与下阶段之间的过渡, 即本阶段执行结束, 进入下一个阶段前, 所要执行的回调,类似插队

浏览器缓存

浏览器缓存机制

HTTP 和 HTTPS 的区别

面试官:什么是 HTTP? HTTP 和 HTTPS 的区别? | web 前端面试 - 面试官系列

React

React Fiber 是什么

一问读懂 React Fiber

React 网络请求放在哪里合适

网络请求放在哪里最合适

放在componentDidMountcomponentWillMount有什么区别

推荐放在componentDidMount

原因:

  1. componentWillMount生命周期在新版中已经过时或者被废弃
  2. React 官方推荐在componentDidMount中发送网络请求
  3. 如果使用服务端渲染componentWillMount这个生命周期的网络请求会发送两次,一次在服务端,一次在客户端,而componentDidMount没有这个问题,只会在客户端请求
  4. 如果组件 render 时发生了异常导致不能正常挂载,componentDidMount则不会发送请求,而componentWillMount会发送请求,请求到的数据无法被使用,浪费资源

使用 Hooks 相比于类组件的优势

  1. 简化代码
    • 类组件需要定义构造函数、生命周期方法等,而函数式组件只需要函数本身,减少了很多样板代码
  2. 易于组合和重用逻辑
    • 使用 Hooks 可以容易地提取和复用组件中的逻辑
  3. 避免了 this
    • 减少了 this 的复杂性,代码更清晰

JSX 如何编译渲染到页面中

  1. 浏览器不能识别 jsx 代码,需要转成 js 代码。

  2. 首先通过 Babel 转换工具将 jsx 转换为 js 代码

    1
    2
    3
    const element = <h1>Hello, world!</h1>;
    // 转换后,分别是 标签的类型、标签的属性值对象、标签的内容(子元素)
    const element = React.createElement('h1', null, 'Hello, world!');

    React.createElement创建的对象也叫做虚拟 DOM

  3. 将虚拟 DOM 转为真实 DOM

    使用React.createRoot创建根对象,然后将虚拟 DOM 渲染到 id 为 root 的 DOM 节点中。

Babel 是什么?转换原理?

Babel 的原理-CSDN 博客

BabelJavaScript 编译器,可以将 TS、JSX、TSX 等转成需要的代码。

Babel 内部原理是将 JS 代码转换为 AST,对 AST 应用各种插件进行处理,最终输出编译后的 JS 代码。

React Hooks 为什么不能放在 if else 中

讲清楚为什么 React Hooks 不能放在条件语句中

多个 Hooks 在 React 中是以链表的形式存在的,第一次渲染时会形成一个链表,存储着所有的 Hook 的信息,后边渲染时都会按照这个链表的信息更新 Hook,如果有判断条件,会导致重新渲染前后的链表不一致,导致状态混乱。

useEffect 和 useLayoutEffect 的区别

「React」useEffect 与 useLayoutEffect 使用与区别_useeffect 和 uselayouteffect 使用场景-CSDN 博客

  • useEffect
    • 组件渲染到屏幕后异步执行
    • 全部 dom 更新完成、浏览器绘制之后异步执行
    • 不会阻塞页面渲染
  • useLayoutEffect 和 useEffect 类似,但也有区别
    • 全部 dom 更新完成后同步执行,在浏览器绘制前执行
    • 会阻塞浏览器渲染
  • 一般推荐默认使用 useEffect,只有在涉及到需要在布局渲染阶段同步执行的 DOM 操作或有严格的顺序要求时,才使用 useLayoutEffect

组件中的 key 属性有什么作用

React 存在 Diff算法,而元素key属性的作用是用于判断元素是新创建的还是被移动的元素,从而减少不必要的元素渲染。

因此key的值需要为每一个元素赋予一个确定的标识

父子组件的子组件有个 key,每次渲染后 key 值+1 后会发生什么

组件被卸载并重新挂载

  • React 使用 key 来唯一标识列表中的每个子组件。
  • key 改变时,React 会认为这是一个全新的组件。
  • 结果是,原来的组件实例会被卸载,新的组件实例会被挂载。

组件的状态丢失

  • 如果子组件内部有本地状态(useState 或类组件的 state),状态会在每次 key 改变时被重置。
  • 这是因为 React 认为这是一个新组件实例,旧的状态无法保留。

性能影响

  • 每次 key 改变,React 会卸载和重新挂载子组件,而不是重用现有的 DOM 和组件实例。
  • 这会增加不必要的渲染和计算负担,从而影响性能,特别是当子组件包含复杂逻辑或有较多 DOM 元素时。

React 性能优化

面试官:说说你是如何提高组件的渲染效率的?在 React 中如何避免不必要的 render? | web 前端面试 - 面试官系列

shouldComponentUpdate,更新前手动比较更新前后的值,如果相同则返回false不进行更新,否则返回true更新

PureComponent

React.memo,缓存组件,给组件的props参数更新时,才会更新组件,只适用于函数式组件

  1. 避免使用内联函数

    • 比如事件回调时,避免在回调时设置类似于箭头函数,而是在外层定义好,直接用函数名代替,避免重复生成函数。
  2. 使用 React.Fragments 避免额外标记

    • 空标签或者 fragment 标签可以作为顶级标签使用,不会像组件引入任何额外标记
  3. 使用 Immutable

    • 使用 Immutable可以给 React 应用带来性能的优化,主要体现在减少渲染的次数

      在做react性能优化的时候,为了避免重复渲染,我们会在shouldComponentUpdate()中做对比,当返回true执行render方法

      Immutable通过is方法则可以完成对比,而无需像一样通过深度比较的方式比较

  4. 使用 lazy 组件懒加载

Context 和 Redux 的区别

【react】context VS redux 前言 自从新的 context API 和 hook 特性相继出来后,江湖上类似于 - 掘金

  • Context

    主要用于解决跨组件数据传递和共享问题,祖先组件通过Context.Provider组件发布数据,后代组件可以通过Context.Consumer或者useContext钩子订阅数据进行消费

  • Context + useReducer

    通过Context管理状态,useReducer改变状态,可以简单实现状态管理的功能。

    但是订阅了 context 实例的组件,当数据更新时,即使这个组件没有消费更新的数据,该组件仍然会重新渲染。

  • Redux

    完整的状态管理框架。通过React-Redux管理状态,当组件消费数据时,其他数据更新不会影响到该组件,只有消费的数据更新了,才会重新渲染。

  • 调试工具

    Redux调试工具可以清楚的看到状态什么时候发生了什么变化,而Context不能看到,只能看到当前的状态

ReactContext

React 组件通信方式

父组件向后代组件传递数据,

父组件通过React.createContext创建一个context

1
const testContext = React.createContext('test');

通过testContext.Provider组件包裹后代组件,将要传递的数据放在Provider组件中。

1
<testContext.Provider value={100}></testContext.Provider>

后代组件获取这个数据可以使用testContext.Consumer组件

1
2
3
4
<testContext.Consumer>
{/* 必须写一个函数,获取的数据放在了函数入参里 */}
{(value) => <div>{value}</div>}
</testContext.Consumer>

或者在类组件中设置contextType属性接收

1
2
3
4
5
6
7
class MyClass extend React.Component {
static contextType = testContext;
render() {
// 获取数据了
let value = this.context;
}
}

React 的发布订阅模式

React 虚拟 dom diff 操作

面试官:说说 React diff 的原理是什么? | web 前端面试 - 面试官系列

  • tree diff,层级比较,树中同一个层级的比较,只有添加、删除操作
  • component diff,组件比较,组件比较类型,类型不同则直接删除旧的,添加新的(连同子组件一并删除、添加)
  • element diff,元素比较,有删除、添加、移动操作。
    • key的情况下可以比较快的移动完成
    • 主要是index, oldIndex, maxIndex,通过这三个值比较,然后进行移动操作
    • 按照新集合的顺序进行排列,即index的值为0, 1, 2, ..., n,然后对比旧集合中key,依次将旧集合的位置索引赋值给oldIndex,所以oldIndex可能为2, 0, 1, 3, ..., n,初始值maxIndex设置为 0
    • 按照如下规则对index进行遍历
      • oldIndex > maxIndex时,令maxIndex = oldIndex
      • oldIndex === maxIndex时,不操作
      • oldIndex < maxIndex时,将oldIndex位置的元素移动到index的位置。

React render 函数理解

面试官:说说 React render 方法的原理?在什么时候会被触发? | web 前端面试 - 面试官系列

render函数里面可以编写JSX,转化成createElement这种形式,用于生成虚拟DOM,最终转化成真实 DOM

React 中,类组件只要执行了 setState 方法,就一定会触发 render 函数执行,函数组件使用useState更改状态不一定导致重新render

组件的props 改变了,不一定触发 render 函数的执行(父组件使用useRef传参,父组件更新 ref 对象,但是子组件不会重新渲染),但是如果 props 的值来自于父组件或者祖先组件的 state,在这种情况下,父组件或者祖先组件的 state 发生了改变,就会导致子组件的重新渲染

所以,类组件一旦执行了setState就会执行render方法,函数式组件useState 会判断当前值有无发生改变确定是否执行render方法,一旦父组件发生渲染,子组件也会渲染

  • 在组件生命周期或 React 合成事件中,setState 是异步
  • 在 setTimeout 或者原生 dom 事件中,setState 是同步

React 生命周期

react 生命周期总结(旧、新生命周期及 Hook)-腾讯云开发者社区-腾讯云

shouldComponentUpdate 周期有什么作用?

CSS

对于 CSS 预编译语言的理解

面试官:说说对 Css 预编语言的理解?有哪些区别? | web 前端面试 - 面试官系列

扩充了 CSS,增加了变量、函数等功能。可以认为是 CSS 的超集。不同的预编译语言有不同的解析器,最终这些都会被编译成对应的 CSS 文件。

主要有 sass, less, stylus,三种。

扩充了一些功能,如

  1. 变量

    • sass:$red: #abc使用$开头,冒号分隔
    • less: @red: #abc使用@开头,冒号分隔
    • stylus: red = #abc直接定义,等号分隔
  2. 作用域

  3. 混入

    • 将一部分样式抽离出来,然后被重复使用
  4. 代码模块化

实现三栏布局

7 种方式实现三栏布局

position 每个属性和作用

JavaScript

对于 Promise 的理解

Promise 的理解

Promise是异步编程的一种解决方案,比传统的解决方案(回调函数)更加合理和更加强大

  • 链式操作减低了编码难度
  • 代码可读性明显增强

有三种状态:

  • pending(等待中)
  • fulfilled(成功)
  • rejected(失败)

pending变为fulfilled或者rejected后,就不会再改变

async 异步函数如何捕获异常

1
2
3
4
async function fn() {
await fetchData();
}
fn();

当执行fn函数时fetchData可能会抛出异常,如何捕获异常?

1. try-catch

1
2
3
4
5
6
7
8
async function fn() {
try {
await fetchData();
} catch (error) {
console.log(error);
}
}
fn();

2. 内部catch

1
2
3
4
5
6
async function fn() {
const data = await fetchData().catch((e) => console.log(e));
// 如果有异常,则data无数据
if (!data) return;
}
fn();

3. 外部catch

1
2
3
4
async function fn() {
await fetchData();
}
fn().catch((err) => console.log(err));

闭包是什么

闭包的理解

一个函数和对其周围状态的引用捆绑在一起,这个组合就形成了闭包,换句话说,闭包可以在函数内部访问到函数外部的作用域。

闭包可以:

  • 创建私有变量
  • 延长变量的生命周期

通常的使用场景:

  • 计数器
  • 函数柯里化
  • 防抖

有哪些模块规范

深入对比 esModule 和 commonjs 模块化的区别前言 commonjs 2009 年,Ryan Dahl 基于开源的 V - 掘金

主要有commonJS, AMD, CMD, ESModule,现在主要使用的是commonJS, ESModule

两者的区别:

  • 引入方式
    • commonJS是动态导入,可以在任何地方引入
    • ESModule模块是静态导入(在编译阶段进行导入),不能动态加载语句,所以 import 不能写在块级作用域和判断条件内
  • 使用语法
    • commonJS是通过module.exports, require导出和导入
    • esModule通过import, export导入导出
  • 模块导入方式
    • commonJS是运行一遍代码,将module.exports的值赋值给变量
    • esModule模块输出的是一个值的引用, 使用的是动态绑定,esModule 导入导出的值都指向同一个内存地址,所以导入值会跟着导出值发生变化
  • 加载模式
    • commonJS是同步加载
    • esModule是异步加载

区别原因:

  • 同步加载会导致浏览器出现卡顿的情况。而 node 大多运行在服务端,同步加载本地文件速度很快。浏览器加载模块通常是网络请求,同步的话会出现卡顿的情况。

JS 的有哪些数据类型

  1. 基本类型

    Number, String, Boolean, Undefined, null, Symbol

  2. 复杂类型

    统称为 object 类型,常见的有Object, Array, Function

面试官:说说 JavaScript 中的数据类型?存储上的差别? | web 前端面试 - 面试官系列

实现一个 request,失败后间隔 interval 重试,设置最大重试次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async function request(url, options, interval, maxCount) {
// 重试次数
let retries = 0;
while (retries < maxCount) {
try {
// await会阻塞,直到返回
const response = await fetch(url, options);
return response;
} catch (error) {
// 如果有错误,说明请求失败,重试
retries++;
// 这里使用await阻塞,表示间隔时间
await new Promise((resolve) => setTimeout(resolve, interval));
}
}
}

字符串 slice, substring, substr 的区别

slice, substring, substr 的区别

new 关键字的执行过程

面试官:说说 new 操作符具体干了什么? | web 前端面试 - 面试官系列

  1. 创建一个空对象
  2. 新对象原型指向构造函数的原型对象
  3. 将新对象设置为构造函数的this,执行构造函数
  4. 函数返回值不为对象或者是null,则返回新对象,否则返回函数的返回值

JS 的垃圾回收

深入了解 JavaScript 垃圾回收机制_javascript 的垃圾回收机制讲一下-CSDN 博客

ES6 常用 api

async, await 实现原理

async 表示声明一个异步函数,这个函数返回值是一个 Promise 对象,如果返回值不是 Promise 类型,则会将返回值包装成 Promise 类型。等同于 Promise.resolve(x)。

await 表示等待的意思,可以等待异步函数也就是 Promise 对象,也可以等待普通的变量值。并且只能在 async 函数中使用。

使用 yield 实现 async,核心原理是递归迭代执行 next

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function myAsync(gen) {
return function (...args) {
return new Promise((resolve, reject) => {
const iter = gen(...args);
const step = (arg) => {
const { value, done } = iter.next(arg);
if (done) {
return resolve(value);
}
Promise.resolve(value).then((val) => step(val));
};
step();
});
};
}

async/await 可以看作是生成器的语法糖。

将生成函数的 * 替换成 async,将 yield 替换成 await

var, let, const 之间的区别

面试官:说说 var、let、const 之间的区别 | web 前端面试 - 面试官系列

  • 变量提升

    var有变量提升,let, const没有

  • 暂时性死区

    var没有暂时性死区,let, const有,只有执行到let, const那行以后才可以使用变量。

  • 块级作用域

    var没有块级作用域,在作用域内声明的,作用域外也可以使用。let, const在作用域内声明的不能在作用域外使用。

  • 重复声明

    var可以重复声明,let, const在同一个作用域内不可重复声明

  • 修改声明的变量

    var, let可以修改声明的变量,const声明时必须初始化,且后边不可修改。

事件流

事件与事件流

事件:通常是使用 js 与浏览器 HTML 文档进行交互的操作,如点击事件等。

事件流三个阶段:

  1. 事件捕获阶段
  2. 事件处理阶段
  3. 事件冒泡阶段

原始事件模型

绑定方式简单,可以在 HTML 代码中直接绑定,也可以通过 js 代码绑定

1
<input type="button" onclick="func()" />
1
2
const rootEl = document.getElementById('root');
rootEl.onclick = func;
  • 只支持事件冒泡,不支持捕获
  • 同一个类型事件只能绑定一次,后边的会覆盖前边的
  • 绑定速度快

标准事件模型

通过addEventListenerremoveEventListener添加和删除事件监听,参数分别为eventType, handler, useCapture,表示事件类型、回调函数、是否捕获(true表示在捕获阶段执行,false表示在冒泡阶段执行)。

1
2
3
4
5
const rootEl = document.getElementById('root');
// 冒泡阶段执行
rootEl.addEventListener('click', handleClick, false);
// 捕获阶段执行
rootEl.addEventListener('click', handleClick, true);
  • 支持事件捕获、事件处理、事件冒泡三个阶段
  • 支持绑定多个事件,不冲突

IE 事件模型(基本不用)

分为事件处理阶段事件冒泡阶段

事件冒泡

父子元素,子元素的事件会将该事件层层上报,使得父元素也发生该事件

事件委托

面试官:解释下什么是事件代理?应用场景? | web 前端面试 - 面试官系列

JS 中的事件冒泡、事件捕获、事件委托 DOM 事件流(event flow )存在三个阶段:事件捕获阶段、处于目标阶段、事件 - 掘金

JS 如何实现异步操作

详解 JS 的四种异步解决方案:回调函数、Promise、Generator、async/await(干货满满)...-CSDN 博客

  • 最开始通过设置回调函数的形式
  • Promise
  • async、await

判断对象是不是数组

JS 判断是否为对象或数组的几种方法_js 判断是否是对象-CSDN 博客

  1. Arrays.isArray()

  2. val instanceof Array

  3. val?.constructor === Array

  4. isPrototypeOf,判断一个对象是不是在另一个对象的原型链上

    Array.prototype.isPrototypeof(val)

sourcemap

blog.csdn.net/weixin_40599109/article/details/107845431

主要是映射转换后的代码和源码的关系,方便做调试。

操作系统

进程和线程和协程的区别

进程之间的通信方式

算法和数据结构

DFS 和 BFS 区别、时间空间复杂度、应用场景

DFS、BFS 空间时间复杂度分析 - wkfxm - 博客园

由 Hexo 驱动 & 主题 Keep
访客数 访问量