前端开发-经验总结

文/晨风不可依米 (2025.10.12)



理解前端开发


前端开发,它是基于浏览器环境,使用html5css3javascript等编程语言构建操作界面,有序执行逻辑交互与服务器进行网络通信的工作内容。
简而言之,前端开发就是基于界面设计、逻辑交互、网络通信的综合性工作内容。


在前端工作的日常学习或开发中,我建议采用分层结构来设计实现功能需求。这种方法,能够快速捕获、理解、掌握功能技术的本质逻辑和实现原理。


界面设计,我概括为场景设计,千变万化。若基于场景设计来学习或开发前端内容,那么很难学得完所有场景,反倒是浪费更多的时间在无效学习过程中。


逻辑交互,我概括为实现步骤,多种方案。更为贴切地讲,这是一种技术选型;从根本上看,大多逻辑交互都是有序操作的,有其固定函数方法。场景需求的定义,不过是在核心逻辑上拓展其所需要的内容。


网络通信,我概括为通信协议,可自定义。在这一方面,主要强调数据的传输方式以及消息格式。这一点,请按后端工程师所定义的API文档可保证正常数据通信。






理解数据结构


数据结构,本质上是组织和存储数据的方式,目的在于合理利用内存资源来管理数据。


数据结构,描述了某个对象的抽象概括。对象所具有的特征,统称为属性;对象所具有的动作,统称为方法。


数据结构的读写操作,是优化数据操作过程中的重点内容。这就是优质程序代码的最终体现。


使用数据结构,应当考虑能否抽象概括对象的内容,再关注对象读写操作过程的性能考虑。






理解设计模式


设计模式,本质上是优化对象的数据结构、封装特定的逻辑交互,结合场景的按需拓展,以及减少重复编写程序代码。
简而言之,设计模式主要体现在对象解耦、代码复用、灵活拓展等这三个硬核标准范式。


设计模式,主要有三个大类;分别为创建型、结构型、行为型等模式。

  • 创建型模式:隐藏对象创建的细节,封装对象特定功能的逻辑。(不直接使用new创建对象)
  • 结构型模式:对象拆分可复用内容,并通过组合关系保持对象结构的灵活性和可扩展性。(组合代替继承、动态拓展功能)
  • 行为型模式:界定对象的分工与合作,确保对象间通信清晰、职责明确。(业务功能逻辑算法封装,中间层流处理)



创建型模式


工厂模式




抽象工厂模式




单例模式




建造者模式




原型模式




结构型模式


适配器模式




桥接模式




过滤器模式




组合模式




装饰器模式




外观模式




享元模式




代理模式




行为型模式




责任链模式




命令模式




解释器模式




迭代器模式




中介者模式




备忘录模式




观察者模式




状态模式




空对象模式




策略模式




模板模式




访问者模式







理解算法实现


算法,本质上是步骤清晰、可执行的有限指令序列。它描述了一组输入数据经过管道函数到最终产生输出结果的流程图;可简单理解为函数封装解决具体问题的概括。


算法的效率取决于数据结构的选取;算法操作的本质是对特定数据结构对象的内存管理。


算法的目的在于有序解决特定场景的业务需求。而设计模式的应用,在保持可灵活扩张的数据结构,让算法的程序代码变得可控、易读、好维护等。


算法的实现,应当优先考虑数据结构和设计模式这两方面。



前端开发者的核心技能


  • 理解业务需求,能够绘制业务流程图和系统流程图,主要识别场景、用户、传达信息、工具绘图、绘图流程等方面。
  • 掌握数据结构、设计模式、算法等知识技能,通过拆解问题、设计步骤、优化效率来实现高质量的程序代码的业务需求。
  • 开发实现流程:从数据逻辑、界面逻辑、事件逻辑依次开发流程;优先实现功能,后续考虑优化,最后确定实现效果。

浏览器渲染原理

重要概念


  • 浏览器渲染(render):将HTML文件内容(字符串)转换为浏览器可识别的像素信息(请通过输入 => 输出方式加强理解)。
  • 浏览器渲染总纲:浏览器的网络线程获取到html文档,将产生一个渲染任务,并且传递到渲染主线程的消息队列。在事件循环机制下,渲染主线程取出消息队列里的渲染任务,开启渲染流程。渲染流程会经过HTML解析样式计算几何布局图层划分矢量绘制位图分块纹理栅格封帧出图等阶段。



浏览器渲染流程(参照谷歌浏览器源码


HTML解析

  1. 浏览器网络线程根据超文本协议(http(s))加载HTML文档资源,并通过响应头信息(content-encodingcontent-type)解压缩、解编码转换为字符流,交给渲染主线程。
  2. 渲染主线程主要通过HTML解析器、预扫描器、CSS解析器,JS-V8引擎等协同完成渲染过程。渲染主线程会事先启动预扫描器快速抓取HTML文档里的资源链接,并交给网络线程加载相关资源。在HTML解析过程中,利用HTML解析器构建DOM树。遇到linkstyle标签,会通过主渲染任务切换机制交给CSS解析器构建CSSDOM树。遇到script标签就暂停解析,等待script标签资源内容加载并执行后,再恢复解析。
  3. HTML文档内容解析完毕(DOM树、CSSDOM树均已构建,且加载并执行全部JS脚本内容),HTML解析器会触发DOMContentLoaded事件通知DOM树构建完毕。
  4. 其它拓展

    • 渲染主线程利用预扫描器快速扫描、抓取资源链接,并通知网络线程并行加载相关资源,以减少相关资源加载等待时间。
    • CSSDOM构建过程在渲染主线程里,通过主线程任务切换机制异步构建,不发生阻塞现象(DOM树与CSSDOM树是2种不同数据结构树,互不影响)。
    • 渲染主线程遇到script时会停止解析过程,是源于JS 脚本操作会改变 DOM 节点的稳定状态(渲染主线程发生阻塞的根本原因)。
    • 所构建的DOM树,可通过document访问得到;所构建的CSSDOM树,可通过document.styleSheets访问得到。
    • 可通过script设置属性关键字asyncdefer来制定执行JS的阻塞策略。

标签关键字 下载阻塞HTML解析 执行阻塞HTML解析 归纳总结 应用场景
无设置 中断HTML解析 中断HTML解析,先解析再执行JS脚本 暂停HTML解析过程,执行JS脚本完毕再恢复HTML解析;多个script,按导入顺序执行 用户脚本执行(可能无法获取DOM对象)
async 不阻塞 加载完执行时发生阻塞 下载不阻塞、执行时阻塞;多个async,谁加载完,谁先执行 无依赖的第三方库初始化
defer 不阻塞 不阻塞,源于等待DOM完全构建才执行 下载、执行不阻塞;等待DOM完全构建且在DOMContentLoaded触发前执行;多个defer按导入顺序执行 有依赖的用户脚本或第三方库



样式计算


渲染主线程遍历DOM树,为遍历节点计算出最终样式。这一过程,会拆分为单独样式规则,并填充缺省值,以及样式值转换(相对值转绝对值,vw/vh单位除外);可通过控制台 > elements > computed查阅节点的最终样式。


  • 样式应用规则

    • 样式来源:行内样式 > 内联样式 > 导入样式 > (浏览器)默认样式
    • 级联顺序:!importtant > 自定义与默认(样式匹配精度 | 选择器权重)

  • 其它拓展

    • 视觉盒子模型
    • CSS计算过程



几何布局


渲染主线程遍历DOM树,并依次计算出节点的几何信息(尺寸、位置等),构建布局树。在构建布局树过程中,会忽略display: none的节点,计算伪类元素信息;并遵循内容必须在行盒内;行盒与块盒不能相邻规则构建布局树;因此DOM树与布局树并非一一对应关系。



图层划分

渲染主线程的图层划分,本质是决定哪些布局树为独立图层渲染;这样做的好处在于某一图层发生变化,仅重新渲染变化图层,从而提升渲染效率。可通过控制台 > Layers 查看图层划分结果。


影响图层划分的因素有:滚动条(scroll)、透明度(opacity)、动画变换(transform)、堆叠上下文(z-index非定位will-change: 指定规则)。



矢量绘制

渲染主线程为每个图层单独产生绘制指令集,用于描述每个图层的绘制过程。这一绘制过程,采用矢量绘制,并将矢量绘制信息提交给合成线程。


至此,渲染主线程的主要活动结束;后续交给合成线程处理。



位图分块


合成线程接收到图层的绘制信息,启用多线程对图层进行切块处理(256*266),形成图层的像素块载体。



纹理栅格


合成线程将图层的像素块载体交给GPU进程进行光栅化处理,最终转换为具有几何属性、纹理句柄的位图对象(quad)。



封帧出图


合成线程将具有几何属性、纹理句柄的位图对象(quad)并根据堆叠顺序(css 堆叠上下文规则)合并为一张完整的帧图像,且标记可合成图层(设置transformopacity等属性)交给GPU进程并行处理矩阵运算(transform高效率的根本原因);并将帧图像存储在GPU帧缓冲区里,后续将依赖GPU 60fps 流畅渲染保证出图。



浏览器渲染流程总结

  • 浏览器渲染流程:从网络线程解压缩、解编码并加载HTML文档资源(字符流),交给渲染主线程。渲染主线程会事先启动预扫描器快速抓取HTML文档里的资源链接,并交给网络线程加载相关资源。渲染主线程通过HTML解析器、CSS解析器,JS-V8引擎等协同合作完成渲染过程。HTML解析器会构建DOM树,在过程中遇到script标签就暂停解析,等待script标签资源内容加载并执行后再恢复解析;CSS解析器会构建CSSDOM树,为每个节点样式填充缺省值并计算最终样式。得到DOM树和CSSDOM树后,会根据每个节点的几何信息来完成布局树构建。得到布局树,根据堆叠上下文规则(滚动条、透明度、动画变换、层级属性、指定划分独立层)进行图层划分,并对每个图层单独产生矢量绘制指令集,再交给合成线程处理。合成线程通过图层的矢量绘制指令集对图层分块,切片为(256*256)图层像素块载体。得到图层像素块载体,合成线程通过GPU进程进行光栅化,返回具有纹理手柄、几何信息的位图对象。最后通过GPU进程将位图对象合并封装成帧图像,并利用GPU 60fps 流畅渲染核心机制交给屏幕显示最终效果图。简而言之,浏览器渲染流程会经过HTML解析样式计算几何布局图层划分矢量绘制位图分块纹理栅格封帧出图等阶段过程。

  • 渲染回流:是指布局树(Layout)的几何信息发生变化所致浏览器重新渲染;因此导致渲染回流的重要因素有:布局树节点的尺寸和位置变化。

  • 渲染重绘:是指图层矢量绘制指令集的样式规则发生变化所致浏览器重新渲染;因此导致渲染重绘的重要因素有:图层矢量绘制指令集的样式变化。


浏览器渲染线路流程图解

  • 渲染主线程主要活动:HTML解析 > 样式计算 > 几何布局 > 图层划分 > 矢量绘制
  • 合成线程主要活动:位图分块 > 纹理栅格 > 封帧出图



回流与重绘


回流(reflow)

回流的本质是重新计算Layout树。导致回流的重要因素:几何属性(尺寸、位置)。


特别注意:为了避免多次操作影响Layout树的计算,浏览器将多次操作合并,并在全部JS执行完毕后再计算Layout树。因此,改动Layout树的操作,是异步完成的;同样的,JS获取布局树属性,就有可能获取不到。最终,浏览器决定在获取布局属性时就发生回流。


重绘(repaint)

重绘的本质是重新根据图层产生矢量绘制指令集。导致回流的重要因素:样式内容。



前端 HTML 概念

HTML 术语统一概念:标签 = 元素 = 节点


语义化标签:用特定的标签表示特定的内容。


  • 结构语义标签-头部信息:header
  • 结构语义标签-导航信息:nav
  • 结构语义标签-侧栏信息:aside
  • 结构语义标签-主区信息:main
  • 结构语义标签-内容信息:article
  • 结构语义标签-底部信息:footer
  • 结构语义标签-自定分区:section
  • 文本语义标签-型号标题:h1h2h3h4h5h6
  • 文本语义标签-段落内容:p
  • 文本语义标签-自定内容:divspan
  • 文本语义标签-列表内容:ulolli
  • 文本语义标签-时间内容:time
  • 文本语义标签-地址内容:address
  • 文本语义标签-引用块内容:blockquote
  • 文本语义标签-文本短引用:q
  • 文本语义标签-文本高亮:mark
  • 文本语义标签-文本粗体:strong
  • 文本语义标签-文本斜体:em
  • 图表语义标签-图片内容:img
  • 图表语义标签-图表媒体:figure
  • 图表语义标签-图表说明:figcaption
  • 表单语义标签-表单容器:form
  • 表单语义标签-控件标签:label
  • 表单语义标签-控件分组:fieldset
  • 表单语义标签-控件分组标题:legend
  • 表单语义标签-单行文本控件:input
  • 表单语义标签-多行文本控件:textarea
  • 表单语义标签-按钮控件:buttonresetsubmit
  • 表单语义标签-选择控件:selectradiocheckbox
  • 表单语义标签-选择分组:optgroup
  • 表单语义标签-选择选项:option,仅对selectoptgroup有效。
  • 表格语义标签-表格容器:table
  • 表格语义标签-表格标题区:thead
  • 表格语义标签-表格主体区:tbody
  • 表格语义标签-表格底部区:tfoot
  • 表格语义标签-表格标题:caption
  • 表格语义标签-表格行:tr
  • 表格语义标签-表头单元格:th
  • 表格语义标签-数据单元格:td
  • 媒体语义标签-视频内容:video
  • 媒体语义标签-音频内容:audio
  • 链接语义标签-链接内容:a
  • 交互语义标签-折叠容器:details
  • 交互语义标签-折叠说明:summary

HTML 标签中,存在2种展示内容的标签。

  • 内容块标签:该标签结束后内容自动换行排版
  • 内容行标签:该标签结束后内容自动接续排版



前端 CSS 概念



前端 JavScript 概念

  • 数据类型:基本类型(简单数据段)存储在栈中;引用类型(简单数据段集合体)存储在堆内存中。
  • 基本类型(简单数据段)

    1. 空值:null
    2. 未定义值;undefined
    3. 布尔:Boolean
    4. 字符串(普通):String
    5. 字符串(符号):Symbol
    6. 数值(普通):Number
    7. 数值(大数):BigInt

  • 引用类型(简单数据段集合体)

    1. 对象:Object
    2. 数组;Array
    3. 函数:Function
    4. 正则:RegExp

  • 垃圾回收:标记清除、引用计数,手动清除(设置为null)。
  • 包装对象:将简单数据段包装成对象,并使对象持有源对象基本方法;一般都是通过基础类型值转换为引用类型值。

  • 执行环境、作用域、作用域链

    • 作用域:定义时已确定变量可被访问的范围。全局作用域的变量允许随时随地访问;函数作用域的变量,允许内部访问,但不允许函数外部直接访问,可通过函数对外暴露提供操作手柄。
    • 执行环境:程序执行时创建的动态容器,并管理运行时的数据状态,随运行时的生命周期结束时销毁。每个执行环境里,都存在一个变量对象。
    • 变量对象:执行环境内存储当前运行时有关数据状态的变量、函数、参数等集合体。当变量对象为函数时,变量对象也称活动对象。
    • 作用域链:由当前执行环境的变量对象,以及所有外出执行环境的变量对象所构成变量查找过程的路径。
    • 特别注意:除了函数表达式定义(如var test = function go () { ... }; test、go 都不发生变量提升),其它通过varfunction所定义的变量,会发生变量提升的过程。
    • 基于作用域链的变量查找过程。

      1. 当执行流进入一个函数,函数的当前执行环境就会被推入栈中;当函数执行完毕,栈将会把函数的执行环境弹出、销毁,并把控制权交给之前的执行环境。
      2. 源于作用域所规定变量的访问范围(外层不能直接访问里层,里层可以访问外层),查找所定义的变量,从当前执行环境的变量对象开始查找,找到直接返回并终止查找过程;否则,根据里层可以访问外层,就从外层执行环境的变量对象继续查找;直至全局变量对象里也未找到,那么返回undefined并终止查找过程。

    • 归纳总结:在所处位置定义变量,就决定变量可被访问的范围(外层不能直接访问里层,里层可以访问外层)。每个执行环境都有一个变量对象。执行环境中,有且只有一个全局执行环境,简称全局环境;其变量对象所存储的变量、函数等定义,也叫全局变量、全局函数。执行环境的变量对象无法直接访问,它源于程序运行时动态所创建,管理当前执行环境的数据状态,并在程序运行结束后随生命周期销毁(全局变量对象永远不会被销毁,源于全局执行环境时刻存在)。可通过浏览器雕调试模式在选项卡Source > Scope选项卡下的LocalGlobal等对象可实时观测。基于变量的查找过程,从当前执行环境的变量对象开始查找,找到直接返回并终止查找过程;否则依次往外层执行环境的变量对象继续查找,直至全局变量对象也未找到,返回undefined并终止查找过程。

  • 理解对象:对象是描述具体事物的抽象概括;具体事物的特征为属性,行为为方法。在面向对象中,对象具有以下特性:

    1. 抽象:描述具体事物的特征及行为。(抽象概括具体事物的模板)
    2. 封装:隐藏内部读写操作数据的细节。(隐藏内部业务逻辑细节)
    3. 继承:子类继承父类,具有父类共有的属性或方法。(常用于代码复用)
    4. 多态:同一操作作用不同对象,所具有的表现也不一样。(常用于拓展方法)

  • 对象成员:对象成员主要有2种类型,分别是实例成员和共享成员。

    • 实例成员是指实例对象自身特有的属性或方法;实例成员挂载在构造类(函数)内部。
    • 共享成员是来源于继承父类的属性或方法;共享成员挂载在原型对象prototype里。

  • 对象创建的方式:

    1. 工厂模式(抽取公共特证作为对象模板,不支持new调用)。
    2. 构造模式(从构造函数内添加实例成员)。
    3. 原型模式(从原型对象添加共享成员)。
    4. 组合模式(构造管实例成员、原型管共享成员)。
    5. 动态原型模式(嗅探成员不存在,则自动生成)。
    6. 寄生构造函数模式(与工厂模式无异,但支持new调用,避免普通调用)。
    7. 稳妥构造函数模式(与工厂模式无异,但没有公共属性。内部不允许使用this,外部不允许new调用)。

  • 对象继承的方式:

    1. 原型链(父类实例是子类的原型对象。JS中对象继承的核心)。
    2. 借用构造函数(通过在构造函数调用父类对象的借用方法)。
    3. 组合继承(通过借用构造函数继承实例成员,通过原型链继承共享成员)。
    4. 原型式继承(基于原有对象作为父类,定义并返回新的构造对象)。
    5. 寄生式继承(在原型式继承基础上,内部拓展新的成员内容来增强对象)。
    6. 寄生组合式继承(解决组合继承2次调用父类问题,并在寄生式继承基础上重写constructor的指向)。

  • 实例、构造函数、原型对象三者关系,(红宝书权威总结)如下:

    1. 创建新函数(构造函数),新函数会自动获得属性prototype,即原型对象;原型对象里有属性constructor,指向该新函数,用于对象识别的类型来源。
    2. 通过关键字new 新函数初始化实例对象,实例对象会自动获得属性__proto__(指针),指向新函数的原型对象。
    3. 因此形成实例对象.__proto__ = 新函数.prototype = 原型对象的关系;最终通过原型对象的属性constructor来识别对象创建的类型来源。

  • 理解原型与原型链:

    • 原型对象是来识别对象创建的类型来源;它包含可被继承的属性和方法,且原型对象属于共享成员的挂载点;因此一定程度上可理解为对象的共享模板
    • 原型连是JS编程语言中对象继承的核心;本质上是一系列原型对象串联而成的链条。通过这种对象与对象之间的关联关系实现继承(ES6 class底层实现也是原型链,并非类与类之间的模板复制)。
    • 基于原型链查找属性或方法的过程:

      1. 查询实例对是否具有所访问的属性或方法,有则返回并中断查询,否则往实例对象的原型对象上继续查询。
      2. 基于JS继承的核心(原型链,子类原型对象为父类实例对象),因此会优先查询父类的实例属性;若未找到,则继续往父类的原型对象(即原型对象的原型对象)查询。
      3. 重复步骤2,若还是未找到,最终到达原型链最顶层(null),并则返回undefined
      4. 归纳总结:对象属性或方法查找顺序是先实例成员,后共享成员的规律。先从对象自身查询,找到就直接返回并中断查询,未找到则往上一层原型对象查询,如此往复直至返回undefined

  • 函数是一等公民:函数本质上是封装特定逻辑的代码块。它允许独立执行、拓展方法、按值传递(赋值输入|出存储)。
  • 函数定义类型:函数声明式(由function直接定义)、函数表达式(将函数定义赋值给变量)。
  • 函数三要素:参数(输入)、函数体(执行逻辑)、返回值(输出)。函数快速实现,先确定输入与输出,再编写有序执行的逻辑步骤。
  • 函数递归:函数内部调用自身;在实现函数递归时,优先确认边界处理,再按实际情况实现调用自身。
  • 函数闭包:函数嵌套函数,内部函数持有外层执行环境的变量对象的引用,在函数执行结束后不被销毁(闭包保存的是执行环境的整个变量对象);那么内部函数就构成函数闭包(建议先看《红宝书》理解清楚执行环境变量对象作用域作用域链等概念)。
  • 函数防抖:事件在指定时间内多次触发,延迟并执行最后一次触发。(应用条件:频繁触发、耗时任务、最终结果)
  • 函数节流:事件在指定时间内多次触发,按时间频率间隔触发事件。(应用条件:频繁触发,间隔输出)
  • 函数私有成员与模块模式

    • 函数私有成员:本质上是函数嵌套过程中,里层函数的外层函数所定义的变量、方法,在函数调用过程中无法直接访问得到;除非通过函数对外提供访问手柄,或者函数提权操作来访问。
    • 函数模块模式:根据函数闭包原理(返回持有外层执行环境的变量对象的引用),并通过定义后立即执行的函数形式(IIEF)实现闭包隔离作用域,避免污染全局变量。

  • 函数的应用理解

    • 参数归一化:函数接收不同类型参数,并将参数转换为同一种类型参数处理。
    • 函数柯里化:将多参数函数转化为单参数函数的链式调用,依赖闭包保存中间参数。
    • 回调函数:本质上是弥补函数执行过程中的缺失。该缺失部分是无法确定因素,因此交给调用者自行决定。


======= 重新编辑闭包相关内容

  1. 普通函数:由关键字function定义,但所定义函数存在二义性;因此ES6通过箭头函数class声明进行区分。
  2. 闭包函数:通过在函数内定义私有成员,并返回可访问持有非基本数据类型的私宥成员的对象或函数(传统闭包返回函数,现代hook返回对象--持有非基本数据类型的引用)。

    • 传统闭包概念:函数嵌套函数,并返回函数。
    • 闭包hook应用:函数内定义私有成员,提供可访问
  3. 即时函数(IIFE):在定义后立即执行的函数,有初始化的性能开销。
  4. 惰性函数:通过嗅探并自我重写同等功能的函数,在首次调用时固化逻辑体内容,后续直接调用。

  • 函数的形式有2种,分别为函数声明式和函数表达式。函数声明式是通过关键字function直接定义,而函数表达式是将函数赋值给变量对象。
  • 理解作用域与作用域链:作用域是指对象有权访问变量的范围。作用域链是变量对象在确定过程所构成的线路方向;它遵循从当前所在的作用域开始确定变量对象的存在,找到就直接返回;若当前所在作用域不存在变量对象,那么将逐层向外层进行查找确定,直至全局作用域为找到,将返回undefined
  • 理解闭包:闭包是一种模块思想,防止变量污染;并允许在函数内部定义私有属性和方法,并通过对外暴露访问私有成员的接口。
  • 借用函数:在定义函数之后,函数自动获得3个相对应的方法(callapplybind)。

    1. 借用函数call会立即执行。第一个参数指代this指向,后续参数列表需逐个传递。
    2. 借用函数apply会立即执行。第一个参数指代this指向,后续参数列表以类数组形式集中在第二个参数。
    3. 借用函数bind不会立即执行,而是返回新函数。第一个参数指代this指向,后续参数逐个传递。注意,首次通过bind指定this指向,后续this指向不再改变。

  • 理解同步任务、异步任务:


    程序执行顺序:程序代码是自上而下执行(JS中存在变量提升概念,即varfunction定义会引起变量提升)。
    同步任务:程序代码执行后可直接获取结果。
    异步任务:程序代码执行后不可直接获取结果,需等待一定时间返回结果。

    1. script脚本。
    2. setTimeoutsetInterval等时间函数。
    3. Node里的setImmediate函数。
    4. I/O 回调:发送请求(xhrfetch)、文件读取(fs.readFile)。
    5. UI render(浏览器插在一次循环末尾)。
    6. requestAnimationFrame(浏览器,在渲染前)。

    微任务JS环境指定优先执行的异步队列任务。

    1. Promise.(then/catch/finally)
    2. queueMicrotask
    3. MutationObserver
    4. process.nextTickNode独有,比Promise还早)。

  • 理解事件循环过程:


    特别注意JS环境指定优先执行的异步队列任务,为微任务队列。在事件循环机制中,渲染主线程会进入无限循环状态检测任务存在,否则进入休眠状态。

    1. 全局JS自上而下执行,优先执行同步任务;遇到异步任务,将异步任务存放在同类型的异步队列里。
    2. 检测微任务队列是否存在任务,存在则优先执行,且保证微任务对列清空后再执行其它异步队列。
    3. 其它异步队列会根据浏览器实际情况进行任务调度执行。执行过程中可能产生微任务或其它异步任务,分别存储到相应的同类型队列里。
    4. 重复2-3步骤;若微任务队列、且其它异步队列都为空,那么事件循环进入休眠状态,等待下一轮唤醒事件循环。

  • 理解this的指向:

    1. 箭头函数里的this指向,看外层作用域确定。
    2. new实例或构造函数内部,this指向当前对象。
    3. 借用函数(callapplybind),this指向第一个参数。
    4. 对象方法的调用,this指向方法所属的对象。
    5. 无所属的函数调用,严格模式下指向undefined、非严格模式下指向当前环境全局对象。

  • 理解浏览器对象模型(BOM):

    1. 屏幕信息(screen):尺寸、色深、方向等。
    2. 历史会话栈(history):默认模式(多页应用),hash模式(老版本SPA)、history模式(现代SPA)。
    3. 路由导航(location):URL读写,导航跳转。
    4. 浏览器信息(navigator):UA、语言、网络、权限、硬件、插件等。
    5. 框架对象(frames):同源句柄直接操作,异源只认postMessage通信。
    6. 浏览器持久化(localStoragesessionStorageIndexedDB): 本地持久同步localStorage会阻塞;本地持久异步IndexedDB存量大;同步会话临时存储sessionStorage会阻塞。
    7. 视口与滚动:scroll*看内容,offset*必含边框。client*实盒大小,inner*浏览器视口。

  • 理解文档对象模型(DOM):

    1. DOM的本质是将标记语言文档(HTML/XML/SVG)解析成内存中的树形对象模型,供脚本语言(JavaScript)动态读写。

    2. DOM的节点类型:

      • NodeNode树所有节点都属于Node
      • Element:继承Node,用于表示文档标签的元素。
      • Document:继承Node,用于表示XML文档项目。
      • HTMLDocument:继承Document,用于表示window.document对象,对应document标签。
      • HTMLElement:继承Element,所有HTML元素的创建都基于该对象。
      • HTMLBodyElement:继承HTMLElement,表示document.body对象,对应body标签。
      • HTMLLinkElement:继承HTMLElement,表示a标签/元素对象,对应a标签。
      • CharacterData:继承Node,用于文本处理类的构造器。
      • Text:继承CharacterData,用于表示标签中所插入的文本内容。
      • Comment:继承CharacterData,用于表示注释内容,即<!-- 注释内容 -->
      • Attr:继承Node,用于标签中的属性内容。
      • NodeList:表示类数组的节点列表(快照形式、只读),可存储储元素、文本、注释等节点。
      • HTMLCollection:表示类数组的节点列表(始终实时、只读),仅存储元素节点。
      • NamedNodeMap:表示映射表的属性对象(始终实时、可读写),专管属性节点。


        特别注意:一个节点,必定存在3个属性,分别为nodeTypenodeNamenodeValue;且NodeValue仅在CharacterData类型时有值。

    3. DOM的读写操作:

      • 基本读取操作内容:nodeTypenodeNamenodeValuetagNameparentNodechildNodeschildrenfirstChildlastChildpreviousSiblingnextSiblingattributesinnerHTMLinnerTextstylegetAttributegetAttributesgetClientRectsscrollWidthoffsetWidthclientWidth(仅块盒)等。
      • 基本写入操作内容:createElementcreateTextNodeappendChildinsertBeforeremoveChildreplaceChild等。
      • 基本判断操作内容:hasChildNodeshasAttributehasAttributescontains等。
      • 选择器快捷方式:getElementByIdgetElementsByNamegetElementsByTagNamegetElementsByClassNamequerySelector(取首个)querySelectorAll等。
      • HTML DOM快捷方式:以document对象操作行为,如document.body;其它快捷方式有imagesappletslinksanchorsforms等。
      • HTML DOM拓展方式:以document对象操作行为,如document.title;其它拓展方式有cookiesreferrerdomain等。

    4. DOM的事件监听器:

      • 事件监听器的指定和移除:addEventListenerremoveEventListener
      • 事件传播(捕获与冒泡):事件捕获是事件触发后,从文档根节点往事件源标签确定事件源位置的过程;事件冒泡是事件触发后,从事件源标签往外层标签触发同类事件的过程。事件传播有3个阶段,按顺序为捕获阶段到达事件源位置冒泡阶段
      • 事件阻断传播(e.stopPropagation())与防止默认行为(e.preventDefault())。
      • 事件类型:鼠标类事件、键盘类事件、载入/窗口类事件、表单类事件。



浏览器的进程模型

重要概念理解

  • 进程:是指程序的专属内存空间。每一个应用程序至少有一个进程,程序进程之间相互独立。若进程之间需要通信,则需要进程双方同意。
  • 线程:是指系统调度的执行单元,即执行程序代码的存在。每一个进程至少有一个线程,即主线程。若程序需要同时执行多块代码,则需要多个线程。

特别总结:进程是固定面积的房子;线程是房子里的员工(负责分工合作);


浏览器的进程与线程

浏览器是一个多进程多线程的应用程序

  • 避免(标签页)相互影响,减少连环崩溃几率;浏览器在启动时,会自动创建多个进程服务。

  • 浏览器的主要进程

    1. 浏览器进程:负责浏览器相关的界面展示(标签页、导航地址、用户交互、子进程管理等)。
    2. 网络进程:负责加载网络资源;自动启用多线程来处理不同的网络任务(不同类型文件所致)。
    3. 渲染进程(前端理解重点):渲染进程启动后,会开启渲染主线程负责处理HTMLCSSJS等程序代码。默认情况下,浏览器为新标签页开启新的渲染进程,以保证标签页之间互不干扰。

  • 浏览器渲染主线程任务:

    • 解析HTML代码。
    • 解析CSS代码。
    • 样式计算。
    • 几何布局。
    • 图层处理。
    • 每秒绘制界面60次(帧率:FPS)。
    • 执行全局JS代码。
    • 执行事件处理函数。
    • 执行计时器的回调函数。
      ......

  • 浏览器渲染主线程为什么不开启多个线程处理。

    • 问题所在;任务调度是个问题--代码执行过程中遇到事件、计时器等任务,哪个任务优先处理。
    • 解决方案:浏览器的渲染主线程通过消息队列(事件循环机制)来排队解决该问题。



事件循环流程


  1. 渲染主线程启动,并进入无限循环状态(while (true) { 检测是否存在下一个任务,否则进入休眠状态 })。
  2. 若渲染主线程的消息队列中存在任务,那么取出并执行;执行完毕后,会进入下一个事件循环。
  3. 其它线程(包括其它进程里的线程),都可以对该消息队列的尾部追加任务。若消息队列为空,追加任务后会自动唤醒事件循环。
  4. 这一个过程循环往复,有条不絮处理消息队列的任务;就叫事件循环(谷歌浏览器的源码里也叫消息循环)。

特别总结:事件循环(消息循环)本质上是渲染主线程的工作方式。



理解同步与异步


  1. JS是一门单线程语言,并且运行在浏览器的渲染主线程里。
  2. JS程序自上而下执行代码。同步执行是指代码运行后能直接获得结果;异步执行是指代码运行后无法立即获得结果,需要等待时间获取结果。但浏览器的渲染主线程有其它任务执行,且每秒绘制界面60次;若需(长期)等待时间获取异步执行的结果(发生阻塞情况),则无法执行其它任务,那么浏览器会陷入掉帧、卡死、白屏等现象。
  3. 为保证渲染主线程不发生阻塞情况,渲染主线程通过将无法立即获得结果的相关处理(计时、通信、交互)打包成一个事件任务,交付给事件循环处理;渲染主线程得以继续其它任务处理。
  4. 特别提醒:浏览器渲染主线程承担极其重要的工作,永远不要发生阻塞情况(性能优化重点)。



理解浏览器的任务


在过去的浏览器,渲染主线程的任务可划分为宏任务和微任务,且微任务优先级高于宏任务。而如今,过去说法已无法满足复杂的浏览器环境。


现代浏览器将过去宏任务队列拆分成多个队列,并根据实际情况来调度执行。根据W3C官方定义:每一个任务都有不同类型,同类型任务必须存放在同一队列里;并规定浏览器主线程必须存在一个微任务队列,且微任务优先级最高,必须优先调度执行。


特别提醒:事件任务没有优先级,但消息队列有优先级。

  • 微任务队列:浏览器规定优先调度的任务队列,优先级最高。
  • 交互队列:用户操作后所产生的事件处理函数;高等优先级。
  • 延时队列;存放计时器到达的回调处理函数;中等优先级。

案例理解


<button id="test_btn">开始测试</button>
<button id="user_btn">交互执行</button>

const test_btn = document.querySelector("#test_btn");
const user_btn = document.querySelector("#user_btn");

function delay(ms) {
  const start = new Date().getTime();
  while (new Date().getTime() - start < ms) {}
}

function delayTask() {
  console.log("添加延时队列");
  setTimeout(() => {
    console.log("执行延时任务");
  }, 200);
  delay(2000);
}

function userHandleTask() {
  console.log("添加交互队列");
  user_btn.onclick = function () {
    console.log("执行交互任务");
  };
  delay(2000);
}

test_btn.onclick = function () {
  delayTask();
  userHandleTask();
  console.log("============");
};

// 输出结果如下:
添加延时队列
添加交互队列
============  (上方理解:程序自上而下执行;下方理解:事件循环 + 队列任务调度优先级-交互(用户触发)> 延时)
执行交互任务
执行延时任务



浏览器输入URL到界面显示全过程


  • 理解进程、线程、程序、指令等概念:进程是系统分配的独立资源边界;线程是系统调度的执行单元;程序是功能逻辑的流程;指令是处理器的计算动作。
  • 理解盒子模型:标准盒模型(width=content的宽度;);怪异盒模型(width=(border+padding+content)的总宽度)。
  • 理解CSS样式规则的格式上下文规范:
    1. 块格式上下文:盒模型内容单独占位一行,后续盒模型内容会自动换行写入。
    2. 行内格式上下文:多个盒模型内容不换行,以接续形式并排写入。
    3. Flex格式上下文:通过主轴、侧轴等进行对齐、分布、换行、拉伸等方式写入。
    4. Grid格式上下文:通过轨道(网格线)绘制显示网格,并在指定网格区块写入。若超出显示网格数量,则自动补足网格,也叫隐式网格。
    5. Table格式上下文:通过把表格拆分成单元格,并按“行、列、格”三层结构对齐,即单元格在同一列或同一行方式写入。
  • 理解浏览器的回流与重绘概念:
    1. 回流在浏览器渲染Layout阶段,即布局盒模型的几何属性发生变动时触发;重绘在浏览器渲染Paint阶段,即布局盒模型的外观属性发生变动时触发。
    2. 根据浏览器渲染流程阶段,回流在前,重绘在后。因此,回流必定导致重绘;而重绘可以单独发生。
    3. 注意:支持硬件加速的样式属性(合成属性四件套:transformopacityfilterwill-change)将跳过主线程Layoutpaint阶段,将在合成线程中处理。

阶段 所在线程 具体任务 同步/异步 产出物
1. DNS 查询 Browser 进程 I/O 线程 解析域名→DoH/DoT/UDP 异步 IP 地址
2. TCP+TLS 握手 Browser 进程 I/O 线程 建连、TLS 1.3 0-RTT 异步 已连接 socket
3. HTTP 请求/响应 I/O 线程 → HTTP 缓存 → 网络栈 发 Header、读 Body、解压 gzip 异步 字节流(Chunked)
4. HTML 分词 Renderer 主线程 Tokenizer 字节→Token 同步 Token 队列
5. 预扫描资源 Renderer PreloadScanner 线程 并行抓 <link>/<img>/<script> 异步 高优网络请求
6. 树构造 主线程 Token→Node→DOM 树 同步 活体 DOM + 样式脏标记
7. CSS 解析+样式计算 主线程 CSSBytes→RuleSet→ComputedStyle 同步 每个节点的 ComputedStyle
8. 布局(Layout) 主线程 生成 LayoutBox,算位置/尺寸 同步 LayoutBox 树
9. 图层划分 主线程 根据层叠上下文、will-change 建 PaintLayer 同步 Layer 列表
10. 绘制指令 主线程 每 Layer 生成 DisplayItemList 同步 矢量绘制命令
11. 栅格化 Renderer Raster Worker 线程池 DisplayItem→位图 Tile 异步 GPU 内存纹理
12. 合成 Renderer Compositor Thread 把 Tile+滚动偏移→DrawQuad 异步 DrawQuad 列表
13. 上架 GPU 进程 Display Compositor 线程 DrawQuad→OpenGL/Vulkan→FrameBuffer 异步(V-Sync) 真正像素
14. 单帧事件循环 主线程 执行 JS、MutationObserver、RAF 回调 事件驱动 新 DisplayItemList → 回到 10

  1. URL标准化与DNS查询过程细节:URL标准化(自动补充协议、端口等、并转换为完整URL),安全检查(HSTS、恶意列表),并将域名转换为对应IP。若浏览器使用缓存策略(强缓存:ExpiresCache-Control;协商缓存:If-Modified-SinceIf-None-Match;强缓存优先级高于协商缓存),则复用本地缓存。DNS寻址会通过浏览器内存、系统内存、系统磁盘、路由器DNS映射表、ISP递归寻址以及各层权威等层级查询,存在则直接返回并终止寻址。
  2. TCP+TLS握手过程细节:客户端向服务端发包请求同步序列编号,状态为SYN_SENT;服务端收包并向客户端发包表示确认,状态为SYN_RECV;客户端收到确认包,向服务端发包请求开启数据连接通道。客户端与服务端选定加密套件(密钥+证书+双方随机数),客户端和服务端协商计算出共享密钥;客户端和服务端利用共享密钥加密/解密并数据传输。
  3. HTTP请求/响应过程细节:构造请求(指定请求方式、参数、HTTP版本号、Header信息)时,会检测是否支持压缩、分块等传输,并经过TLS通道加密传输请求报文,服务端接收请求报文并TLS解密、解压缩、以及JSON反序列化,提取请求内容交给相应服务逻辑层处理;构造响应(指定状态码、Header信息以及返回内容),后续交给客户端解析处理。客户端接收服务端的响应头和MIME嗅探决定是否在网络线程下载相关资源,并在FilterSourceStream工作线程里解压缩,在URLLoader线程里读字节,预扫描(HTML资源优先)相关资源下载。浏览器主线程划分两条流水线处理内容:下载流水线和渲染流水线。
  4. HTML分词过程细节:读取服务端返回内容(数据流形式,也叫网络字节流),通过HTMLInputStream(UTF-8解码)获取文本数据内容,经过HTMLTokenizer状态机单趟扫描生成解释扫描内容的抽象对象Token;若在过程中遇到CSS/JS/图片/字体等相关资源,就交给网络线程下载,下载完后再通知渲染线程。
  5. 预扫描资源过程细节:在Renderer主线程分词过程中,抓取linkimagescriptsourceURL资源提前扔给网络线程,让下载与解析并行,省掉“解析到才下载”的空窗期。
  6. 树构建过程细节:解析已解码的文本数据内容,根据HTML标签创建对应的Node类型节点,并挂载在所属层级节点上。每一次树构建的节点变动,开发者可以通过MutationObserver监听树构建的状态。
  7. CSS解析+样式计算过程细节:读取服务端返回CSS资源(数据流形式,也叫网络字节流),通过(字节流解码器UTF-8解码)获取文本数据内容,通过状态机Tokenizer与词法解析Parser成样式规则StyleRule;将简写样式规则展开成多个单个样式规则,并对缺省值填充(初始化或继承值);以冒泡式(从右往左)匹配选择器;并按级联顺序(!important>作者样式>代理样式>默认或继承样式)计算出ComputedStyle对象;最后把计算值转换应用值、实际值。注意:vm/vh将在浏览器渲染Layout阶段转换为实际值;其它样式属性将在ComputedStyle过程计算得出。
  8. 布局(Layout)过程细节:根据ComputedStyle对象过滤不占用空间的样式规则(dispaly:none等),建立Layout树,生成LayoutObject对象;并通过计算独立格式化上下文(详见CSS样式规则的格式上下文规范)实现格式上下文规范层的内部布局(无外界无关);根据父子盒模型的几何属性协商可用宽高;遇到浮动样式优先排版,其原因是它脱离正常文档流(父盒子空间占位缩短,后续块盒应清除浮动方可正常排版布局);最后处理基线与对齐、溢出与滚动等布局内容。
  9. 图层划分过程细节:本质是决定哪些布局树为独立图层。根据ComputedStyle样式计算和布局盒模型LayoutBox的分层命中规则(3Dwill-changevideofixedmaskscroll、动画、重叠、内存限)划分独立图层(GraphicsLayer);其它布局树都将依附在父级布局树里,也作为独立图层。
  10. 绘制指令过程细节:通过独立图层(GraphicsLayer)内部的LayoutObject的子树遍历,形成一条条绘制矢量指令,并汇总为图层专用的DisplayItemList矢量指令集。
  11. 栅格化过程细节:主线程将DisplayItemList转换为图片(Picture),并随合成帧(CompositorFrame)交付给Impl线程进行切片,以层边界按256×256 默认尺寸打网格,生成Tile对象数组;通过队列方式在光栅线程池(RendererWorker)转换为位图Tile纹理对象(纹理句柄和几何属性)。
  12. 合成过程细节:合成器根据最新滚动偏移/缩放,算出可见矩形(视口)以及位图Tile纹理对象组装成矩形绘制命令(DrawQuad)。
  13. 上架(送帧)过程细节:汇总矩形绘制命令(DrawQuad)列表,并封装到合成帧(CompositorFrame),通过GPU进程交付给OpenGL/Vulkan,一次性提交到GPU的交换缓冲区(SwapBuffers)推送给屏幕V-Sync显示。
  14. 单帧事件循环过程细节:用户行为(点击、键盘、滚动)、动画函数(requestAnimationFrame)、宏/微任务队列、回流与重绘等都将触发屏幕V-Sync显示;即再次上架(送帧)。
  15. 四次挥手:主动与被动,取决于谁优先提出FIN;主方告知客方结束,客方回复准备收尾;客方回应收尾完成,主方关闭数据传输的连接通道。



浏览器请求对象(AxiosFetch



做具有产品经理能力的程序开发者

理解程序员的开发模式

  • 瀑布模式:需求明确固定,在分析、设计、编码、测试等阶段中,前一阶段完成并通过评审后进入下一阶段;持续渐进开发。
  • 增量模式:项目规划时间拆分多个迭代周期,按周期完成部分功能,并交付可执行版本;待评审以及反馈进行完善项目产品。
  • 敏捷模式:约定一个项目截止日期,但项目的需求量不固定;主要体现在力求出效果功能,不注重后期维护,容易崩盘终结。
    -DevOps模式:将开发与运维结合,通过自动化工具实现持续集成/部署、自动测试,以提高开发效率。

理解企业常见模式

企业模式有三大类别:云、业务、生产。


模式 所属线 一句话场景 英文全称
IaaS 只租“水电”——服务器+存储+网络 Infrastructure as a Service
PaaS 租“水电+厨房”——再加中间件、数据库 Platform as a Service
SaaS 直接租“成品菜”——账号登录就用 Software as a Service
DaaS 租“桌面或数据接口” Desktop / Data as a Service
CRM 业务 管理客户生命周期,让销售续费 Customer Relationship Mgmt.
ERP 业务 人、财、物、产、供、销一体化 Enterprise Resource Planning
SCM 业务 把供应商、仓库、物流串成网 Supply Chain Management
CMS 业务 管理内容,官网/电商/媒体都用 Content Management System
HRM 业务 招人、发薪、绩效在线化 Human Resource Management
OEM 生产 我只出品牌,工厂帮我贴牌 Original Equipment Manufacturer
ODM 生产 品牌+设计都别人做,我直接贴 logo Original Design Manufacturer
CM 生产 按我图纸代工,无品牌权 Contract Manufacturing
OBM 生产 自己设计、自己造、自己品牌 Original Brand Manufacturer
DevOps 云+生产 开发运维一体化,快速上线 Development & Operations
Agile CM 云+生产 用敏捷思想管配置、环境、变更 Agile Configuration Management

产品经理必会流程图


基础核心能力:能理解业务需求,具有绘制流程图泳道图UML图等能力。


列名 业务流程图 系统流程图
应用场景 需求调研及确认 技术方案选型实现
用户对象 业务方 各协作部门
传达信息 业务流程中的起点与终点、参与者、操作行为;可概括为项目业务的生命周期 各系统之间的数据流转、流向;可概括为数据的生命周期



编写整洁且高效执行的程序代码

  • 一个函数只做一件事。



一级标题

二级分类

三级内容

重要提醒: 四级提醒

特别注意:五级强调




文章收获

  • 如果觉得对你有所帮助,请点下“推荐”吧!
  • 如果担心文忘记章地址,请点下“收藏”吧!
  • 如果对博主文章内容喜欢,可进行“关注”博主,更好地获悉最新文章内容。
posted @ 2025-11-02 16:16  晨风不可依米  阅读(5)  评论(0)    收藏  举报