当前位置:首页 > 文章列表 > 文章 > 前端 > JavaScript Range.compareBoundaryPoints 怎样比较两个范围的端点

JavaScript Range.compareBoundaryPoints 怎样比较两个范围的端点

来源:17golang原创 2026-10-27 14:25:28 0浏览 收藏

Range.compareBoundaryPoints(how, otherRange) 用来比较两个范围的边界点,结果只有三类:当前范围的指定边界在对方边界之前返回 -1,相同返回 0,之后返回 1。真正容易出错的地方不是返回值,而是四个 how 常量的配对方向,尤其是 END_TO_START。

文档入口:https://developer.mozilla.org/en-US/docs/Web/API/Range/compareBoundaryPoints。下面用同一文本节点建立两个可读的范围,先得到一组稳定的比较基线,再说明偏移单位和适用边界。

要点速览
  • 比较方向始终是“当前 Range 对 otherRange”,不是把两个 Range 交换后再猜结果。
  • START_TO_END 比较当前范围的终点与对方范围的起点;常量名要和映射表一起看。
  • 这个方法只比较边界点,不能单独回答两个范围是否重叠或是否包含。

先把四种边界配对写成表

可以把调用理解成“从当前 Range 取一个端点,再从 otherRange 取一个端点”。返回值比较的是这两个端点在文档树中的顺序:

how 常量当前 Range 取值otherRange 取值适合表达的关系
START_TO_STARTstartstart两个范围从哪里开始
START_TO_ENDendstart当前范围末端与对方起点
END_TO_STARTstartend当前范围起点与对方末端
END_TO_ENDendend两个范围在哪里结束
JavaScript Range compareBoundaryPoints 四种常量对应起点终点的静态关系图
图1:Range 边界配对说明图,展示四种常量如何从当前范围和对方范围取起点或终点;这是静态结构图,不是浏览器截图。

表中最值得单独记住的是:常量名的前半段对应当前范围,后半段对应对方范围,但实际比较的端点名称遵循 DOM API 的固定映射,不能凭英文直觉交换。遇到复杂逻辑时,先在代码旁写出“当前端点 → 对方端点”,再调用方法。

用一个可复核的文本节点建立比较基线

下面的两个范围都来自字符串 0123456789。当前范围是 [1, 6),对方范围是 [1, 4);方括号表示包含起点、不包含终点,便于把偏移和字符位置对应起来。

const text = new Text("0123456789");

const currentRange = new Range();
currentRange.setStart(text, 1);
currentRange.setEnd(text, 6);

const otherRange = new Range();
otherRange.setStart(text, 1);
otherRange.setEnd(text, 4);

// 四次调用分别比较起点、交叉端点和终点
const results = {
  startToStart: currentRange.compareBoundaryPoints(
    Range.START_TO_START, otherRange
  ),
  startToEnd: currentRange.compareBoundaryPoints(
    Range.START_TO_END, otherRange
  ),
  endToStart: currentRange.compareBoundaryPoints(
    Range.END_TO_START, otherRange
  ),
  endToEnd: currentRange.compareBoundaryPoints(
    Range.END_TO_END, otherRange
  )
};

// 预期为 { startToStart: 0, startToEnd: 1,
//          endToStart: -1, endToEnd: 1 }
console.log(results);

这里 START_TO_START 返回 0,因为两个起点都在偏移 1;START_TO_END 实际比较当前范围终点 6 与对方起点 1,所以返回 1。END_TO_START 比较当前范围起点 1 与对方终点 4,因此返回 -1;最后两个终点是 6 和 4,返回 1。

返回值只说明边界顺序,不直接说明重叠

把返回值翻译成业务判断时,始终使用“当前端点相对于对方端点”的方向。-1 表示当前端点在前,0 表示两个端点相同,1 表示当前端点在后。它类似比较函数的返回约定,不应被理解成距离或重叠长度。

JavaScript Range 比较端点后得到 -1 0 1 的关系说明图
图2:比较结果说明图,把端点关系映射到 -1、0、1 三种结果;它表达的是静态关系,不是执行流程或运行截图。

例如两个范围完全分离时,当前范围的终点与对方范围的起点可以用 START_TO_END 观察;但一个可靠的“是否重叠”判断仍需要同时考虑两个范围的起止关系。只看一次比较,无法区分“包含”“被包含”和“部分相交”等情况。

偏移单位和使用边界要先核对

Range 的边界点由节点和偏移组成。对 Text 节点,偏移是文本节点内部的位置;对元素节点,偏移表示子节点序号。不能把一个页面全局字符下标直接当成任意节点的 offset,也不要把 children.length 当作 childNodes.length。

function compareRanges(currentRange, otherRange, how) {
  if (!(currentRange instanceof Range) || !(otherRange instanceof Range)) {
    // 先拒绝不属于当前文档模型的输入,避免错误藏在比较结果里
    throw new TypeError("两个参数都必须是 Range");
  }
  if (![Range.START_TO_START, Range.START_TO_END,
        Range.END_TO_START, Range.END_TO_END].includes(how)) {
    // how 不是四个常量之一时,浏览器会抛出 NotSupportedError
    throw new TypeError("how 必须是 Range 的比较常量");
  }
  return currentRange.compareBoundaryPoints(how, otherRange);
}

这个封装只做参数边界说明,不会把返回值改成布尔值,因为调用方还需要知道“前、同、后”。如果目标是 input 或 textarea 内的选区,应使用控件自己的选择接口;如果 DOM 被框架重渲染,旧节点和旧 offset 也可能失效,不能把一次 Range 比较结果当成长期书签。

写判断代码时的检查清单

  • 先写清楚当前 Range 和 otherRange,不要在调用前后交换变量。
  • 把 how 展开成“当前端点 → 对方端点”,尤其检查 START_TO_END 和 END_TO_START。
  • 比较前确认两个 Range 的节点和 offset 仍然来自有效的 DOM 状态。
  • 需要判断重叠、包含或相邻时,同时检查起点和终点,不用单次返回值替代完整关系判断。

常见问题

返回 0 是不是代表两个 Range 完全相同?

不是。它只代表本次选择的两个边界点相同,例如两个范围的起点相同;终点、包含关系和范围长度仍可能不同。

为什么 END_TO_START 的直觉容易反?

因为 API 的映射固定为当前范围起点对比对方范围终点。把常量名直接当成“当前终点对方起点”会把这一次比较写反,应该以四行对照表为准。

compareBoundaryPoints 能替代重叠检测吗?

不能。它提供端点排序原语;重叠检测还要结合两组起止边界,并考虑范围相邻、包含和折叠等情况。

参考资料:https://developer.mozilla.org/en-US/docs/Web/API/Range/compareBoundaryPoints;方法语义以 DOM Range 规范为准。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
JavaScript Range.createContextualFragment 怎样按上下文解析 HTML 片段JavaScript Range.createContextualFragment 怎样按上下文解析 HTML 片段
上一篇
JavaScript Range.createContextualFragment 怎样按上下文解析 HTML 片段
JavaScript TreeWalker.currentNode 怎样从指定节点继续遍历
下一篇
JavaScript TreeWalker.currentNode 怎样从指定节点继续遍历
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    734次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    736次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    815次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    776次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    611次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码