Skip to content

前端图片加载该用 <img> 还是 new Image()

更新: 6/6/2026 字数: 0 字 时长: 0 分钟

这两者经常被混淆,但用对场景能让页面更流畅、代码更简洁。

板块一:浏览器加载图片的底层机制

要搞懂两者区别,先得明白浏览器是怎么把一张图片「搬」到屏幕上的。整个过程其实分三步:

第一步:发起网络请求 浏览器拿到图片地址(URL)后,向服务器发送一个请求:「请把这张图给我」。这一步走的是网络,耗时取决于图片大小和网速。

第二步:下载图片数据 服务器把图片的二进制数据一点点传回来。此时图片还只是「一堆字节」,并不能直接看。

第三步:解码并渲染 浏览器把下载好的数据解码(把压缩的 JPG/PNG 还原成像素)、计算尺寸,再把它画(渲染)到页面对应位置上。到这一步,用户才真正「看见」图片。

关键认知:下载 ≠ 显示 一张图片可以「已经下载到浏览器里了」,但「还没有显示在页面上」。这两件事是分开的——这正是理解 <img>new Image() 区别的核心。

还有一个隐藏帮手:浏览器缓存 同一张图片第一次加载后,浏览器会把它存进缓存。下次再用到相同 URL 的图片时,就不必重新走网络,直接从缓存里秒取。new Image() 的预加载技巧,本质就是在利用这套缓存机制。

浏览器加载图片的底层机制

板块二:两者的本质差异

这是全篇最关键的一节。一句话概括:

<img> 是「页面上的图片元素」,看得见、会上屏;new Image() 是「内存里的图片对象」,默认看不见、不上屏。

对比维度<img>(HTML 标签)new Image()(JS 创建的对象)
本质写在页面里的真实 DOM 元素JS 在内存中 new 出来的 HTMLImageElement 对象
是否显示在页面上会,默认就显示不会,除非你手动把它 append 到页面
触发图片下载设置 src 后自动下载设置 src 后同样会下载(并写入缓存)
主要用途直接展示图片给用户看后台预先下载、监听加载状态、做逻辑控制
写法<img src="a.jpg">const img = new Image(); img.src = "a.jpg";

补充说明(划重点): 其实 new Image() 创建出来的,和页面里的 <img>同一种东西——都是图片元素对象。区别只在于:<img> 一出生就「站在页面上」,而 new Image() 默认「待在内存里、不露面」。正因为它不上屏,所以特别适合用来「偷偷把图片先下载好」。

img 标签与 new Image() 的本质区别

板块三:什么时候 new Image() 更合适?

new Image() 的杀手锏是「先下载、不显示」。凡是需要提前准备图片、或对加载过程做控制的场景,它都更合适。

1. 图片预加载(最经典用法) 比如轮播图、相册下一张、鼠标悬停才显示的大图。你可以在用户还没看到之前,用 new Image() 把图片悄悄下载进缓存。等真正要显示时,因为缓存已命中,图片瞬间出现、不会白屏闪烁

js
// 预加载下一张图片,提前写入缓存
const img = new Image();
img.src = "next-banner.jpg";

2. 需要监听加载完成 / 失败new Image() 能精确监听 onload(加载成功)和 onerror(加载失败),方便你「加载完再显示」「失败了换备用图」。

js
const img = new Image();
img.onload = () => console.log("图片下载好了,可以显示了");
img.onerror = () => console.log("加载失败,换默认图");
img.src = "photo.jpg";

3. 纯逻辑用途,不需要立刻上屏 比如提前探测某张图能不能正常加载、获取图片真实宽高、做埋点统计等。这些只需要图片「在内存里」,不需要呈现给用户,用 new Image() 最干净。

一句话:「先下后用、要监听、不急着显示」→ 用 new Image()

new Image() 预加载图片场景

板块四:什么时候直接用(甚至只用)<img>

绝大多数日常场景,直接写 <img> 才是正解,不要画蛇添足。

1. 就是要在页面上展示一张图 内容图、头像、Logo、商品图……只要目的是「让用户看到」,直接写 <img> 即可,浏览器会自动下载并显示,简单可靠。

html
<img src="avatar.jpg" alt="用户头像">

2. 想要代码简单、可维护<img> 是声明式写法,HTML 里写清楚就行,不用写一堆 JS 逻辑。能用一行标签解决的,就别用脚本绕弯。

3. 想用浏览器原生的优化能力 现代 <img> 自带很多「免费福利」,直接写属性就能用:

  • loading="lazy"原生懒加载,图片快滚到可视区域时才加载,省流量、提速度,无需任何 JS。
  • srcset / sizes:根据屏幕自动选择合适清晰度的图片。
  • decoding="async":异步解码,避免卡住页面渲染。
html
<img src="banner.jpg" loading="lazy" alt="活动横幅">

重要提醒:别用 new Image() 去做 <img> 本来就能做的事。 很多新手为了「懒加载」手写一堆 new Image() 逻辑,其实现在一个 loading="lazy" 属性就够了,又简单又高效。

一句话:「就是要显示、追求简单、想吃浏览器原生优化」→ 直接用 <img>

直接用 img 标签显示图片

一张表帮你快速决策

你的需求推荐方案
页面上直接展示图片<img>
图片懒加载(滚动到才加载)<img loading="lazy">
提前预加载下一张/即将用到的图new Image()
监听图片加载成功 / 失败new Image() + onload/onerror
探测图片是否可用、获取尺寸等纯逻辑new Image()
兼顾展示 + 加载控制new Image() 预载,再用 <img> 展示

最终心法:默认用 <img>(声明式、简单、有原生优化);当你需要「在显示之前对加载过程做控制」时,才请出 new Image()。两者不是对立,而是分工。

文档已覆盖你要求的全部维度——底层加载机制、本质差异、new Image() 适用场景、<img> 适用场景,并为每个板块配齐了统一卡通科普风、中文内容的配图及可直接复用的生成提示。如果需要,我可以把它整理成排版精美的飞书文档或 HTML 网页,方便沉淀到你的开发学习资料库。