排序算法
冒泡排序 冒泡排序(Bubble Sort)是一种 交换类 的基础排序算法,重复遍历待排序数组,依次 比较相邻两个元素,若顺序错误则交换二者,每一轮遍历都会将当前 未排序部分 中最大(或最小)的元素 “冒泡” 到末尾。 交换类排序算法通过 比较并交换元素位置 来实现排序,主要操作是相邻或远距离的元素互换。 典型算法 冒泡排序:相邻元素两两比较,大值逐轮"冒泡"到末尾。 快速排序:选定基准值,通过交换将序列分为左右两部分,递归处理。 核心思想 冒泡排序的核心思想是 相邻元素两两比较,通过不断交换将最值逐位后移。 每一轮从前往后遍历,比较每一对相邻元素,若前者大于后者则交换。这个过程中,较大的元素就像气泡一样,一步步 “冒泡” 到当前未排序区间的末尾。 每完成一轮,末尾就多一个已排好的最大值,下一轮比较范围缩短一位,若某轮无交换则提前结束。 实现过程 以升序排序为例: 进行一轮循环,每次循环都找到 未排序部分 的最大元素并交换到末尾,只需要查找 n-1 次就能完成排序(最后一个元素不需要排序)。 123for (let i = 0; i < n - 1...
异步编程
异步编程体系 JS 是 单线程 + 事件循环,所有耗时操作丢给浏览器 / Node 底层多线程处理,完成后把回调推入 任务队列,主线程同步代码执行完再取队列执行。所有异步方案,全部基于 回调函数入队执行 这套底层机制搭建。 回调函数模式 回调函数模式是 JS 异步编程 最原始、最通用 的实现方式,所有更高层的异步方案本质都是 对回调的封装。 核心逻辑 异步操作执行完成后,调用预先传入的回调函数来传递结果,通常遵循 错误优先 的约定(Node.js 生态的统一规范)。 错误优先:第一个参数永远是 错误对象,成功时 error 为 null,后续为结果。 错误优先回调成功 / 失败双回调123456789// Node 文件读取 APIfs.readFile("./a.txt", function (err, data) { if (err) { // 单独处理当前层错误 console.error(err); return; } console.log(data.toString());});1...
遍历
数组遍历 全量遍历 forEach 遍历数组,对每一项执行回调函数,无返回值,除非抛出错误否则 无法中断遍历。 arr.forEach(callback(currentValue, index, array), thisArg) 参数列表 参数 说明 currentValue 当前遍历的元素 index 当前元素索引(可选) array 调用方法的原数组(可选) thisArg 指定回调内的this指向(可选) 调用示例 1234567891011121314151617const fruits = ["苹果", "香蕉", "橙子"];const context = { prefix: "我喜欢的水果:", printFruit: function (name) { console.log(this.prefix + name); },};fruits.forEach(function (currentValue, ...
垃圾回收
内存泄露 程序在运行过程中,已经不再需要使用的内存,没有被操作系统或垃圾回收机制正确释放,导致 可用内存持续减少 的现象即 内存泄露。 内存泄露的场景 1. 意外的全局变量 12345678910function leak() { // 没有 var/let/const,直接赋值 leakedVar = "这个变量挂在了 window 上"; // 在非严格模式下,函数内部的 this 指向 window this.anotherLeak = "我也是全局的";}leak();// leakedVar 和 window.anotherLeak 永远无法回收,直到页面刷新 使用 use strict 严格模式,它会禁止自动创建全局变量。 隐式全局变量:在非严格模式下,直接给一个未声明的变量赋值,JS 不会报错,会自动把这个变量挂载到全局对象上,变成一个全局变量。 2. 被遗忘的定时器、事件监听器 12345678910const btn = document.querySelector("#btn&qu...
事件循环
JavaScript 设计为单线程的原因 JavaScript 在1995年诞生时就是作为浏览器脚本,让网页拥有交互能力。 如果允许多线程操作 DOM,需要引入 锁机制,但早期网页只需要简单的表单验证和动画,从简单、安全的角度考虑,JS被设计成了单线程,从根源上 避免了 DOM 操作可能产生的并发冲突。 Java 和 JavaScript 语言毫无关系,只是为了商业营销而改名。 WebWorker 拥有独立线程,但是不能访问 DOM,DOM 操作 必须限制在主线程。 DOM 和 BOMDOM(文档对象模型)提供 操作文档节点的 API,document 是 DOM 的根节点。 BOM(浏览器对象模型)提供 与浏览器窗口交互的 API,window 是 BOM 的根结点。 为什么需要任务队列 JavaScript 的异步 API 是 由宿主环境提供 的,定时器、文件读写等异步操作都交给浏览器底层线程处理,它们的回调 不能立刻执行,必须先存起来,存放容器就是 任务队列。 JS 采用 非抢占式调度,不允许中途打断正在执行的同步代码:一旦允许随时插入回调,执行顺序不可预测,会产生大...
闭包
闭包的定义 如果一个内层函数访问了外层函数作用域里的变量,那么即使外层函数执行完被销毁了,内层函数依然能访问到那些外层变量,这个 内层函数 + 被它捕获的外层变量 的集合就叫做 闭包。 只要一个语言支持 满足以下两个条件 的函数,就可以认为支持闭包: 函数可以作为参数、返回值传递,也可以赋值给变量。 函数可以捕获定义时所在作用域的变量,哪怕原作用域已经销毁,这些被捕获的变量依然可以被访问。 闭包不是特意创造的功能 在 ES 标准里,没有单独定义闭包这个语法,只是定义了词法作用域和函数的传递规则,闭包是实现这些规则时 自然而然的产物:如果一个函数被拿到它定义的作用域之外执行,而它又需要访问定义时父作用域的变量,JS 引擎就必须保留这些外层变量,不能随着外层函数执行完就销毁,否则函数在外面执行的时候就找不到变量了。 ECMAScript 与 JavaScriptES 是 ECMAScript 的缩写,是由国际标准化组织 ECMA 国际 制定的脚本语言的通用规范标准,它不绑定任何具体的宿主环境,只规定脚本语言最核心的语法、特性、规则。 JavaScript 是 ES 规范 最知名...
模块
在 JavaScript 中,模块 的作用是:将代码分割成 独立、可复用 的文件,每个文件拥有独立私有作用域,通过导出、导入实现文件间代码复用。 主要有两大规范:CommonJS(CJS,Node.js 旧规范)、ES Module(ESM,ES6 新标准)。 CommonJS CommonJS 中,模块的导出本质是给 module.exports 对象赋值,所有需要对外暴露的内容都挂载在这个对象上。 CommonJS 是 Node.js 默认模块规范,浏览器不原生支持,运行时同步加载。 导出和导入 1. 导出单个内容(函数、对象、变量、类都可以) 12345678910// utils.js 导出一个工具函数function add(a, b) { return a + b;}// 直接把整个模块导出为add函数module.exports = add;// 导入的add就是utils.js导出的函数const add = require("./utils.js");console.log(add(1, 2)); // 3 2. 导出...
媒体播放器
快速阅读 功能概述 这是一个媒体播放器,用于播放视频和音频,可以修改播放速度、显示歌词、修改轮播逻辑、切换主题、缩放页面。 界面划分 上栏:包括白天/夜间模式切换、时间显示、媒体搜索框、消息提醒。 侧栏:包括主页、电影页、MV 页、音频页、自定义页、资源库 ABC。 主栏:显示选中的页面内容。 下栏:包括控制区、进度条、功能区。 按键控制 W A S:显示 / 隐藏上、侧、下栏 D:进入 / 退出主栏全屏 ← →:播放回退 / 播放快进 ↑ ↓:切换到上一个页面 / 下一个页面 F:进入 / 退出画中画 G:进入 / 退出视频全屏 Q:进入 / 退出缩放屏状态 R:打开 / 关闭主题窗口 T:打开 / 关闭模式窗口 V:打开 / 关闭词条窗口 B:打开 / 关闭视频窗口 1 2 3 4 5 6 7 8:切换到第 1 / 2 / 3 / 4 / 5 / 6 / 7 / 8 个页面 核心节点 轮播图:保存元素序列到数组,所有的元素横向排列,通过设定整体偏移距离实现轮播图效果。 缩略图:设置页面栈保存当前打开的页面,对不同的页面数进行不同方式的排版。 滑动栏:设定两个按键左移...









