javascript:void(0)与href="#"有什么区别?

一只小鹿
一只小鹿
发布时间:2026-09-18| 14人浏览过
原创

在编写前端页面时,开发者常希望使用超链接标签 <a> 绑定点击事件,却不需要它跳转到新页面。两种最常见的占位写法是 href="#" 和 href="javascript:void(0)"。两者在语义定位、滚动条行为、历史记录管理以及无障碍访问上存在本质差异。

核心结论:一句话看清两者本质

href="#" 是一个锚点定位指令,而 href="javascript:void(0)" 是一个静默执行脚本。

当你点击 href="#" 时,浏览器将其识别为网页内部书签跳转。若 URL 后面没有指定锚点 ID,浏览器会默认定位到文档的最顶端,导致页面视口瞬间向上滚动。而 href="javascript:void(0)" 借助 javascript: 伪协议在当前上下文中计算表达式 void(0),该操作返回 undefined,浏览器接收到无返回值的指令后会保留在当前位置,不执行任何跳转或滚动。

href=# 与 javascript:void(0) 的底层机制对比
图 1:href="#" 与 javascript:void(0) 的底层执行链路与状态变化对比

机制拆解:它们在浏览器内部到底做了什么?

1. href="#" 的行为细节与滚动副作用

HTML 中的 # 代表 URI 片段标识符(Fragment Identifier)。在标准规范中,如果在 # 后面跟具体的名称(例如 href="#profile"),浏览器会自动查找到页面中 id="profile" 的元素,并滚动到该元素所在位置。

当单独写一个 # 而后面没有任何标识时,浏览器的默认规范就是直接跳回当前文档的最顶部(Top of Page)。这往往会导致以下问题:

  • 破坏用户浏览位置: 如果用户已经滚动到长页面的中间或底部,点击一个带有 href="#" 的按钮,页面会瞬间跳回顶部,严重影响操作体验。
  • 污染浏览器历史: 点击一次 #,浏览器的当前地址栏就会多出一个 # 字符,并在 Session History 中新增一条记录。用户点击“后退”按钮时,不会返回上一页,而是撤销这次哈希变化。

2. javascript:void(0) 是什么意思?

这个表达式可以拆分成两部分来理解:

  1. javascript: 伪协议:告诉浏览器将后面的内容当成一段即时 JavaScript 脚本在当前页面上下文中运行。
  2. void 操作符:JavaScript 原生关键字,其作用是对其后的表达式进行求值,并始终返回 undefined。void 0 或 void(0) 运算后的返回值都是严格的 undefined。

根据浏览器对伪协议的规范:如果执行表达式返回了一个非 undefined 的值(例如 javascript:'Hello World'),浏览器会直接用这个返回值替换掉当前整个网页的 HTML 内容。而当表达式返回 undefined 时,浏览器将保持当前页面完全不变。因此,void(0) 成了最安全、最短小的不产生页面变动的表达式。

void 操作符运算求值原理图
图 2:JavaScript void 操作符求值与浏览器页面覆盖保护机制

两者多维度详细对比

为了直观对比两者的差异,下表列出了在日常开发中需要关心的所有关键指标:

对比维度 href="#" href="javascript:void(0)"
页面滚动效果 视口立刻强制滚动到页面顶部。 完全不滚动,保持在当前点击位置。
地址栏变化 URL 末尾追加 #。 地址栏完全不发生任何改变。
历史记录影响 增加一条 Hash 记录,影响后退按钮行为。 不增加任何浏览记录。
安全策略 (CSP) 通常完全不受 CSP 限制。 如果网站启用了严格 CSP,伪协议会被拦截报错。
执行开销 仅为内置定位动作,无 JS 执行上下文开销。 每次点击需要启动 JS 引擎计算并求值。

如何正确阻止跳转?实战代码与迁移步骤

如果你手头已有的项目代码中存在 href="#",可以通过以下具体步骤避免页面乱跳:

步骤一:使用 event.preventDefault() 拦截

当你绑定点击事件时,只要显式调用事件对象的 preventDefault() 方法,就能阻止浏览器的默认锚点跳转和滚动行为:

<!-- 方式 A:在 HTML 属性中直接拦截 -->
<a href="#" onclick="event.preventDefault(); handleAction();">点击操作</a>

<!-- 方式 B:在外部 JS 监听器中拦截(推荐) -->
<a href="#" id="action-btn">点击操作</a>

<script>
  const btn = document.getElementById('action-btn');
  btn.addEventListener('click', function(e) {
    // 阻止 # 带来的向上滚动和 URL 变更
    e.preventDefault();
    console.log('执行实际交互逻辑');
  });
</script>

注意:如果事件监听函数在执行过程中发生未捕获的异常,且该异常发生在 e.preventDefault() 之前,浏览器仍会继续执行默认动作,页面依然会跳回顶部。因此,建议将 e.preventDefault() 写在事件处理逻辑的最前列。

点击事件生命周期与阻止默认行为的执行流程
图 3:a 标签点击事件分发与默认行为拦截步骤

现代前端开发中的最佳实践

既然 href="#" 会带来滚动副作用,而 href="javascript:void(0)" 又存在 CSP 拦截以及语义不规范的问题,那么在现代前端开发中,我们应该怎么做?

原则一:仅仅用于操作交互,改用 <button>

从 HTML 语义学的角度来看:

  • <a> 标签(Anchor)的核心使命是导航:用于在不同的页面、或同一页面的不同部分之间建立超链接跳转。
  • <button> 标签的核心使命是操作:用于打开弹窗、提交表单、切换展开/收起、执行异步请求等。

如果你的元素点击后并不涉及 URL 跳转,纯粹是触发一段业务代码,那么在语义上它就是一个按钮,而不是链接。使用 <button type="button"> 具备极佳的屏幕阅读器可访问性(Accessibility),还能天然获得键盘回车(Enter)和空格键(Space)的触发支持。

<!-- 推荐:使用样式重置后的原生 button -->
<button type="button" class="btn-link" onclick="openModal()">打开弹窗</button>

<style>
  /* 将按钮重置为类似超链接的外观 */
  .btn-link {
    background: none;
    border: none;
    padding: 0;
    color: #6B88A6;
    font: inherit;
    cursor: pointer;
    text-decoration: underline;
  }
</style>
技术选型与场景决策总结流程
图 4:交互元素选型与场景决策总结

原则二:必须保留 <a> 时,首选 href="#" 搭配拦截

如果由于既有第三方 UI 框架、样式库强制依赖 a 标签选择器,必须保留 <a>:

  • 优选方案:使用 href="#" 并在 JS 中第一时间调用 e.preventDefault()。这种写法符合 W3C 规范,即使在最严格的 CSP 策略下也能正常工作。
  • 兼容性权衡:在极简的小型内部管理后台或早期的无构建项目中,href="javascript:void(0)" 省去了手写拦截事件的代码,能保证即使没有阻止默认事件页面也不滚动,但需要确保页面没有配置限制内联脚本的 CSP 头。

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。