什么是事件循环
JavaScript 是一门单线程、非阻塞的语言。事件循环(Event Loop)是 JavaScript 实现异步编程的核心机制,它负责协调主线程执行同步代码和管理异步任务的执行顺序。
为什么需要事件循环
JavaScript 只有一个主线程,同步代码会阻塞主线程。事件循环的作用是在主线程空闲时,从任务队列中取出任务执行,从而实现「非阻塞」的特性。
执行栈和任务队列
执行栈(Call Stack)
执行栈是一个后进先出(LIFO)的数据结构,用于存储代码执行时的上下文。
JavaScript 是一门单线程、非阻塞的语言。事件循环(Event Loop)是 JavaScript 实现异步编程的核心机制,它负责协调主线程执行同步代码和管理异步任务的执行顺序。
JavaScript 只有一个主线程,同步代码会阻塞主线程。事件循环的作用是在主线程空闲时,从任务队列中取出任务执行,从而实现「非阻塞」的特性。
执行栈是一个后进先出(LIFO)的数据结构,用于存储代码执行时的上下文。
┌────────────────────────────────────────────┐
│ 浏览器渲染流程 │
│ │
│ JS/CSS → Layout(重排) → Paint(重绘) │
│ ↓ │
│ 几何属性变化 样式变化 │
│ (位置/尺寸/显隐) (颜色/阴影/背景) │
└────────────────────────────────────────────┘
Web Worker 是一种运行在主线程之外的 JavaScript 并行执行环境。通过 Web Worker,开发者可以将耗时的任务(如数据处理、文件解析等)从主线程中剥离,从而提高页面的响应速度和用户体验。
Frontmatter
参数是包含 Worker 脚本的文件路径。需要注意的是,文件必须与主线程在同源下运行。
文件预览是指在浏览器中直接查看各种文件内容,无需下载到本地安装对应软件才能打开。常见的场景包括:
kkFileView 是一个文件文档在线预览解决方案,使用 Spring Boot 搭建,易于部署和使用。
JavaScript 数组提供了丰富的方法来处理数据。本文详细介绍常用数组方法的用法及引入版本。
| 版本 | 年份 | 主要数组新方法 |
|---|---|---|
| ES5 | 2009 | forEach, map, filter, reduce, every, some, indexOf, lastIndexOf, concat, slice, splice, push, pop, shift, unshift, sort, reverse, join, toString |
| ES6 (ES2015) | 2015 | find, findIndex, fill, copyWithin, includes, Array.from, Array.of |
| ES2016 | 2016 | Array.prototype.includes |
| ES2017 | 2017 | flat, flatMap |
| ES2019 | 2019 | flat (增强), Array.prototype.flat |
| ES2021 | 2021 | Array.prototype.at, Promise.allSettled |
| ES2023 | 2023 | toReversed, toSorted, toSpliced, with |
全局只能存在一个实例,并在全局可以访问。
一般用于全局状态的共享和缓存。
class A {
static instance?: A
getInstance() {
if (A.instance) {
return A.instance
} else {
return new A()
}
}
}
MutationObserver用于监听Dom对象的变更,包括节点属性的变化、子节点的增删改。
const observer = new MutationObserver(callback)
后执行当持续触发事件,一定时间内没有再次触发事件,事件处理函数就会执行一次;如果在设定的事件内又出发了一次,那么就重新计时并不执行函数。
var input = document.getElementById('input')
//防抖函数
function debounce(delay: number) {
let timer
return function (value) {
clearTimeout(timer)
/*
* 我们想清除的是setTimeout 我们应该要存储timer这个变量
* 所以timer变量需要保存在内存中
* 所以在触发之前需要清除之前的定时器
* timer存储在内存中就要涉及到内存的泄露和闭包
* */
timer = setTimeout(function () {
console.log(value);
}, delay)
}
}
// 我们需要的是在键盘抬起后不再输入后的一秒之后触发函数打印
var debounceFunc = debounce(1000) // 这个是一个函数
input.addEventListener('keyup', function (e) {
debounceFunc(e.target.value)
})
undefined 表示不存在定义,声明变量但没有初始化,这个变量的值就是undefined; 注意:在任何一个引用变量值设置为undefined都是错误的
null ,表示一个值被定义了,定义为空值; 使用场景为 定义变量准备在将来用于保存对象;所以引用值可以是null而不会是undefined;
undefined和null的区别:js诞生的时候只设置了null作为“无”的值。最初的设计是null是表示一个“无”的对象,转为数值时为0; | undefined表示“无”的原始值,转为数值时为NaN;红宝书上说引入undefined就是为了正式的区分空对象指针与未经初始化的变量,变量设置为null就是空对象指针,没有设置就是未经初始化!
Boolean,字面值为true和false
number,字面量格式可以是十进制、八进制(八进制第一位必须是0)、十六进制(前两位必须是0x)
String 由零个或多个16位Unicode字符组成的字符序列
symbol,ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是ES6 引入Symbol的原因